簡體   English   中英

動畫 UIStackView 視圖到中心

[英]Animate UIStackView views into centre

我在UIStackView有 5 個按鈕。 其中之一是居中的。 按住中心按鈕后,我想將所有其他按鈕設置為中心並隱藏它們。 然后當我釋放中心按鈕時,我想將它們從中心退回到原來的位置。

目前我的代碼如下所示:

private func transform(views: [UIView], toIdentity isIdentity: Bool) {
   UIView.animate(withDuration: 0.3) {
        for view in views {
            if isIdentity {
                view.transform = .identity
            } else {
                view.center.x = self.view.center.x
            }
            
            view.isHidden = !isIdentity
        }
    }
}

這是有效的,但是當isIdentity為 false 時,按鈕都跳到父視圖之外,然后移動到中心。

我也嘗試將此代碼放在動畫塊中。 這避免了奇怪的跳躍問題,但它們比中心移動得更遠。

let delta = self.view.center.x - view.center.x
view.transform = isIdentity ? .identity : view.transform.translatedBy(x: delta, y: 0)

為什么會這樣,我該如何解決?

您確定您的堆棧視圖居中嗎? 我不明白為什么翻譯代碼不起作用。 也許嘗試從 centerView 而不是實際視圖創建 Delta。 注意:第一個動畫中的問題是它正在更新中心,然后嘗試使用不起作用的變換撤消該更新,它需要將幀更新回原始位置。

let delta = centerButton.center.x - view.center.x
view.transform = isIdentity ? .identity : view.transform.translatedBy(x: delta, y: 0)

有幾種方法可以做到這一點,但這里有一種使用堆棧視圖的方法。

假設我們已經在 Storyboard 5 按鈕的堆棧視圖中布局了這些屬性:

Axis: Horizontal
Alignment: Fill
Distribution: Fill Equally
Spacing: 8

(間距可根據需要更改)

試試這個代碼:

class ButtonAnimViewController: UIViewController {
    
    @IBOutlet var buttonsStackView: UIStackView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // we want the outer buttons to "slide in behind" the center button
        //  so we need to custom set their z-orders
        buttonsStackView.arrangedSubviews[0].layer.zPosition = 0
        buttonsStackView.arrangedSubviews[1].layer.zPosition = 1
        buttonsStackView.arrangedSubviews[2].layer.zPosition = 4
        buttonsStackView.arrangedSubviews[3].layer.zPosition = 3
        buttonsStackView.arrangedSubviews[4].layer.zPosition = 2
        
    }
    
    @IBAction func doCollapse(_ sender: Any) {
        // verbose for clarity
        let btn1 = buttonsStackView.arrangedSubviews[0]
        let btn2 = buttonsStackView.arrangedSubviews[1]
        let btn3 = buttonsStackView.arrangedSubviews[2]
        let btn4 = buttonsStackView.arrangedSubviews[3]
        let btn5 = buttonsStackView.arrangedSubviews[4]
        
        // calculate translationX distance for each button to the center button
        let xDistance1 = btn3.center.x - btn1.center.x
        let xDistance2 = btn3.center.x - btn2.center.x
        
        let xDistance4 = btn3.center.x - btn4.center.x
        let xDistance5 = btn3.center.x - btn5.center.x
        
        // animate the transforms
        UIView.animate(withDuration: 0.3) {
            btn1.transform = CGAffineTransform(translationX: xDistance1, y: 0.0)
            btn2.transform = CGAffineTransform(translationX: xDistance2, y: 0.0)
            btn4.transform = CGAffineTransform(translationX: xDistance4, y: 0.0)
            btn5.transform = CGAffineTransform(translationX: xDistance5, y: 0.0)
        }
    }
    
    @IBAction func doExpand(_ sender: Any) {
        // verbose for clarity
        let btn1 = buttonsStackView.arrangedSubviews[0]
        let btn2 = buttonsStackView.arrangedSubviews[1]
        let btn4 = buttonsStackView.arrangedSubviews[3]
        let btn5 = buttonsStackView.arrangedSubviews[4]

        // animate transforms back to identity
        UIView.animate(withDuration: 0.3) {
            btn1.transform = .identity
            btn2.transform = .identity
            btn4.transform = .identity
            btn5.transform = .identity
        }
        
    }
    
}

編輯

作為參考, UIStackView的標准行為——在許多情況下很有幫助——是當你隱藏一個排列好的子視圖時會發生什么。

當子視圖保留時,它的框架從堆棧視圖的排列中移除

因此,例如,如果您在這樣的子視圖中有兩個視圖,前導 / 尾隨 == 40 和分布 == 填充相等:

在此處輸入圖片說明

然后你設置viewB.isHidden = true ,結果將是:

在此處輸入圖片說明

如您所見,如果您希望視圖不可見,但繼續影響布局,則需要設置其.alpha = 0而不是隱藏它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM