UIView 高度约束动画,与其他视图有锚连接

Posted

技术标签:

【中文标题】UIView 高度约束动画,与其他视图有锚连接【英文标题】:UIView height constraint animation, which has anchor connection with other views 【发布时间】:2018-08-09 00:02:13 【问题描述】:

Xcode Swift 4

我有一些在代码中动态添加的视图。 每个新的视图顶部锚点都连接到先前的视图底部锚点。 每个视图都有一个按钮,可以使视图随动画展开/折叠。这是按钮代码:

    let fullHeight : CGFloat = 240
    let smallHeight : CGFloat = 44

    let currentHeigth  = rootView.frame.size.height //I use this to get current height and understand expanded view or not

    let heighCons = rootView.constraints.filter //I use this to deactivate current height Anchor constraint
    
        $0.firstAttribute == NSLayoutAttribute.height
    
    NSLayoutConstraint.deactivate(heighCons)
    rootView.layoutIfNeeded()

    if currentHeigth == smallHeight
    
        rootView.heightAnchor.constraint(equalToConstant: fullHeight).isActive = true
        rootView.setNeedsLayout()

        UIView.animate(withDuration: 0.5)
        
            rootView.layoutIfNeeded() //animation itself
        

    
    else
    
        rootView.heightAnchor.constraint(equalToConstant: smallHeight).isActive = true
        rootView.setNeedsLayout()

        UIView.animate(withDuration: 0.5)
        
            rootView.layoutIfNeeded() //animation itself
        
    

这一切都很完美,但我有一个问题:查看当前扩展视图下方的视图会立即更改它的 y 位置,而没有动画。它只是跳转到上一个视图底部锚点,在动画完成后将处于活动状态。

所以我的问题是:

1) 当视图通过底部/顶部动画相互连接时,制作高度约束动画的正确方法是什么?

2) 我的目标只是制作一个可以在单击按钮时展开/折叠的视图,也许我应该以另一种方式来做?

【问题讨论】:

【参考方案1】:

这是一种使用 Visiblity Gone Extension 的方法

extension UIView 
func visiblity(gone: Bool, dimension: CGFloat = 0.0, attribute: NSLayoutAttribute = .height) -> Void 
    if let constraint = (self.constraints.filter$0.firstAttribute == attribute.first) 
        constraint.constant = gone ? 0.0 : dimension
        self.layoutIfNeeded()
        self.isHidden = gone
    
 

用法

expanview.visiblity(gone: true,dimension: 0)

示例

@IBOutlet weak var msgLabel: UILabel!
@IBOutlet weak var expanview: UIView!
@IBAction func toggleCollapisbleView(_ sender: UIButton) 
    if sender.isSelected
        sender.isSelected = false
        expanview.visiblity(gone: false,dimension: 128)
        sender.setTitle("Collapse",for: .normal)
    
    else
        sender.isSelected = true
        expanview.visiblity(gone: true,dimension: 0)
        sender.setTitle("Expand",for: .normal)
        msgLabel.text = "Visiblity gone"
    


【讨论】:

tabassum,感谢您的回答,但这并不是我所需要的。您的代码可以工作,但是将它与动画视图扩展一起使用与我的解决方案的工作方式相同。(需要折叠或展开的视图会通过动画更改其高度,但其他视图只是跳转到没有动画的新位置)。要理解我的意思,只需删除“self.layoutIfNeeded()”扩展 UIView 并在调用可见性方法 expanview.visiblity(gone: true,dimension: 0) rootView.setNeedsLayout() UIView.animate(withDuration: 0.5) rootView.layoutIfNeeded() tabassum 不,它没有完成)您的代码不适用于动画。我需要这样的东西,但对于 Xcode github.com/AAkira/ExpandableLayout @Bios90 i.gyazo.com/… 可以看看这个链接 你的 GIF 上的 tabassum 都完全按照我的需要工作,但在我看来,它的工作方式是另一种方式。我的视图是在没有故事板的情况下动态添加的,“translatesautoresizingmaskintoconstraints = false”,每个新视图的顶部锚点都是以前的底部锚点,也许这就是原因。 这样你就可以使用tableview来添加动态视图了。

以上是关于UIView 高度约束动画,与其他视图有锚连接的主要内容,如果未能解决你的问题,请参考以下文章

在约束上动画更改 UITableView 节标题的高度

IOS 8 高度约束动画未按预期工作

UIPickerView 高度约束动画跳跃

UIView的高度约束动画

UIView 动画与子视图同步

基于子视图约束的超级视图没有增加高度