[英]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.