如何动画分段控件选择?
How to animate Segmented Control selection?
我有一个 UISegmentedControl
,有 3 个可能的选择,我在第一个选择中添加了彩色下划线。我试图弄清楚如何为下划线设置动画,以便它移动以突出显示新选择,但下划线栏没有移动。
我不打算用动画更改索引。我试图弄清楚如何将下划线栏 UIView 保持在所选的同一段中。我已经看到这个实现很普遍。
这是当前正在发生的事情的屏幕录像 - https://imgur.com/a/jTQ8z1M
我通过 Storyboard
添加了 UISegmentedControl
,然后使用 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
,但没有任何反应。
问题是您正在为更新 X、Y 和宽度、高度属性的 underlineBar 设置约束,因此当您尝试为位置变化设置动画时,视图没有移动,因为约束具有更高的优先级。总之,您需要为约束设置动画。
我创建了一个全局 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() 函数,您将在其中制作动画:
This function will get called every time the value of the segment control is changed
@objc func updateSegmentedControl() {
let padding = underlineBar.frame.width * CGFloat(self.segmentedControl.selectedSegmentIndex)
underlineBarLeftAnchor.constant = padding
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
您需要计算需要多少左填充,然后更新 ui、layoutIfNeeded(),同时对更改进行动画处理。
我有一个 UISegmentedControl
,有 3 个可能的选择,我在第一个选择中添加了彩色下划线。我试图弄清楚如何为下划线设置动画,以便它移动以突出显示新选择,但下划线栏没有移动。
我不打算用动画更改索引。我试图弄清楚如何将下划线栏 UIView 保持在所选的同一段中。我已经看到这个实现很普遍。
这是当前正在发生的事情的屏幕录像 - https://imgur.com/a/jTQ8z1M
我通过 Storyboard
添加了 UISegmentedControl
,然后使用 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
,但没有任何反应。
问题是您正在为更新 X、Y 和宽度、高度属性的 underlineBar 设置约束,因此当您尝试为位置变化设置动画时,视图没有移动,因为约束具有更高的优先级。总之,您需要为约束设置动画。
我创建了一个全局 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() 函数,您将在其中制作动画:
This function will get called every time the value of the segment control is changed
@objc func updateSegmentedControl() {
let padding = underlineBar.frame.width * CGFloat(self.segmentedControl.selectedSegmentIndex)
underlineBarLeftAnchor.constant = padding
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
您需要计算需要多少左填充,然后更新 ui、layoutIfNeeded(),同时对更改进行动画处理。