how to place UILabel behind SKSpriteNode - ios

i am trying to place a UILabel behind a SKSpriteNode. but what ever i try the label stays in front of the SpriteNode. z-index doesn't work and .movetoback also doesn't work.
could someone explain me how to do this?

You can add UILabel as a subview of SKView and adjust its position accordingly.
E.g. the following creates a white square sprite with an UILabel in front of it:
scene = SKScene(size: spriteView.bounds.size)
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
let sprite = SKSpriteNode(
color: SKColor.whiteColor(),
size: CGSize(width: 100, height: 100)
)
scene.addChild(sprite)
spriteView.presentScene(scene)
let frame = CGRect(
x: spriteView.bounds.midX - 50,
y: spriteView.bounds.midY - 50,
width: 100,
height: 100)
label = UILabel(frame: frame)
label.textAlignment = .Center
label.text = "Ook"
spriteView.addSubview(label)
P.S. I can not understand why would you want to use UILabel while SpriteKit has SKLabelNode which does practically the same but can be a part of the scene, so that will make your life easier in terms of adjusting positions.

Related

How do I constrain an SKShapeNode to the device edges in SpriteKit?

Just to test things out I have created a blue square and placed it at the center of the screen like this:
let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
mySquare.fillColor = SKColor.blue
mySquare.lineWidth = 1
let myPoint = CGPoint(x: UIScreen.main.nativeBounds.midX, y: UIScreen.main.nativeBounds.midY)
mySquare.position.x = 0
mySquare.position.y = 0
self.addChild(mySquare)
Works great. Now, I would like to use constraints and set up the square constraints to the edges of the device screen. I have tried this, but the blue square doesn't appear, so I think I have the wrong idea on how to capture the CGPoint of the screen edges.
let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
mySquare.fillColor = SKColor.blue
mySquare.lineWidth = 1
let myPoint = CGPoint(x: UIScreen.main.nativeBounds.maxX, y: UIScreen.main.nativeBounds.maxY)
let range = SKRange(lowerLimit: 10.0, upperLimit: 10.0)
let myConstraints = SKConstraint.distance(range, to: myPoint)
mySquare.constraints = [myConstraints]
self.addChild(mySquare)
How do I capture the screen edges and constrain the square to those?
SKConstraint doesn't work equally as UIKit Constraints.
SKConstraint functionality is really specific:
Please take a look here: https://developer.apple.com/documentation/spritekit/skconstraint
Anyway, can give you some recommendations:
Transform screen position to scene position:
self.view?.convert(myPoint, to: self)
You can start with this example and get node on a corner
let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
mySquare.fillColor = SKColor.blue
mySquare.lineWidth = 1
let myScreenPoint = CGPoint(x: UIScreen.main.bounds.maxX, y: UIScreen.main.bounds.maxY)
if let myScenePoint = self.view?.convert(myScreenPoint, to: self) {
mySquare.position = myScenePoint
}
self.addChild(mySquare)
With this logic, you can get each side of the screen and decrease or increase margin and make each 4 sides; or 1 constraint for the center.

How to create a ruler / scale slider with Swift 3?

I'm trying to recreate a temperature ruler similar to the Coinbase app for an app in Swift 3. Unfortunately, I'm not sure if I follow the right approach.
In my current experiment, I used a UIScrollView element and placed / drawn lines at a certain distance (with a loop and UIBezierPath). In the next step I want to read the user input. With the current approach I have to use the X-position of the UIScrollView to convert things to read the current temperature. That seems to me a relatively inaccurate thing to be? My result looks like this.
// UI SCROLL VIEW
var scrollView: UIScrollView!
scrollView = UIScrollView(frame: CGRect(x: 0, y: 120, width: 400, height: 100))
scrollView.contentSize = CGSize(width: 2000, height: 100)
scrollView.showsHorizontalScrollIndicator = false
let minTemp = 0.0
let maxTemp = 36.8
let interval = 0.1
// LINES
let lines = UIBezierPath()
// DRAW TEMP OTHER LINES
for temp in stride(from: minTemp, to: maxTemp, by: interval)
{
let isInteger = floor(temp) == temp
let height = (isInteger) ? 20.0 : 10.0
let oneLine = UIBezierPath()
oneLine.move(to: CGPoint(x: temp*50, y: 0))
oneLine.addLine(to: CGPoint(x: temp*50, y: height))
lines.append(oneLine)
// INDICATOR TEXT
if(isInteger)
{
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 40, height: 21))
label.center = CGPoint(x: temp*50, y: height+15)
label.font = UIFont(name: "HelveticaNeue",
size: 10.0)
label.textAlignment = .center
label.text = "\(temp) °C"
scrollView.addSubview(label)
}
}
// DESIGN LINES IN LAYER
let shapeLayer = CAShapeLayer()
shapeLayer.path = lines.cgPath
shapeLayer.strokeColor = UIColor.black.cgColor
shapeLayer.lineWidth = 1
// ADD LINES IN LAYER
scrollView.layer.addSublayer(shapeLayer)
view.addSubview(scrollView)
self.view = view
The Coinbase app also struck me that there is some kind of adaptive feedback (at least on the iPhone X) when I move the slider. The iPhone vibrates easily when you come across a line, similar to the UIPickerView. I do not have that with my approach and I strongly doubt that the developer has programmed it in manually on Coinbase... So maybe there's a smarter, more up-to-date approach to how to recreate such a ruler natively in Swift?
you can using this pod
this will allow you to using that as horizontal or vertical
https://github.com/farshidce/RKMultiUnitRuler

