How to position an SKLabelNode on top of a UISlider in SpriteKit - sprite-kit

I'm using UISliders in my SpriteKit game.
Sometimes I want to pause the game and add some info in an SKLabelNode but I can't find a way to position the SKLabelNode on top of a UISlider.
Here's a simplified example.
override func didMove(to view: SKView) {
let slider = UISlider(frame: CGRect(x: 100, y: 100, width: 300, height: 50))
let label = SKLabelNode(text: "Text Label should be on top of Slider")
label.fontColor = .red
label.verticalAlignmentMode = .top
label.position = CGPoint(x:160, y:self.frame.size.height - 110)
view.addSubview(slider)
self.addChild(label)
slider.layer.zPosition = 1
label.zPosition = 2
}
UISlider remains above SKLabel :-(.
Any help appreciated.
EDIT:
In response to question by #Muffinman2497 "Why not use a UILabel?"
I may have to do that but I'm actually using a custom multi line label that's been designed using spriteKit and SKLabels. So I was hoping for a simple property change rather than a redesign.
Using a UILabel definitely does work though.
let myUILabel = UILabel(frame: CGRect(x: 50, y: 0, width: 300, height: 50))
myUILabel.text = "UILabel would like to obscure UISlider"
myUILabel.backgroundColor = .red
slider.addSubview(myUILabel)
slider.layer.zPosition = 1
myUILabel.layer.zPosition = 2

Related

How to order views' layers on top of each others in Swift

I added the redView as a subView of the textField and used AutoLayout to constraint it to be as it appears in the image, but the problem here now is
I want to bring the red view to be on top of the border
I tried to use this method
bringSubviewToFront(floatingPlaceholderContainer)
but it didn't work, also tried to use the layer.zPosition = .greatestFiniteMagnitude and it also didn't work
Edit-
the code I used and didn't work as I expected
override func layoutSubviews() {
super.layoutSubviews()
self.redlayer.backgroundColor = UIColor.red.cgColor
self.redlayer.frame = CGRect(x: 10, y: -10, width: 100, height: 30)
self.layer.addSublayer(self.redlayer)
self.redlayer.zPosition = 10
}
and this is the result
You need to configure the timing of when you're adding this layer. This approach works fine for me:
class MyTextField : UITextField {
let redlayer = CALayer()
override func layoutSubviews() {
super.layoutSubviews()
self.redlayer.backgroundColor = UIColor.red.cgColor
self.redlayer.frame = CGRect(x: 10, y: -10, width: 100, height: 30)
self.layer.addSublayer(self.redlayer)
self.redlayer.zPosition = 10
}
}

Why is CALayer not being added to UITextView

I have a text view and I am attempting to add a line underneath it. I am trying to accomplish this with a CALayer, however it is not showing up in the textView. I would appreciate it if someone could help me. The code is below.
let border = CALayer()
border.backgroundColor = UIColor(hexString: "#CC0000").cgColor
border.frame = CGRect(x: 0, y: messageField.frame.height - 3, width: messageField.frame.width, height: 3)
messageField.layer.addSublayer(border)
In my test app, I just tried this:
let messageField = UITextView(frame: CGRect(x: 30, y: 40, width: view.frame.width - 60, height: 40))
var border = CALayer()
border.backgroundColor = UIColor.red.cgColor
border.frame = CGRect(x: 0, y: messageField.frame.height - 3, width: messageField.frame.width, height: 3)
messageField.layer.addSublayer(border)
view.addSubview(messageField)
And it worked fine. Weird but fine. The color showed up no problem, but it scrolls along with the text view. But that might be what you want. I tried it with different heights for the message field too. I couldn't get it to not show.
If you want it to work and have the line not scroll with the text, try this answer: https://stackoverflow.com/a/38327895/793607

Swift: Constrain object to and point within a circular NSLayoutConstraint? Circle anchor?

Within a view controller, I have a UIView (backgroundCircle) and a UILabel. The UILabel is moving based on motionManager.startAccelerometerUpdates data. Using this data, I am animating the label.center point. However, I want to bound the movement so that it only moves within a circular area around its starting point (as if it was on a leash from the starting point). Is this possible? Sample code below if it helps.
//objects called during set up
let backgroundCircle = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
backgroundCircle.layer.cornerRadius = circle.frame.width / 2
backgroundCircle.backgroundColor = .clear
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
label.text = "Hello"
//this is called in a separate function, continuously
label.center = newCenter
I'd try using UIKit Dynamics, especially UICollisionBehavior which allows to define collision boundaries with bezier paths.

UIView Orientation change in Swift

I'm developing an app to display a binary tree.
Each node will be displayed as a subview programatically generated from the ViewController - I run the following from viewDidLayoutSubviews().
let theView = BinaryTreeView(frame: CGRect(x: 0, y: 50, width: width, height: 100))
// let theView = BinaryTreeView(s: "I'm testing")
theView.backgroundColor = .white
theView.addGestureRecognizer(UIPinchGestureRecognizer(target:theView, action:#selector(BinaryTreeView.changeScale(recognizer:))))
self.view.addSubview(theView)
theView.eyesOpen = false
let secondView = BinaryTreeView(frame: CGRect(x: width/2, y: 150, width: width/2, height: 100))
// let theView = BinaryTreeView(s: "I'm testing")
secondView.backgroundColor = .white
secondView.addGestureRecognizer(UIPinchGestureRecognizer(target:secondView, action:#selector(BinaryTreeView.changeScale(recognizer:))))
self.view.addSubview(secondView)
let thirdView = BinaryTreeView(frame: CGRect(x: (width/2)+width/4, y: 250, width: width/4, height: 100))
// let theView = BinaryTreeView(s: "I'm testing")
thirdView.backgroundColor = .white
thirdView.addGestureRecognizer(UIPinchGestureRecognizer(target:thirdView, action:#selector(BinaryTreeView.changeScale(recognizer:))))
self.view.addSubview(thirdView)
The issue is that on orientation change the views repeat each other (above there are three nodes, on orientation change 4 might display.
I looked through Stack and Within my subclassed UIView I added:
self.contentMode = UIViewContentMode.redraw
Within the programatic Subview but the same happens.
Don't worry - I'm going to generate my nodes in a loop later (I'm trying to understand how layout works). Incidentally I found the same happened using a UICollectionView so I seem to be doing something fundamentally wrong.
Change the "target:" to the controller (to self) for all three. Your controller will respond to gestures, not the views themselves. The target will be the same in all three cases.
secondView.addGestureRecognizer(UIPinchGestureRecognizer(target:secondView, action:#selector(BinaryTreeView.changeScale)))
self.view.addSubview(secondView)
becomes
secondView.addGestureRecognizer(UIPinchGestureRecognizer(target:self, action:#selector(BinaryTreeView.changeScale)))
self.view.addSubview(secondView)

Couldn't add NSButton to the Sprite-Kit scene

I'm a newbie to OS X programming. I'm building a simple game for Mac with Sprite-Kit, and stuck with the problem of adding NSButton (and other NSObjects) to the view. It just doesn't work - no button shows up.
My code:
class LaunchScene: SKScene {
override func didMoveToView(view: SKView) {
let background = SKSpriteNode(imageNamed: "Wall")
background.size = CGSize(width: 1600, height: 1200)
background.position = CGPoint(x: CGRectGetMidX(self.frame),
y: CGRectGetMidY(self.frame))
self.addChild(background)
let button = NSButton(frame: NSRect(x: self.frame.width/2,
y: self.frame.height/2, width: 50, height: 25))
self.view!.addSubview(button) //button doesn't show up
How could I fix it?
P.S. I tried to add a layer to my view, as some bloggers recommended, in this situation the button actually does show up but the screen turns completely black or renders only glitches.
let layer = CALayer()
self.view!.layer = layer
self.view!.wantsLayer = true
OK, finally I figured out how to do that (don't need to assign a layer to your view if self.view!.wantsLayer is equal to "true"):
class LaunchScene: SKScene {
override func didMoveToView(view: SKView) {
let background = SKSpriteNode(imageNamed: "Wall")
background.size = CGSize(width: 1600, height: 1200)
background.position = CGPoint(x: CGRectGetMidX(self.frame),
y: CGRectGetMidY(self.frame))
self.addChild(background)
self.view!.wantsLayer = true
let button = NSButton(frame: NSRect(x: self.frame.width/2,
y: self.frame.height/2, width: 50, height: 25))
self.view!.addSubview(button)