I am working on an MTG life counter app and am having issues with UIButtons and their title text not sizing properly after rotating for a vertical view. The text either comes out very small when I set the font size to adjust to fit width, or as "..." when I don't set the font size to adjust to fit the width.
https://imgur.com/a/BEI3Zim
I have tried to set the font to adjust to fit width, but then it comes out very small and unreadable. If I don't set the font to adjust to fit width, then the text comes out as "..."
// player 3 cell
let cell = tableView.dequeueReusableCell(withIdentifier: "VerticalPlayerTableViewCell", for: indexPath) as! VerticalPlayerTableViewCell
cell.player.name = playerData[2].name
cell.player.health = playerData[2].health
cell.playerTopButton.backgroundColor = playerData[2].playerColor
cell.playerTopButton.setTitle(String(cell.player.health), for: .normal)
cell.playerBottomButton.backgroundColor = playerData[2].playerColor
cell.playerBottomButton.setTitle(cell.player.name, for: .normal)
// rotating top button title text
cell.playerTopButton.titleLabel?.transform = CGAffineTransform(rotationAngle: (CGFloat.pi / 2) )
cell.playerTopButton.titleLabel!.adjustsFontSizeToFitWidth = true
cell.playerTopButton.titleLabel!.numberOfLines = 1
// rotating bottom button title text
cell.playerBottomButton.titleLabel?.transform = CGAffineTransform(rotationAngle: (CGFloat.pi / 2))
cell.playerBottomButton.titleLabel!.adjustsFontSizeToFitWidth = true
cell.playerBottomButton.titleLabel!.numberOfLines = 1
return cell
I was expecting the text to be fine after just rotating the UIButton title label 90 degrees to the right.
Related
I have some UILabels next to each other containing text.
It could be:
2x-5 = 3
I can drag "-5" to the other side.
2x = 3-5
It then moves in to place next to "3" and then I change the sign from - to +, within a UIView.animate() function.
Because "+" is a little bit wider than "-" the text goes past the limits of the UILabel, which cuts of the text in one side.
So I resize the labels width, but it is visible when using the application.
I have tried changing the size of the label before I change the sign, just adding a lot of space.
But it still cuts some of the text off.
Here is the code:
let v = UILabel()
v.text = "+5"
UIView.animate(withDuration: 0.5, animations: {
v.frame.size.width = v.intrinsicContentSize.width + 20
v.text = "-5"
v.font = UIFont.boldSystemFont(ofSize: 45)
v.textAlignment = .center
v.frame.size.width = v.intrinsicContentSize.width
v.frame.size.height = v.intrinsicContentSize.height
}
Optimally I want the label not to cut off any of the text when the width of the text is changed.
(Edit: removed other question unrelated to main question)
Thank you in advance for any help!
What I want to do is create a new UILabel programmatically every time a certain action occurs in my code. I know the x, y, and height that I want to give the label, but I don't want to give it a set width. I want to constrain the sides so that the UILabel width is equal to the width of the screen, and so that the label width will change if the orientation is flipped.
I have considered using:
CGRect(x:, y:, width:, height:)
However, I would have to give it a set width if I use this, so I don't think it will work.
I also tried using:
CGPoint(x:, y:)
Then setting leading, trailing and height anchors, however, this doesn't seem to work either as even though it does compile, I get an error when I try creating a new UILabel.
I'm kind of new to programming in Swift so I'm not sure if there is an obvious fix to this.
Like you said, we already have x, y and height available for the label, i.e.
let x: CGFloat = 0
let y: CGFloat = 0
let height: CGFloat = 50
Let's create a label using the above details. Also set the width of the label as UIScreen.main.bounds.width as per your requirement.
let label = UILabel(frame: CGRect(x: x, y: y, width: UIScreen.main.bounds.width, height: height))
label.text = "This is a sample text"
Don't forget to set label's translatesAutoresizingMaskIntoConstraints as false and add it to whatever subview you want.
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
Add the relevant constraints of label with its superview - top, bottom, leading, height. You can definitely add bottom constraint if required. That totally depends upon your UI.
I'm adding the label to the top of the viewController's view.
NSLayoutConstraint.activate([
label.heightAnchor.constraint(equalToConstant: height),
view.topAnchor.constraint(equalTo: label.topAnchor),
view.leadingAnchor.constraint(equalTo: label.leadingAnchor),
view.trailingAnchor.constraint(equalTo: label.trailingAnchor)
])
You can use following code to create UILabel programmatically.
private let label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.text = "Hello World"
return label
}()
Then inside your viewDidLoad()
addSubview(label)
NSLayoutConstraint.activate([
topAnchor.constraint(equalTo: label.topAnchor),
bottomAnchor.constraint(equalTo: label.bottomAnchor),
leadingAnchor.constraint(equalTo: label.leadingAnchor),
trailingAnchor.constraint(equalTo: label.trailingAnchor)
])
I have UIButton, which title is dynamic changes. Button size should changes with title size and will be equal title size.
How to do this programmatically in Swift?
To have your button use its intrinsic content size and automatically resize based upon its text, use Auto Layout to position the button. Only set constraints to position the button and iOS will use the size of the text to determine the width and height of the button.
For example:
let button = UIButton()
// tell it to NOT use the frame
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Hello", for: .normal)
view.addSubview(button)
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
This also works if you create the button in the Storyboard. Again, only give constraints to place the button and it will resize to accommodate the text.
Follow below steps(its not a proper solution but you can solve your problem by doing like this )
Create a UILabel (because UILabel adjust its height and width depends on the text)
UIlabel number of line to 1
Create a UIButton over UILabel
Set button title to ""
Set button's constraint : Align button's top and leading to UILabel and equals width and height
Hope this will works for you :)
You can get UIButton's width and Height dynamically with its title.
With the help of, NSString's Size property we can achieve this.
let buttonNAme = [" hi ", "welcome", "Login", "Forgot Password ??", "New to here. Sign up??"]
var yPos = CGFloat()
override func viewWillAppear(_ animated: Bool) {
yPos = 40
for i in 0..<buttonNAme.count
{
self.view.addSubview(addingCustomButton(buttonTitle: buttonNAme[i], buttonFontSize: 15, buttonCount: i))
}
}
func addingCustomButton(buttonTitle : String, buttonFontSize: CGFloat, buttonCount : Int) -> UIButton
{
let ownButton = UIButton()
ownButton.setTitle(buttonTitle, for: UIControlState.normal)
ownButton.titleLabel?.font = UIFont.systemFont(ofSize: buttonFontSize)
let buttonTitleSize = (buttonTitle as NSString).size(attributes: [NSFontAttributeName : UIFont.boldSystemFont(ofSize: buttonFontSize + 1)])
ownButton.frame.size.height = buttonTitleSize.height * 2
ownButton.frame.size.width = buttonTitleSize.width
ownButton.frame.origin.x = 30
yPos = yPos + (ownButton.frame.size.height) + 10
ownButton.frame.origin.y = yPos
ownButton.tintColor = UIColor.white
ownButton.backgroundColor = .brown
ownButton.tag = buttonCount
ownButton.setTitleColor(UIColor.darkGray, for: UIControlState.highlighted)
ownButton.addTarget(self, action: #selector(ownButtonAction), for: UIControlEvents.touchUpInside)
return ownButton
}
func ownButtonAction(sender: UIButton)
{
print("\n\n Title \(sender.titleLabel?.text) TagNum \(sender.tag)")
}
Output
Just Constraint it's origin, and the size will fit it's button title
I have a UILabel with centered text. Single line, not attributed. I want to get the CGRect for the actual text in the label (it spans the whole width of a iOS device). Some of the text is dynamic in the text, so the width of the text in the label can change from time to time. So I want to get the position of the text so that I can place an image next to the first character.
I did this in the past but can't remember what I did to do it.
I ended up using UILabel.textRect. It works perfectly for me.
let myRect:CGRect = _topBanner.textRect(forBounds: _topBanner.bounds, limitedToNumberOfLines: 1)
_icon.frame.origin.x = myRect.origin.x - _icon.frame.size.width + 50
_icon.frame.origin.y = _topBanner.frame.origin.y + 8
Try creating a temporary UILabel just to get the text width:
let fullWidthLabel: UILabel = ...
let tmpLabel = UILabel()
tmpLabel.text = fullWidthLabel.text
tmpLabel.font = fullWidthLabel.font
tmpLabel.sizeToFit()
let textWidth = tmpLabel.frame.width
Use textWidth to solve your original problem.
I have several labels inside an scrollview. Each label is an "page". But the offset isn't right. And I can't find the problem.
My code:
let quantity = 10;
var width : CGFloat = 0.0;
override func viewDidLoad() {
super.viewDidLoad()
width = self.scrView.frame.width;
for i in 0..<quantity {
let xPos = width * CGFloat(i);
let label = UILabel(frame: CGRect(x: xPos, y: 0, width: width, height: self.scrView.frame.height))
label.textAlignment = .center
label.font = UIFont(name: "Helvetica Neue", size: 50)
label.textColor = UIColor.white
label.text = "\(i + 1)"
label.backgroundColor = .randomColor()
scrView.addSubview(label);
}
scrView.contentSize.width = width * CGFloat(quantity + 1);
}
The pink color on the left side is from the previous "page".
And again, note the purple color on the left side from the previous (number 8) page.
The first page seems fine. However the higher the number the greater the offset. I want to cover the whole visible area for 1 label.
Does somebody knows an solution?
Your code works fine for me.
Note that the size of the scrollView can change after viewDidLoad as a result of Auto Layout. A better place to set up your scrollView would be in an override of viewDidLayoutSubviews. The size of the scrollView will be established by then. But be careful, because viewDidLayoutSubviews will run multiple times, so make sure you only set up your scrollView once.
This is not your bug, but your contentSize.width is too big. You don't need to add 1 to quantity since there are exactly quantity labels in your scrollView content area.
scrView.contentSize.width = width * CGFloat(quantity)
Also, Swift doesn't need the ; at the ends of lines, so delete those.