Reputation: 85
I have a UIButton with the label on the left side and UIImageView on the right side. The button is used to open a UIPicker. When a value is picked in the picker the same value is shown in button title. When the title changes (or, more accurately, when to uilabel has a width that screws the UI up) the title and icon is moved and the UI does not look good.
When a title with too long text is used the word is clipped and when it's too short the alignment is messed up.
I've tried changing the label frame so it can be constant, whatever the text, and left aligning the text so the jumping stops. I added adjustsFontSizeToFitWidth = true which kind of works, but with a longer title the text will get too small. I've also tried recreating/rerendering the button when the title changes but all attempts fail.
lazy var sortButton = { () -> UIButton in
let btn = UIButton()
btn.addTarget(self, action: #selector(sortButtonPressed), for: .touchUpInside)
btn.setTitle(NSLocalizedString("Sortera", comment: ""), for: .normal)
btn.titleLabel?.text = btn.titleLabel?.text?.uppercased()
btn.setImage(UIImage(named: "ios-down"), for: .normal)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitleColor(Colors.FILTER_BUTTON_TEXT_COLOR, for: .normal)
btn.titleLabel?.adjustsFontSizeToFitWidth = true
btn.titleLabel?.font = UIFont(name: Fonts.AkzidenzGroteskProMd, size: 16)
btn.backgroundColor = Colors.BUTTON_BACKGROUND_GRAY
btn.imageView?.contentMode = .scaleAspectFit
btn.imageEdgeInsets = UIEdgeInsets(top: 16, left: (btn.titleLabel?.frame.size.width)! - buttonInsideOffset/2, bottom: 16, right: -(btn.titleLabel?.frame.size.width)! + buttonInsideOffset/2)
btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -(btn.titleLabel?.frame.size.width)! + buttonInsideOffset, bottom: 0, right: (btn.titleLabel?.frame.size.width)! - buttonInsideOffset)
return btn
}()
I want all button to like like this, whatever the title text:
However, when the text is too small it looks like this:
or when it's too long:
Upvotes: 1
Views: 348
Reputation: 4412
If you dont want button image to be shifted to the right or left then you have to constraint independent of the button's title label
btn.imageView?.frame = CGRect(x: 0, y: 0, width: 20, height: 20) // Or any size you want
// NB: I ommited left insets intentionally
btn.imageEdgeInsets.top = 16
btn.imageEdgeInsets.bottom = 16
btn.imageEdgeInsets.right = 16
Then constraint your label dependent to the imageView position, that way only label size will change without affecting the position of image.
btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -(btn.titleLabel?.frame.size.width)! + buttonInsideOffset, bottom: 0, right: btn.imageView?.frame.width + 10)
Lastly, Since the frame is fixed size, I think you need to limit the font scaling factor to the min size you want and truncate the tail when that size is reached. If you don't want to truncate tail then you have to enable multiline titleLabel (Which I think you don't want this).
btn.titleLabel?.minimumScaleFactor = 0.5 // Or whatever minimum scale you wish
btn.titleLabel?.lineBreakMode = NSLineBreakMode.byTruncatingTail // Since button size is fixed and you want to limit font size then the best option is to truncate tail
Upvotes: 0
Reputation: 692
You can do it in many way but the simplest way :
Take a UIView and then others two-element (a label a imageView) set in this View and make it look like button then set constraint as you want. Then addTarget to label and do all functionality to that that target selector method.
Upvotes: 2