Below is a short piece of demo code distilled from my project. It consists of a UINavigationBar, UINavigationItem, and several UIBarButtonItems. Tapping on a barButtonItem highlights it and dims the others. In doing so, it is understandable that the font size changes, but I want the size of the barButtonItems themselves to be fixed. That way, when I tap randomly on the barButtonItems, they don't appear to jiggle as their title text shrinks and expands. How do I make the barButtonItems resist resizing as their title text changes?
import UIKit
class ViewController: UIViewController {
var barButtonItems: [UIBarButtonItem]!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .darkGray
let navBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 100, width: view.frame.width, height: 40))
navBar.barTintColor = #colorLiteral(red: 0.1019607857, green: 0.2784313858, blue: 0.400000006, alpha: 1)
view.addSubview(navBar)
let navItem = UINavigationItem()
let appleBarBtnItem = UIBarButtonItem(title: "Apple", style: .plain, target: self, action: #selector(barItemTapped))
let bananaBarBtnItem = UIBarButtonItem(title: "Banana", style: .plain, target: self, action: #selector(barItemTapped))
let kiwiBarBtnItem = UIBarButtonItem(title: "Kiwi", style: .plain, target: self, action: #selector(barItemTapped))
let pearBarBtnItem = UIBarButtonItem(title: "Pear", style: .plain, target: self, action: #selector(barItemTapped))
let orangeBarBtnItem = UIBarButtonItem(title: "Orange", style: .plain, target: self, action: #selector(barItemTapped))
barButtonItems = [appleBarBtnItem, bananaBarBtnItem, kiwiBarBtnItem, pearBarBtnItem, orangeBarBtnItem]
navItem.leftBarButtonItems = barButtonItems
navBar.setItems([navItem], animated: false)
setCurrentBarItem(appleBarBtnItem)
}
func setCurrentBarItem(_ barBtnItem: UIBarButtonItem) {
for btn in barButtonItems {
highlight(btn, turnedOn: (btn == barBtnItem) )
}
}
func highlight(_ button: UIBarButtonItem, turnedOn: Bool) {
button.tintColor = #colorLiteral(red: 0.7230747342, green: 0.9554787278, blue: 0.9893732667, alpha: 1)
let weight: UIFont.Weight = turnedOn ? .bold : .thin
let attributes: [NSAttributedString.Key : Any] = [ .font: UIFont.systemFont(ofSize: 20, weight: weight)]
button.setTitleTextAttributes(attributes, for: .normal)
}
@objc func barItemTapped(_ sender: UIBarButtonItem) {
setCurrentBarItem(sender)
}
}
CodePudding user response:
One reason they are jiggling is that you are setting setTitleTextAttributes
only for .normal
state. Add it for .selected
as well so it jiggle less however it won't fully fix your issue.
Sth like this
button.setTitleTextAttributes(attributes, for: .selected)
I would suggest to try to add some margin to the ui text holder element of the UIBarButtonItems. May fix it!
CodePudding user response:
Looks like I have to give up on having a .bold
font weight for the selected barButtonItem and a .thin
font weight when it's not, because the change in font weight expands or shrinks the width of the barButtonItem causing the juxtaposing barButtonItems to shift and jiggle around when I tap on them. I finally decided on only changing the colors of the barButtonItems and providing a simple animation:
func highlight(_ button: UIBarButtonItem, turnedOn: Bool) {
let tintColor = turnedOn ?
#colorLiteral(red: 0.7230747342, green: 0.9554787278, blue: 0.9893732667, alpha: 1)
:
#colorLiteral(red: 0.1901655495, green: 0.5488880277, blue: 0.7976593971, alpha: 1)
UIView.animate(withDuration: 0.2,
delay: 0,
options: [.allowUserInteraction, .curveEaseInOut],
animations: { button.tintColor = tintColor },
completion: nil)
}