【问题标题】:UIKit: how to animate a constraint change with a programmatically created constraint?UIKit:如何使用以编程方式创建的约束为约束更改设置动画?
【发布时间】:2021-12-17 02:53:36
【问题描述】:

我已按照this answer 从 XIB 文件中实例化视图:

extension UIView {    
    class func fromNib(named: String? = nil) -> Self {
        let name = named ?? "\(Self.self)"
        guard let nib = Bundle.main.loadNibNamed(name, owner: nil, options: nil) else {
            fatalError("missing expected nib named: \(name)")
        }
        guard let view = nib.first as? Self else {
            fatalError("view of type \(Self.self) not found in \(nib)")
        }
        return view
    }
}

现在我想根据内容创建一个具有自适应高度的视图:

class CustomTopView: UIView {
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var subtitleLabel: UILabel!
    
    static func instance(withTitle title: NSAttributedString, subtitle: NSAttributedString) -> CustomTopView {
        let customTopView = CustomTopView.fromNib()
        customTopView.titleLabel.attributedText = title
        customTopView.subtitleLabel.attributedText = subtitle
        return customTopView
    }
}

我想做的是从屏幕顶部以动画形式显示这个视图,就像一个通知弹出窗口一样。我是这样写的:

extension UIView {
    func showCustomTopView(withTitle title: NSAttributedString, subtitle: NSAttributedString) {
        let customTopView = CustomTopView.instance(withTitle: title, subtitle: subtitle)
        addSubview(customTopView)
        customTopView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            customTopView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
            customTopView.constraint(equalTo: customTopView.trailingAnchor, constant: 20.0),
        ])
        customTopView.layoutIfNeeded() // *
        NSLayoutConstraint.activate([customTopView.topAnchor.constraint(equalTo: topAnchor, constant: -customTopView.bounds.height)])
    }
}

我有两个问题。主要是我不知道如何执行我想要的动画,以便视图最终可见。我在最后一个NSLayoutConstraint.activate(...) 之后尝试了这个:

UIView.animate(withDuration: 0.5) {
    self.topAnchor.constraint(equalTo: customTopView.topAnchor, constant: 100.0).isActive = true
    self.layoutIfNeeded()
}

但弹出窗口并没有按预期显示,而是从屏幕顶部开始 100 像素,然后上升并消失。我做错了什么?

另外,我不确定标有// * 的行:我写这行是为了获取正确的customTopView 高度,但我不确定这是正确的方法。

感谢您的帮助!

【问题讨论】:

    标签: ios uikit nslayoutconstraint


    【解决方案1】:

    一种方法:

    • 创建一个约束,将 customTopView 的底部设置在视图顶部的上方
    • 创建一个第二个约束,将customTopView的顶部设置在视图顶部下方
    • 添加customTopView作为子视图,激活第一个约束
    • 通过停用第一个约束并激活第二个约束,将 customTopView 动画化到视图中

    这是您的showCustomTopView(...) 扩展的修改版本,使用UILabel 作为customTopView - 应该可以与您的CustomTopView.instance(withTitle: ...) 配合使用:

    extension UIView {
        func showCustomTopView(withTitle title: NSAttributedString, subtitle: NSAttributedString) {
            let customTopView = UILabel()
            customTopView.text = title.string
            customTopView.backgroundColor = .green
            addSubview(customTopView)
            customTopView.translatesAutoresizingMaskIntoConstraints = false
            let g = self.safeAreaLayoutGuide
            // constraint: Bottom of customTopView to Top of self Minus 8-pts
            let cvBot = customTopView.bottomAnchor.constraint(equalTo: topAnchor, constant: -8.0)
            // constraint: Top of customTopView to Top of self Plus 8-pts
            let cvTop = customTopView.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0)
            NSLayoutConstraint.activate([
                customTopView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
                customTopView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20.0),
                // activate cvBot, so customTopView is 8-pts above the top of self
                cvBot,
            ])
            // execute this async, so the initial view position is set
            DispatchQueue.main.async {
                // deactivate the Bottom constraint
                cvBot.isActive = false
                // activate the Top constraint
                cvTop.isActive = true
                // animate it into view
                UIView.animate(withDuration: 0.5, animations: {
                    self.layoutIfNeeded()
                })
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多