Placing UILabel in the center of screen - swift

I have a UILabel which I want to be displayed at the center of screen regardless of which iPhone it is played on!
But I can't get it right! It's always somewhere else but not in the middle.
what am i doing wrong?
Here is the picture and code of what is happening!
class end: SKScene {
var label = UILabel()
override func didMoveToView(view: SKView) {
scene?.backgroundColor = UIColor(red: CGFloat(59.0/255.0), green: CGFloat(89.0/255.0), blue: CGFloat(152.0/255.0), alpha: CGFloat(1.0))
let w = UIScreen.mainScreen().bounds.width
let h = UIScreen.mainScreen().bounds.height
label = UILabel(frame: CGRect(x: w / 2, y: h / 2, width: 120, height: 30))
label.text = "REPLAY"
label.center = CGPoint(x: w / 2, y: 2)
label.textColor = UIColor.whiteColor()
self.view?.addSubview(label)

I think your label actually is centered.
If I add a red background color like so:
label.backgroundColor = UIColor.redColor()
and change the vertical center to be the center of the screen, that is, changes this line in your example:
label.center = CGPoint(x: w / 2, y: 2)
to this:
label.center = CGPoint(x: w / 2, y: h / 2)
I end up with this:
So, the label actually is centered. The text however, is not centered in the label, which makes it seems as if the text is not centered when you have no background color.
If I change the textAlignment to .Center and remove the background color again I end up with this result:
The final code example looks like this:
override func didMoveToView(view: SKView) {
scene?.backgroundColor = UIColor(red: CGFloat(59.0/255.0), green: CGFloat(89.0/255.0), blue: CGFloat(152.0/255.0), alpha: CGFloat(1.0))
let w = UIScreen.mainScreen().bounds.width
let h = UIScreen.mainScreen().bounds.height
label = UILabel(frame: CGRect(x: w / 2, y: h / 2, width: 120, height: 30))
label.text = "REPLAY"
label.center = CGPoint(x: w / 2, y: h / 2)
label.textAlignment = .Center
label.textColor = UIColor.whiteColor()
self.view?.addSubview(label)
}
And when all that is said, then maybe you should look into the SKLabelNode as #whirlwind suggests in the comment, that way your label becomes an integrated part of the SKScene and not something that is bolted to the outer UIView (if that makes any sense to you).
Hope this helps you.

Best option is going for autolayout. You can set it vertically and horizontally aligned to view. Regardless of display or orientation it works.
You can use either interface builder or you can add autolayoutconstraints

The easiest way would be to use:
label.center = view.center

Related

Add a text above the triangle CAShapeLayer

I use this function to draw an triangle
func drawTriangle(size: CGFloat, x: CGFloat, y: CGFloat, up:Bool) {
let triangleLayer = CAShapeLayer()
let trianglePath = UIBezierPath()
trianglePath.move(to: .zero)
trianglePath.addLine(to: CGPoint(x: -size, y: up ? size : -size))
trianglePath.addLine(to: CGPoint(x: size, y: up ? size : -size))
trianglePath.close()
triangleLayer.path = trianglePath.cgPath
triangleLayer.fillColor = UIColor.white.cgColor
triangleLayer.anchorPoint = .zero
triangleLayer.position = CGPoint(x: x, y: y)
triangleLayer.name = "triangle"
layer.addSublayer(triangleLayer)
}
and call it:
drawTriangle(size: 10, x: frame.minX + 45, y: 40, up: false)
How I can modify this function to add a text/ label above or under this triangle by using same x and y coordinate.
Thank you so much for your help.
To add a label below the triangle you just need to create it at zero origin with zero size, choose the font size, set the text alignment to center and call sizeToFit. Then all you need to do is set the center of the label at the same point you have passed to the drawTriangle method but adding half of the label's height to the y value. To add it above the triangle you would need to subtract. half of the label's height and the size of the triangle.
let x = view.frame.minX + 45
let y: CGFloat = 40
drawTriangle(size: 10, x: x, y: y, up: false)
let label = UILabel(frame: .init(origin: .zero, size: .zero))
label.font = .systemFont(ofSize: 10)
label.textColor = .white
label.text = "StackOverFlow"
label.backgroundColor = .red
label.textAlignment = .center
label.sizeToFit()
let labelHalfHeight = label.frame.height/2
label.center = .init(x: x, y: y + labelHalfHeight)
view.backgroundColor = .blue
view.addSubview(label)

How to fill out an SKLabelNode with a specific color through animation?

I've been searching the internet for a while now and I couldn't come up with any solution.
I've created a SKLabelNode in my SpriteKit project which displays level numbers.
SKLabelNode:
let levelLbl = SKLabelNode(fontNamed: "LEMON-Bold")
levelLbl.text = "1"
levelLbl.fontSize = 100
levelLbl.fontColor = .grey
levelLbl.zPosition = 2
levelLbl.horizontalAlignmentMode = .center
levelLbl.verticalAlignmentMode = .center
levelLbl.position = CGPoint(x: frame.midX, y: frame.height * 0.75)
addChild(levelLbl)
Screenshot:
Screenshot of my label
I want to fill up the number of my label smoothly with white color from the bottom to the top with an animation so that after x seconds the label is completely white.
I don't want the color to fade in but rather to be filled up similar to a cup of water.
It would be amazing if someone could help me out here!
This is how far I came by using a SKCropNode. My problem is I don't know why I don't see an animation:
func labelAnimation() {
let levelLbl = SKLabelNode(fontNamed: "LEMON-Bold")
let blackRect = SKShapeNode(rectOf: CGSize(width: levelLbl.frame.width, height: levelLbl.frame.height))
blackRect.fillColor = .grey
blackRect.strokeColor = .grey
blackRect.position = CGPoint(x: 0, y: levelLbl.frame.height / 2)
let whiteRect = SKShapeNode(rectOf: CGSize(width: levelLbl.frame.width, height: levelLbl.frame.height))
whiteRect.fillColor = .white
whiteRect.strokeColor = .white
whiteRect.position = CGPoint(x: 0, y: -levelLbl.frame.height / 2)
//Level Node
levelNode.position = CGPoint(x: 0, y: 0)
levelNode.addChild(blackRect)
levelNode.addChild(whiteRect)
//Mask Node
levelLbl.text = "\(levelNr)"
levelLbl.fontSize = 100
levelLbl.horizontalAlignmentMode = .center
levelLbl.verticalAlignmentMode = .center
//Crop Node
cropNode.addChild(levelNode)
cropNode.maskNode = levelLbl
cropNode.position = CGPoint(x: frame.midX, y: frame.midY)
cropNode.zPosition = 5
addChild(cropNode)
//action
let movelevelNode = SKAction.move(to: CGPoint(x: 0, y: frame.height / 3), duration: 8)
levelNode.run(movelevelNode)
}

How to change view for label

I have a UILabel and I want to change its background view. Somebody advised me to use bezier but I want a simple variant.
My label:
What it should look like:
Since these are not very complex shapes, I would suggest creating two white UIViews, rotating them 45 degrees and then adding them as subviews to the UILabel. The code would look something like this:
myLabel.clipsToBounds = true
// create the triangle on the left side of the label
let leftSquare = UIView(frame: CGRect(x: myLabel.frame.height / -2, y: 0, width: myLabel.frame.height, height: myLabel.frame.height))
leftSquare.translatesAutoresizingMaskIntoConstraints = true
leftSquare.isUserInteractionEnabled = false
leftSquare.backgroundColor = UIColor.white
leftSquare.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi / 4)) // 45 degree rotation
// create the triangle on the right side of the cell
let rightSquare = UIView(frame: CGRect(x: myLabel.bounds.width - (myLabel.frame.height / 2), y: 0, width: myLabel.frame.height, height: myLabel.frame.height))
rightSquare.translatesAutoresizingMaskIntoConstraints = true
rightSquare.isUserInteractionEnabled = false
rightSquare.backgroundColor = UIColor.white
rightSquare.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi / 4))
// add squares to label
myLabel.addSubview(leftSquare)
myLabel.addSubview(rightSquare)
myLabel.sendSubview(toBack: leftSquare)
myLabel.sendSubview(toBack: rightSquare)

