在 iOS 9 上更改隐藏属性时 UIStackView 不会动画
Posted
技术标签:
【中文标题】在 iOS 9 上更改隐藏属性时 UIStackView 不会动画【英文标题】:UIStackView won't animate when changing the hidden property on iOS 9 【发布时间】:2016-11-16 18:21:18 【问题描述】:我正在使用 Stack 视图来创建一种表格 UI,我在 StackView 中有 6 个视图,其中 0、2、4 是可见的,而 1、3、5 是隐藏的。当点击其中一个可见视图时,我希望“打开”其中一个隐藏的视图。
我的这段代码在 ios 10 上运行良好,但由于某种原因我无法理解它在 iOS 9 上运行不佳。
请注意,如果我加载所有打开的视图,关闭动画将起作用,但在将 hidden 属性设置为 false 时它不会打开。
这是我的代码 -
编辑 经过一些调试,看起来视图高度约束也没有从隐藏中恢复,它的框架仍然是高度为0。
import UIKit
class DeckView: UIView
class ViewController: UIViewController
var scrollView: UIScrollView!
var stackView: UIStackView!
override func viewDidLoad()
super.viewDidLoad()
scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: .alignAllCenterX, metrics: nil, views: ["scrollView": scrollView]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView]|", options: .alignAllCenterX, metrics: nil, views: ["scrollView": scrollView]))
stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.spacing = 0
stackView.alignment = .center
stackView.distribution = .fillProportionally
stackView.axis = .vertical
scrollView.addSubview(stackView)
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[stackView]|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: ["stackView": stackView]))
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[stackView]|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: ["stackView": stackView]))
for i in 0 ..< 8
let view = DeckView()
view.tag = i
view.translatesAutoresizingMaskIntoConstraints = false
view.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
view.isUserInteractionEnabled = true
if i%2 == 0
view.backgroundColor = UIColor.magenta
let constriant = view.heightAnchor.constraint(equalToConstant:160)
constriant.priority = 999
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.openDeck(_:))))
view.addConstraint(constriant)
else
view.backgroundColor = UIColor.red
let constriant = view.heightAnchor.constraint(equalToConstant:160)
constriant.priority = 999
view.addConstraint(constriant)
view.isHidden = false
stackView.addArrangedSubview(view)
func openDeck(_ sender:UIGestureRecognizer)
if let view = sender.view as? DeckView,
let childView = stackView.viewWithTag(view.tag + 1)
UIView.animate(withDuration: 0.4, animations:
childView.isHidden = !childView.isHidden
)
【问题讨论】:
【参考方案1】:-
保持视图的高度优先级低于 1000(选择 999)。
如果
setHidden:true
已经隐藏,不要设置(这是UIStackView的bug)
【讨论】:
Baaaam 你救了我的命!!!这个错误记录在哪里?!你能在这里发一个链接吗?我需要在我的代码中记录这个... 对此我感激不尽。 2015 年的 problem(雷达 UIStackView: toggleing hidden with animations gets stuck in hidden mode 和 Calling setHidden:NO on a subview of UIStackView does not always show it 应 @blackjacx 要求)和步骤 2 中的 solution 在 2017 年 8 月仍然有效。我应该提一下我不需要执行第 1 步(distribution = .fill
对我来说很好)。这个错误显然与动画有关,因为当我立即切换isHidden
时它没有出现。
This article 和this article 很好地解释了vats 步骤1 的推理。总结:“基本上,这里发生的是垂直堆栈视图将自动设置视图的高度到 0 px 以隐藏它。但是,如果它具有冲突的约束,例如可能试图保持它的填充,例如 16 px 高,那么您将需要降低这些约束的优先级以允许将其缩短到 0 px 高度隐藏时。”
@vats This isHidden 动画错误已经困扰我好几个星期了。非常感谢!
这在 iOS 13 中仍然是一个东西 -_____________________-'【参考方案2】:
如果有人偶然发现了这个问题。
我能够通过删除 -
来解决这个问题stackView.distribution = .fillProportionally
我不确定为什么会发生这种情况,但我发现 Autolayout 添加了一个名为“UISV-fill-proportionally”的高度约束,常量为 0,优先级高于我的高度约束。删除 fillProportionally 解决了这个问题。
【讨论】:
以上是关于在 iOS 9 上更改隐藏属性时 UIStackView 不会动画的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 9 中更改 UITabBarItem 色调颜色?