繁体   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