iOS Swift Why can't height of UILabel text be made bigger? - ios

I want the UILabel text to be larger, but when I change value_row_height, there is no change in size.
var value_row_x = 30
var value_row_y = 100
var value_row_height = 320
var value_row_width = 30
let heart_rate_title_UILabel = UILabel(frame: CGRect(x: value_row_x, y: value_row_y, width: value_row_width, height: value_row_height ))
heart_rate_title_UILabel.center = CGPoint( x: value_row_x + value_row_width / 2, y: value_row_y + value_row_height/2 )
heart_rate_title_UILabel.textAlignment = .left
heart_rate_title_UILabel.text = "heart: "
heart_rate_title_UILabel.sizeToFit()
self.view.addSubview( heart_rate_title_UILabel)
UPDATE:
I added following code, but size failed to change...
heart_rate_title_UILabel.font = label.font.withSize(20)
heart_rate_title_UILabel.minimumScaleFactor = 0.1 //or whatever suits your need
heart_rate_title_UILabel.adjustsFontSizeToFitWidth = true
heart_rate_title_UILabel.lineBreakMode = .byClipping
heart_rate_title_UILabel.numberOfLines = 0

You are changing the physical height of the label. You are not saying anything about what the text size should be. Text size is a matter of setting the label's font (which includes size).

This worked jim-dandy....
value_row_y -= 10
value_row_x += 45 + inter_value_gap_pix // + width of heart rate value
let title_UILabel = UILabel(frame: CGRect(x: value_row_x, y: value_row_y, width: value_row_width, height: value_row_height ))
title_UILabel.center = CGPoint( x: value_row_x + value_row_width / 2, y: value_row_y + value_row_height/2 )
title_UILabel.textAlignment = .left
title_UILabel.text = " RSP: "
self.view.addSubview( title_UILabel)
// set font height to biggest (ie. label height)...
title_UILabel.numberOfLines = 1;
title_UILabel.font = title_UILabel.font.withSize(30)

Related

Making a very simple graph with uibezierpath

