1. 程式人生 > >iOS 給 storyboard 建立的 view 新增動畫效果

iOS 給 storyboard 建立的 view 新增動畫效果

使用 storyboard, xib 建立的檢視, 檢視的約束是用的 Autolayout , 所以實現動畫效果也要通過改變約束的值,而不是直接改變 frame

 

示例: 在控制器上新增一個 blueView, blueView 上新增一個 greenView, 現改變 blueView 的寬度實現動畫效果

 

一. 改變約束值實現動畫

將 blueView 的寬度拉成屬性 BlueView_Width, 改變 BlueView_Width 的 constant 值, 然後在UIView.animate 中新增                 strongSelf.view.layoutIfNeeded(), 更新controller View 的子檢視佈局, 不新增的 strongSelf.view.layoutIfNeeded() 沒有動畫效果

blueView 是 View 的子檢視, blueView 的寬度改變時, view 的 viewWillLayoutSubviews 會執行

        @IBOutlet weak var blueView: UIView!
        @IBOutlet weak var greenView: UIView!
        @IBOutlet weak var BlueView_Width: NSLayoutConstraint!

        let blueWidth = BlueView_Width.constant + 10
        BlueView_Width.constant = blueWidth
        UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseIn, animations: { [weak self] in
            if let strongSelf = self {
                strongSelf.view.layoutIfNeeded()
            }
            
        }, completion: nil)

二.使用 frame 實現動畫

 view 的 viewWillLayoutSubviews  不會執行

錯誤:

blueView 的寬度改變了, 但是 greenView 的寬度沒有隨著改變

UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseIn, animations: { [weak self] in
            if let strongSelf = self {
                let blueWidth = strongSelf.blueView.frame.width + 10
                strongSelf.blueView.frame.size.width = blueWidth
                strongSelf.view.layoutIfNeeded()

            }
        }, completion: nil)

因為 blueView 和 greenView  的約束是通過 Autolayout 建立的, 所以改變 blueView frame 時, 它的子檢視並不會隨之改變, view 的 viewWillLayoutSubviews 不會執行, 要讓 greenView 寬度改變, 需要改變 greenView 的 frame

UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseIn, animations: { [weak self] in
            if let strongSelf = self {
                let blueWidth = strongSelf.blueView.frame.width + 10
                strongSelf.blueView.frame.size.width = blueWidth
                strongSelf.greenView.frame.size.width = 70
                strongSelf.view.layoutIfNeeded()
            }
            
        }, completion: nil)

如果使用 blueView 的 layoutIfNeeded() 方法, 需要寫在改變 greenView 寬度之前, 寫在之後沒有效果

UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseIn, animations: { [weak self] in
            if let strongSelf = self {
                let blueWidth = strongSelf.blueView.frame.width + 10
                strongSelf.blueView.frame.size.width = blueWidth
                strongSelf.blueView.layoutSubviews()
                strongSelf.greenView.frame.size.width = 70
            }
            
        }, completion: nil)