Drawing a simple line chart using Swift

I am writing a Swift program using Xcode 9.2 for the MacOS with the objecting of displaying a simple line chart with three points.
The program's objective is to create a line graph using apple's core graphics. It is a horizontal line graph with three points, one at the center and at each end. If the mouse pointer is over the center point I want some text to display like "xyz" and when the mouse moves away the text would disappear. The end points will have labels containing numbers but for now let's call them "min" and "max".
Using XCode's playground, so far I have managed to accomplish to display a very clunky line graph using the following code:
class MyView : NSView {
override func draw(_ rect: NSRect) {
NSColor.green.setFill()
var path = NSBezierPath(rect: self.bounds)
path.fill()
let leftDot = NSRect(x: 0, y: 0, width: 10, height: 20)
path = NSBezierPath(ovalIn: leftDot)
NSColor.black.setFill()
path.fill()
let rightDot = NSRect(x: 90, y: 0, width: 10, height: 20)
path = NSBezierPath(ovalIn: rightDot)
NSColor.black.setFill()
path.fill()
let centerDot = NSRect(x: 50, y: 0, width: 10, height: 20)
path = NSBezierPath(ovalIn: centerDot)
NSColor.black.setFill()
path.fill()
}
}
let viewRect = NSRect(x: 0, y: 0, width: 100, height: 10)
let myEmptyView = MyView(frame: viewRect)
The code produces a clunky looking line graph as follows:
The chart below is from Excel and this line chart is much cleaner and is what I am looking for but I want the line to be horizontal instead of diagonal.
Thanks in advance for your help.
To draw a horizontal line similar to the sample image you provided, I took your sample code and modified it. This would give this result:
The code would look like this then:
override func draw(_ rect: NSRect) {
NSColor(red: 103/255, green: 146/255, blue: 195/255, alpha: 1).set()
let line = NSBezierPath()
line.move(to: NSMakePoint(10, 5))
line.line(to: NSMakePoint(90, 5))
line.lineWidth = 2
line.stroke()
NSColor(red: 163/255, green: 189/255, blue: 218/255, alpha: 1).setFill()
let origins = [NSPoint(x: 10, y: 1),
NSPoint(x: 50, y: 1),
NSPoint(x: 90, y: 1)]
let size = NSSize(width: 8, height: 8)
for origin in origins {
let quad = NSBezierPath(roundedRect: NSRect(origin: origin, size: size), xRadius: 2, yRadius: 2)
quad.fill()
quad.stroke()
}
}
Update for iOS
Due to a request in the comments section here the iOS variant:
override func draw(_ rect: CGRect) {
UIColor(red: 103/255, green: 146/255, blue: 195/255, alpha: 1).set()
let line = UIBezierPath()
line.move(to: CGPoint(x: 10, y:5))
line.addLine(to: CGPoint(x: 90, y:5))
line.lineWidth = 2
line.stroke()
UIColor(red: 163/255, green: 189/255, blue: 218/255, alpha: 1).setFill()
let origins = [CGPoint(x: 10, y: 1),
CGPoint(x: 50, y: 1),
CGPoint(x: 90, y: 1)]
let size = CGSize(width: 8, height: 8)
for origin in origins {
let quad = UIBezierPath.init(roundedRect: CGRect(origin: origin, size: size), cornerRadius: 2)
quad.fill()
quad.stroke()
}
}
Alternatively, you could add a CAShapeLayer sublayer whose path property is a UIBezierPath to the UIView.

