ios - 如果我想在之后为自动布局约束设置动画,我该如何修改我的 UIView 扩展?

标签 ios swift xcode nslayoutconstraint

我做了一个 UIView 扩展来设置我的 NSLayout anchor 。一切正常。但是,如果我想添加一个 NSLayoutConstraint,我该如何修改我的扩展,以便之后可以为约束设置动画?

这是我当前的扩展:

extension UIView {
    func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
        //translate the view's autoresizing mask into Auto Layout constraints
        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
        }

        if let leading = leading {
            leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
        }

        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
        }

        if let trailing = trailing {
            trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
        }

        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }

        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
    }
}

扩展的调用方式如下:

//feedViewButton constraints
feedViewButton.anchor(top: nil, leading: nil, bottom: view.safeAreaLayoutGuide.bottomAnchor, trailing: view.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 0, right: 25), size: .init(width: 50, height: 50))

更新

我想要这样的东西

var topAnchor: NSLayoutConstraint?

topAnchor = topAnchor.constraint(equaltTo: top, constant: padding.top)
topAnchor.isActive = true

然后像这样制作动画:

let animator = UIViewPropertyAnimator(duration: 1, curve: .easeOut) {
    topAnchor.constant = 20
}
animator.startAnimation()

最佳答案

只需尝试使用自动布局对其进行动画处理,因为尚未应用约束,它应该是可动画的:

feedViewButton.anchor(top: nil, leading: nil, bottom: view.safeAreaLayoutGuide.bottomAnchor, trailing: view.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 0, right: 25), size: .init(width: 50, height: 50))
feedViewButton.superview?.setNeedsLayout()
UIView.animate(withDuration: 0.2, delay: 0, options: [.allowUserInteraction], animations: {
    feedViewButton.superview?.layoutIfNeeded()
}, completion: nil)

更新

如果您想稍后更改 anchor 上的常量以动画化其他更改,则必须保留对约束的引用以便以后能够操纵它们:

enum ConstraintType {
    case top, leading, trailing, bottom, width, height
}

extension UIView {

    func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) -> [ConstraintType : NSLayoutConstraint] {
        //translate the view's autoresizing mask into Auto Layout constraints
        translatesAutoresizingMaskIntoConstraints = false

        var constraints: [ConstraintType : NSLayoutConstraint] = [:]

        if let top = top {
            constraints[.top] = topAnchor.constraint(equalTo: top, constant: padding.top)
        }

        if let leading = leading {
            constraints[.leading] = leadingAnchor.constraint(equalTo: leading, constant: padding.left)
        }

        if let bottom = bottom {
            constraints[.bottom] = bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom)
        }

        if let trailing = trailing {
            constraints[.trailing] = trailingAnchor.constraint(equalTo: trailing, constant: -padding.right)
        }

        if size.width != 0 {
            constraints[.width] = widthAnchor.constraint(equalToConstant: size.width)
        }

        if size.height != 0 {
            constraints[.height] = heightAnchor.constraint(equalToConstant: size.height)
        }
        let constraintsArray = Array<NSLayoutConstraint>(constraints.values)
        NSLayoutConstraint.activate(constraintsArray)
        return constraints
    }
}

此扩展返回一个约束字典,您可以稍后更改这些约束并为这些更改设置动画。例如:

let constraints = feedViewButton.anchor(top: nil, leading: nil, bottom: view.safeAreaLayoutGuide.bottomAnchor, trailing: view.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 0, right: 25), size: .init(width: 50, height: 50))
// applies the constraints    
self.view.layoutIfNeeded()

// now to animate bottom to -50:
if let bottomConstraint = constraints[.bottom] {
    bottomConstraint.constant = -50
    self.view.setNeedsLayout()
    let animator = UIViewPropertyAnimator(duration: 1, curve: .easeInOut, animations: {
        self.view.layoutIfNeeded()
    })
    animator.startAnimation()
}

关于ios - 如果我想在之后为自动布局约束设置动画,我该如何修改我的 UIView 扩展?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48804229/

相关文章:

ios - 无法将文件的所有者连接到 View

iphone - 检测应用程序的首次运行

ios - 如何进入ios中的特定页面

ios - Swift - 在 whereField 子句中传递多个参数以从 firebase 检索

swift - 为什么要用T!而不是 T 作为函数参数和返回类型?

iOS:TouchXML xmlReadMemory VS xmlParseMemory

objective-c - 观察一次 Action 对多个 View 的触摸

ios - ApplicationDomain.getDefinition 在适用于 iOS 的 Release Build 中不起作用

ios - Tableviewcontroller "cellForRowAtIndexPath"- 索引从 4 开始,而不是 0

ios - 为什么我的 iOS 应用程序无法从 Firebase 数据库读取?