Как оживить выделение сегментированного элемента управления? - PullRequest
0 голосов
/ 01 сентября 2018

У меня есть UISegmentedControl с 3-мя возможными вариантами, и я добавил цветную линию подчеркивания к первому варианту. Я пытаюсь выяснить, как анимировать подчеркивание, чтобы оно двигалось, чтобы выделить новый выбор, но линия подчеркивания не движется.

Я не смотрю, чтобы изменить индекс с анимацией. Я пытаюсь понять, как сохранить подчеркивание UIView в том же сегменте, который выбран. Я видел, как это реализовано обычно.

Вот экранная запись того, что происходит сейчас - https://imgur.com/a/jTQ8z1M

Я добавил UISegmentedControl через Storyboard, а затем добавил подчеркивание в коде с view.addSubview (underlineBar). Вот что у меня есть:

    class ViewController: UIViewController {

        @IBOutlet weak var segmentedControl: UISegmentedControl!

    override func viewDidLoad() {
            super.viewDidLoad()

            setSegmentedControlStyle()   
        }

    func setSegmentedControlStyle() {
            segmentedControl.backgroundColor = .clear
            segmentedControl.tintColor = .clear
            segmentedControl.setTitleTextAttributes([NSAttributedStringKey.font : UIFont.systemFont(ofSize: 16), NSAttributedStringKey.foregroundColor: UIColor.lightGray
                ], for: .normal)
            segmentedControl.setTitleTextAttributes([NSAttributedStringKey.font : UIFont.systemFont(ofSize: 16),
                NSAttributedStringKey.foregroundColor: UIColor.blue
                ], for: .selected)

let underlineBar = UIView()
            underlineBar.translatesAutoresizingMaskIntoConstraints = false // false since we are using auto layout constraints
            underlineBar.backgroundColor = UIColor.blue
            view.addSubview(underlineBar)

            underlineBar.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor).isActive = true
            underlineBar.heightAnchor.constraint(equalToConstant: 3).isActive = true
            underlineBar.leftAnchor.constraint(equalTo: segmentedControl.leftAnchor).isActive = true
            underlineBar.widthAnchor.constraint(equalTo: segmentedControl.widthAnchor, multiplier: 1 / CGFloat(segmentedControl.numberOfSegments)).isActive = true
            UIView.animate(withDuration: 0.3) {
                underlineBar.frame.origin.x = (self.segmentedControl.frame.width / CGFloat(self.segmentedControl.numberOfSegments)) * CGFloat(self.segmentedControl.selectedSegmentIndex)
            }
        }

    }

Называется UIView.animate, но ничего не происходит.

1 Ответ

0 голосов
/ 01 сентября 2018

Проблема в том, что вы устанавливаете ограничения для underlineBar , которые обновляют свойства X, Y и width, height, поэтому при попытке анимировать изменение положения вид не перемещается, потому что ограничения имеют более высокий приоритет. В заключение вам нужно будет анимировать ограничения.

Я создал глобальный leftAnchor , который вы будете изменять при каждом нажатии сегмента.

var underlineBarLeftAnchor: NSLayoutConstraint!

Там, где вы устанавливаете свои ограничения, обновите функцию следующим образом:

underlineBar.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor).isActive = true
underlineBar.heightAnchor.constraint(equalToConstant: 3).isActive = true
underlineBar.widthAnchor.constraint(equalTo: segmentedControl.widthAnchor, multiplier: 1 / CGFloat(segmentedControl.numberOfSegments)).isActive = true

underlineBarLeftAnchor = underlineBar.leftAnchor.constraint(equalTo: segmentedControl.leftAnchor, constant: 0)
underlineBarLeftAnchor.isActive = true

Теперь вам нужно зарегистрировать методы целевого действия для сегментированного элемента управления, используя константу valueChanged , как показано ниже, обновить viewDidLoad () :

override func viewDidLoad() {
    super.viewDidLoad()

    setSegmentedControlStyle()
    segmentedControl.addTarget(self, action: #selector(updateSegmentedControl), for: .valueChanged)

}

Последний шаг, создайте функцию updateSegmentedControl () , в которой вы будете анимировать движение:

Эта функция вызывается каждый раз, когда изменяется значение сегмента управления

@objc func updateSegmentedControl() {
    let padding = underlineBar.frame.width * CGFloat(self.segmentedControl.selectedSegmentIndex)
    underlineBarLeftAnchor.constant = padding

    UIView.animate(withDuration: 0.3) {
        self.view.layoutIfNeeded()
    }
}

Вам нужно вычислить, сколько левого отступа вам нужно, а затем обновить пользовательский интерфейс, layoutIfNeeded () , анимируя изменения.

...