my question was
I want to create a simple line graph with certain values. This is done in a view within the mainviewcontroller. I created a UIview named chart. I pass the data to the chart when its retrieved from the API. I figured out how to draw the axis but I am stuck now. I cant find anything on google on how to set labels on intervals and to make the points appear dynamically.
draw the xasis and its labels.
draw the dots in the graph.
My salution
i figured out how to do all the things i asked for.
The code I have now:
class ChartView: UIView {
//some variables
var times: [String] = []
var AmountOfRain: [Double] = []
let pathy = UIBezierPath()
let pathx = UIBezierPath()
var beginwitharray = Array<CGFloat>()
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
//draw the y line
pathy.move(to: CGPoint(x: 30, y: 10))
pathy.addLine(to: CGPoint(x: 30, y: 10))
pathy.addLine(to: CGPoint(x: 30, y: frame.size.height - 30))
UIColor.black.setStroke()
pathy.lineWidth = 1.0
pathy.stroke()
//draw the x line
pathx.move(to: CGPoint(x: 30, y: frame.size.height - 30))
pathx.addLine(to: CGPoint(x: 30, y: frame.size.height - 30))
pathx.addLine(to: CGPoint(x: frame.size.width - 30, y: frame.size.height - 30))
UIColor.black.setStroke()
pathx.lineWidth = 1.0
pathx.stroke()
//when the data arrives form the SUPER slow duienradar API refresh it with the data
if beginwitharray != []{
//remove the label retriving data
let label = viewWithTag(1)
DispatchQueue.main.sync {
label?.removeFromSuperview()
}
//create the dots in the graph
var point = CGPoint()
//simple way to do 2 loop in 1 loop.
var intforbeginarray = 0
let stoke = UIBezierPath()
//get the first 6 itmes out of the rain array cuz of space issues
let first6aumountarray = AmountOfRain[0...5]
stoke.move(to: CGPoint(x: 30, y: self.frame.size.height - 30))
//loop trough the data in the amounts array
for amount in first6aumountarray{
//determen the hight of the dot
let InitialHeight = (CGFloat(amount) * (self.frame.size.height - 30))/6
let pointHeight = (frame.size.height - 30) - InitialHeight
//make the point so we can draw it using UIbezierpath()
point = CGPoint(x: beginwitharray[intforbeginarray] + 20, y: pointHeight)
intforbeginarray += 1
//create the dot
let dot = UIBezierPath()
dot.addArc(withCenter: point, radius: CGFloat(5), startAngle: CGFloat(0), endAngle: CGFloat(360), clockwise: true)
UIColor.black.setFill()
dot.lineWidth = 30
dot.fill()
//create the line between dots will give a warning on the last one cuz the last one doenst go anyway
stoke.addLine(to: point)
stoke.move(to: point)
stoke.lineWidth = 1
UIColor.black.setStroke()
}
//make the strokes
stoke.stroke()
}
}
func getvalues(RainData: [Double], TimesData:[String]){
//assing the data to the subview
self.AmountOfRain = RainData
self.times = TimesData
//xaxis values
let maxint = [0, 1, 2, 3, 4, 5, 6]
//calculate the hight spacing to fit the graph
let heightperstep = ((self.frame.size.height - 5)/6)-5
var beginheight = self.frame.size.height - 35
//calculate the width spacing to fit the graph
let widthperstep = ((self.frame.size.width - 5)/6)-5
var beginwith = CGFloat(30)
//extra check to see if we have data at all.
if times != []{
//get the first 6 items out of the times array for use in our graph
let first6 = times[0...5]
//draw the label on the main queue
DispatchQueue.main.sync {
//draw the xaxis labels accroding to the spacing
for number in maxint{
let label = UILabel(frame: CGRect(x: 5, y: beginheight, width: 25, height: 15))
label.text = "\(number)"
self.addSubview(label)
beginheight = beginheight - heightperstep
}
//draw the yaxis labels according to the spacing
for time in first6{
let label = UILabel(frame: CGRect(x: beginwith, y: self.frame.size.height - 20, width: 55, height: 15))
label.text = time
self.addSubview(label)
beginwitharray.append(beginwith)
beginwith = beginwith + widthperstep
}
}
}
//redrawthe graph with new data.
setNeedsDisplay()
}}
Any help would be appreciated. I also can't use a lib or a pod since this is a school project and I need to create a simple graph.
EDIT:
Completed my code, cleared up an error when running this code
What I did first was to draw the x-asis and the y-axis. After this I considered reasonable values for the aumountofrain data. this turns out cannot really be higher then 6. Since I could fit around 6 labels in the space I have the steps where easy go down by 1 till I hit 0. The calculations I did are for my specific frame height. After I figured it all out and the padding for the y-asxis. It was a matter of figuring out how to get the dots in the right place. Since I already have the data in the beginwitharray I just needed to calculate the height. Then it was simply loop trough the data and draw each dot. Then I just had to connect the dots using the uibezierpath.
i hope my troubles will save someone a lot of time when they read how i done it.
This might be helpful: Draw Graph curves with UIBezierPath
Essentially what you need to do is for every data set you have you need to know the y-axis range of values and based on those ranges assign each value a CGFloat value (in your case inches of rain needs to correlate to a certain CGFloat value). Let's say you have your set amountOfRain = [0.1, 1.3, 1.5, 0.9, 0.1, 0] so your range is var rangeY = amountOfRain.max() - amountOfRain.min(). now lets find out where your first data point 0.1 should go on your graph by converting inches of rain to a CGFloat value that corresponds to the axis you've drawn already, this equation is just basic algebra: let y1 = (amountOfRain[0]/rangeY)*((frame.size.height-30) - 10) + 10 now it looks like your rain samples are at regular intervals so maybe let x1:CGFloat = 10 now you can add a dot or something at the CGPoint corresponding with (x1,y1). If you did this with all the data points it would create a graph that has your maximum value at the top of the graph and minimum value at the bottom. Good Luck!

need to change positioning of labels using cgpoint (swift3)

I have two labels. One lane occupies the top left section of the screen and the other occupies the top right section of the screen. Even though it states bottom alignment mode the position is still on the top of the screen
scoreLabel.text = " Score: 0"
scoreLabel.fontSize = 70
scoreLabel.fontColor = SKColor.white
scoreLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.left
scoreLabel.position = CGPoint(x: self.size.width*0.15, y: self.size.height + scoreLabel.frame.size.height)
scoreLabel.zPosition = 100
self.addChild(scoreLabel)
livesLabel.text = "LIVES: 5"
livesLabel.fontSize = 70
livesLabel.fontColor = SKColor.white
livesLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.right
livesLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.bottom
livesLabel.position = CGPoint(x: self.size.width*0.85, y: self.size.height + livesLabel.frame.size.height)
livesLabel.zPosition = 100
self.addChild(livesLabel)
How can I write code so that both of these labels occupy the the bottom left and right sections of the screen?

How to calculate the correct position for a matrix of circles to fit inside given view with proportional gaps?

