在 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 色调颜色?

IOS、UIView、检测子视图隐藏状态变化

iOS 9 上的 Safari 不会触发隐藏输入文件的点击事件

在iOS 7中隐藏导航栏时,如何更改状态栏的颜色?

在 iOS 9 的一个视图控制器上隐藏状态栏

检测 iOS-WebApp 并更改 CSS 属性