Как исправить размер UIBarButtonItem при изменении веса шрифта

#swift #size #uibarbuttonitem

Вопрос:

Ниже приведен короткий фрагмент демо-кода, взятый из моего проекта. Он состоит из UINavigationBar, UINavigationItem и нескольких UIBarButtonItems. Нажатие на кнопку-кнопку выделяет ее и затемняет остальные. При этом понятно, что размер шрифта меняется, но я хочу, чтобы размер самих элементов barButtonItems был исправлен. Таким образом, когда я случайным образом нажимаю на элементы barButtonItems, они не кажутся покачивающимися, когда их текст заголовка сжимается и расширяется. Как заставить элементы barButtonItems сопротивляться изменению размера при изменении текста заголовка?

 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)
    }
}
 

Элементы barButtonItems изменяют размер по мере изменения размера их заголовков

Ответ №1:

Одна из причин, по которой они колеблются, заключается в том, что вы настраиваете setTitleTextAttributes только .normal состояние. Добавьте его .selected также, чтобы он меньше покачивался, однако это не решит вашу проблему полностью. Вот так

 button.setTitleTextAttributes(attributes, for: .selected)
 

Я бы предложил попробовать добавить некоторое поле в элемент держателя текста пользовательского интерфейса элементов UIBarButtonItems. Может быть, это исправит!

Комментарии:

1. Нет, это не помогло. Похоже, мне придется отказаться от наличия .bold веса шрифта для выбранного элемента BarButtonItem и .thin веса шрифта, когда это не так, потому что изменение веса шрифта увеличивает или уменьшает ширину элемента BarButtonItem. В конце концов я решил просто изменить цвета элементов barButtonItems и создать простую анимацию.

Ответ №2:

Похоже, мне придется отказаться от наличия .bold веса шрифта для выбранного элемента BarButtonItem и .thin веса шрифта, когда это не так, потому что изменение веса шрифта увеличивает или уменьшает ширину элемента BarButtonItem, заставляя сопоставляющие элементы BarButtonItem смещаться и покачиваться, когда я нажимаю на них. В конце концов я решил изменить только цвета элементов barButtonItems и предоставить простую анимацию:

     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)
    }
 

Визуально улучшен выбор элементов BarButtonItem