I am pretty new to iOS development and I am trying to display a 10x10 grid inside a UIView respecting its bounds and I would like that the circles would be calculated based on the available width/height of the device.
What I tried so far without luck:
func setUpPoints() {
let matrixSize = 10
let diameter = (min(painelView.frame.size.width, painelView.frame.size.height) / CGFloat(matrixSize + 1)).rounded(.down)
let radius = diameter / 2
for i in 0...matrixSize {
for j in 0...matrixSize {
let x = CGFloat(i) * diameter + radius
let y = CGFloat(j) * diameter + radius
let frame = CGRect(x: x, y: y, width: diameter, height: diameter)
let circle = Circle(frame: frame)
circle.tag = j * matrixSize + i + 1
painelView.addSubview(circle)
}
}
}
My goal is to distribute the circles inside the gray rectangle proportionally so it will look like the Android pattern lock screen:
Can someone please give me some pointers?
Thanks.
If I understand what you are trying to do, then the following line:
let radius = (painelView.frame.size.width + painelView.frame.size.height) / CGFloat(matrixSize * 2)
should be:
let radius = (min(painelView.frame.size.width, painelView.frame.size.height) / CGFloat(matrixSize + 1)).rounded(.down)
The above change will allow the "square" of circles fit within whichever is smaller - the view's width or height, allowing for a gap around the "square" equal to half the diameter of each circle.
You also need to change both loops to start with 0.
for i in 0..<matrixSize {
for j in 0..<matrixSize {
BTW - your radius variable is really the diameter. And gap is really the radius.
The following code provides a border around the square of circles and it includes some space between the circles. Adjust as needed.
func setUpPoints() {
let matrixSize = 10
let borderRatio = CGFloat(0.5) // half a circle diameter - change as desired
let gapRatio = CGFloat(0.25) // quarter circle diameter - change as desired
let squareSize = min(painelView.frame.size.width, painelView.frame.size.height)
let diameter = (squareSize / (CGFloat(matrixSize) + 2 * borderRatio + CGFloat(matrixSize - 1) * gapRatio)).rounded(.down)
let centerToCenter = (diameter + diameter * gapRatio).rounded(.down)
let borderSize = (diameter * borderRatio).rounded()
for i in 0..<matrixSize {
for j in 0..<matrixSize {
let x = CGFloat(i) * centerToCenter + borderSize
let y = CGFloat(j) * centerToCenter + borderSize
let frame = CGRect(x: x, y: y, width: diameter, height: diameter)
let circle = Circle(frame: frame)
circle.tag = j * matrixSize + i + 1
painelView.addSubview(circle)
}
}
}

How to make text the same size on all devices in SpriteKit?

In SpriteKit, is there a way to make an SKLabelNode look the same size, regardless of the device, eg: Looks the same size on a iPhone 5 as a 6Plus?
I've tried using this method someone else recommended:
let textRect = CGRect(x: 0, y: 0, width: frame.width * 0.4, height: frame.height * 0.045)
let scalingFactor = min(textRect.width / text.frame.width, textRect.height / text.frame.height)
text.fontSize *= scalingFactor
But it doesn't make all text the same size, as words like "man" aren't as physically tall as words like "High" (due to it's "y" and "h" sticking out).
So is there a method to make text look the same size on all devices? At the moment I create the SKLabelNode like so:
let text = SKLabelNode(text: "Start")
text.fontSize = 30
text.position = CGPoint(x: 0, y: 0)
addChild(text)
The issue here is that you are trying to scale the fontSize, and this does not really play well with complex decimal numbers. Instead, after you create your label, just scale that to the scale factor that you are using to scale everything else
let text = SKLabelNode(text: "Start")
text.fontSize = 30
text.position = CGPoint(x: 0, y: 0)
text.xScale = xScaleFactor
text.yScale = yScaleFactor
where xScaleFactor and yScaleFactor are the factors you are using to determine your scale. (This number should only have to be calculated once, and then stored, if you are not doing that, I would recommend making that change)
Basically in the code you provided it is done like this:
let textRect = CGRect(x: 0, y: 0, width: frame.width * 0.4, height: frame.height * 0.045)
let scaleFactorX = textRect.width / text.frame.width
let scaleFactorY = textRect.height / text.frame.height
I think it's more like an algorithm question. Think about you need to implement the same thing in TV, iPad or in the iPhone device. You should think about storing its absolute value rather than its actual value.
The formula should be width for store value = actual width for this device / device width. The same with the height. Then, if you use the same image data in other devices. You will just need to multiply the new device width/height.

Resize parent UIView based on its children size

I'm new in iOS programming and still don't know how to handle correctly basic stuff like this so I hope someone has good practice to share.
I created a custom keyboard for the user to answer to a question.
It's an UIView containing some UIButton.
How does one center the whole keyboard?
I know I could calculate the width of the keyboard by adding up the width of each key but this seems quite complicated for such a simple action.
Here's my code (in Swift) for now, thanks.
keyboardContainer = UIView(frame: CGRectMake(0, 0, self.frame.width, 200))
keyboardContainer!.center = CGPoint(x: keyboardContainer!.frame.width / 2, y: self.frame.height - keyboardContainer!.frame.height / 2)
self.addSubview(keyboardContainer!)
let gap = Int(self.frame.width) / 8
for i in 0..<keyboardLetters!.count {
let posX = Int(i % 7) * gap + 22
let posY = Int(i / 7) * gap + 25
let key = Key(frame: CGRectMake(0, 0, 44, 44))
key.letter = keyboardLetters![i]
key.tag = i
key.center = CGPoint(x: posX, y: posY)
keyboardContainer!.addSubview(key)
key.addTarget(self, action: "onKeyboardTap:", forControlEvents: .TouchUpInside)
}
Move the center of keyboardContainer and all the buttons will move with it.

Resources