Shadow left and right of UIView

Hi i like to add an CALayer Shadow to an View where the shadow was left and right of the view the simplest way was:
someView.layer.shadowColor = [[UIColor blackColor] CGColor];
someView.layer.shadowOffset = CGSizeMake(0.0f,0.0f);
someView.layer.shadowOpacity = 1.0f;
someView.layer.shadowRadius = 10.0f;
someView.layer.shadowPath = [[UIBezierPath bezierPathWithRect:someView.bounds] CGPath];
but i will add a bigger shadow as like a shadow when i increase the shadowRadius it do not look good. How i can make a shadow that looks good at left and right.
I think 10 is a pretty big shadow radius, try 3 or 4 instead, also opacity I usually use 0.7:
someView.layer.shadowColor = [[UIColor blackColor] CGColor];
someView.layer.shadowOffset = CGSizeMake(0.0f,0.0f);
someView.layer.shadowOpacity = 0.7f;
someView.layer.shadowRadius = 4.0f;
If you want the shadow only on left and right, then inset the rectangle on the top and bottom so the top and bottom shadow are hidden behind your view:
CGRect shadowRect = CGRectInset(someView.bounds, 0, 4); // inset top/bottom
someView.layer.shadowPath = [[UIBezierPath bezierPathWithRect:shadowRect] CGPath];
I'm not really sure if that's what you wanted.
swift 3.0 version
imageView.layer.shadowOpacity = 0.8
imageView.layer.shadowOffset = CGSize(width: 0, height: 3)
imageView.layer.shadowRadius = 4.0
let shadowRect: CGRect = imageView.bounds.insetBy(dx: 0, dy: 4)
imageView.layer.shadowPath = UIBezierPath(rect: shadowRect).cgPath
progrmr's answer was very helpful, cheers!
I made a slide-out menu and I had a problem with the shadow surrounding my VC and disrupting the navigation bar. Turned out I had to inset the shadow layer.
Here's my solution using swift:
rightViewController!.view.layer.shadowOpacity = 0.8
rightViewController!.view.layer.shadowOffset = CGSizeMake(0, 3)
rightViewController!.view.layer.shadowRadius = 4.0
let shadowRect: CGRect = CGRectInset(rightViewController!.view.bounds, 0, 4); // inset top/bottom
rightViewController!.view.layer.shadowPath = UIBezierPath(rect: shadowRect).CGPath
I created a shadow that can be used at the top/bottom or left/right, without prejudice at all. No shadow will appear in the left/right if you choose top/bottom, and so on. I hope I helped. Here's the code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let imgView = UIImageView(frame: CGRect(x: self.view.bounds.midX - 150, y: self.view.bounds.midY - 150, width: 300, height: 300))
imgView.contentMode = .scaleToFill
imgView.image = UIImage(named: "name image")
self.view.addSubview(imgView)
//You can put left/right or top/bottom
imgView.addShadow(sides: .leftRight, constant: 10, alpha: 5)
}
}
extension UIView{
func addShadow(sides: Sides, constant: Int, alpha: Int){
if(constant > 0 && alpha > 0){
switch sides {
case .leftRight:
let view = UIView(frame: CGRect(x: -CGFloat(constant), y: 0, width: self.bounds.width + CGFloat((constant * 2)), height: self.bounds.height))
self.addSubview(view)
addMask(sides: .leftRight, view: view, constant: constant, shadowRadius: alpha)
case .topBottom:
let view = UIView(frame: CGRect(x: 0, y: -CGFloat(constant), width: self.bounds.width , height: self.bounds.height + CGFloat(constant * 2)))
self.addSubview(view)
addMask(sides: .topBottom, view: view, constant: constant, shadowRadius: alpha)
}
}
}
private func addMask(sides:Sides, view: UIView, constant: Int, shadowRadius:Int){
let mutablePath = CGMutablePath()
let mask = CAShapeLayer()
switch sides {
case .leftRight:
mutablePath.addRect(CGRect(x: -CGFloat(constant), y: 0, width: view.bounds.width, height: view.bounds.height))
mutablePath.addRect(CGRect(x: CGFloat(constant) , y: 0, width: view.bounds.width , height: view.bounds.height))
case .topBottom:
mutablePath.addRect(CGRect(x: 0, y: -CGFloat(constant), width: view.bounds.width, height: view.bounds.height))
mutablePath.addRect(CGRect(x: 0, y: CGFloat(constant) , width: view.bounds.width , height: view.bounds.height))
}
mask.path = mutablePath
mask.fillRule = CAShapeLayerFillRule.evenOdd
mask.fillColor = UIColor(white:1.0, alpha: 0.2).cgColor
view.layer.mask = mask
view.layer.addSublayer(mask)
mask.shadowColor = UIColor.black.cgColor
mask.shadowRadius = CGFloat(shadowRadius)
mask.shadowOpacity = 1.0
mask.shadowOffset = CGSize(width: 0, height: 0)
}
}
enum Sides{
case leftRight
case topBottom
}
You just need to call the extension UIView, which has the addShadow() function and pass the parameters you want.