Add a complex boarder to UIImageView

How do I add boarder like in the below image (in Objective-C ) to UIImageView. I tried using UIBezierPath but wasn't successful.
Create a UIView (square in dimensions), add corner radius = 1/2 times its side.
Now add the UIImageView as a subview to this UIView.
As the image is circular in shape, so a simpler appraoch to the solution to your problem is to add corner radius to your UIVIew.
Below is the code I used:
let circleView: UIView = UIView(frame: CGRect(x: 0,
y: 0,
width: 100,
height: 100))
circleView.center = view.center
circleView.backgroundColor = .lightGray
circleView.layer.cornerRadius = 50
view.addSubview(circleView)
let imageView: UIImageView = UIImageView(frame: CGRect(x: 0,
y: 0,
width: 100,
height: 100))
imageView.image = UIImage(named: "F8FIs.png")
circleView.addSubview(imageView)
Please note that I added lightGray color to circle view for clarity.
And here is the screenshot of how it looks:

Stop affine transform from applying on subview

I have a UIView that holds a UILabel inside.
After applying affine transform on the UIView using:
myView.transform = CGAffineTransformMakeScale(4, 4);
My UILabel (which is a sub view to myView) grows as well.
Is there a way to prevent this?
i tried:
1) Using the CGAffineTransformIdentity flag on the label.
2) Adding a superview to myView and adding myView as superview's subview, and the label as a subview to the superview (and not myView).
Non of them seem to be working, the label keeps growing.
Any ideas?
You answered your own question with option 2. Not sure why it's not working since you did not supply any code. The playground code below shows it will work. Uncomment out the last line to transform the subview but not the label.
import UIKit
import XCPlayground
let superview = UIView(frame: CGRect(x: 10, y: 10, width: 200, height: 200))
XCPlaygroundPage.currentPage.liveView = superview
superview.backgroundColor = UIColor.redColor()
let view = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100))
view.backgroundColor = UIColor.greenColor()
superview.addSubview(view)
let label = UILabel(frame: CGRect(x: 20, y: 10, width: 40, height: 40))
label.text = "Hello"
superview.addSubview(label)
//view.transform = CGAffineTransformMakeScale(2, 2)

How do I add a UIview to an imageView while ensuring that the contents of the UIView are inside the it's frame?

I have a superview which contains a ImageView, a testView, and some buttons. I created a UIView which contains ImageView2 and a removebutton.
When I add UIView to UIImageView, the contents of UIView are not in the frame of UIView. Because of that, I cannot apply pan gesture recognizer.
I have tried to apply constraints and to change the frame and centre of ImageView2.
Below is the code I am using to create the above mentioned UIView. How do I ensure that the contents of the UIView are visible in the frame of the UIView?
let rect = CGRect(x: self.imageView.center.x-30, y: self.imageView.center.y-30, width: 80, height: 80)
testview = UIView(frame: rect)
testview.layer.cornerRadius = testview.frame.width/2
testview.backgroundColor = UIColor.blackColor()
testview.clipsToBounds = true
imageView2 = UIImageView(frame: CGRect(x: testview.frame.minX+10, y: testview.frame.minY+10, width: 60, height: 60))
let rect2 = CGRect(x: self.testview.frame.maxX-17, y: self.testview.frame.minY, width: 20, height: 20)
removeButton = UIButton(frame: rect2)
removeButton.layer.cornerRadius = removeButton.frame.width/2
removeButton.backgroundColor = UIColor.blackColor()
removeButton.clipsToBounds = true
imageView2.layer.cornerRadius = imageView2.frame.width/2
imageView2.userInteractionEnabled = true
imageView2.clipsToBounds = true
testview.alpha = 0.3
imageView2.center = testview.center
imageView2.center = testview.center
testview.addSubview(imageView2)
testview.addSubview(removeButton)
testview.bringSubviewToFront(imageView2)
imageView.addSubview(testview)
The problem is that lines like this do not do what you think:
let rect = CGRect(x: self.imageView.center.x-30, y: self.imageView.center.y-30, width: 80, height: 80)
// ... and ...
imageView2.center = testview.center
The center of a view is in its frame coordinates - it has to do with how the view is placed in its superview. But the position of a subview must be described in terms of its superviews bounds, not its frame. Its bounds are its internal coordinates, which is what you want.
Let's take the simplest case: how to center a subview in a superview. This is not the way:
imageView2.center = testview.center
You see the problem? testview.center is where testview is located in its superview; it is not the internal center of testview, which is what you want. The internal center of testview comes from its bounds. This is the way:
let c = CGPointMake(testview.bounds.midX, testview.bounds.midY)
imageView2.center = c

Resources