UIStackView 隐藏/取消隐藏排列的子视图问题

Posted

技术标签:

【中文标题】UIStackView 隐藏/取消隐藏排列的子视图问题【英文标题】:UIStackView Hiding/UnHiding arrangedSubView issue 【发布时间】:2018-05-19 10:51:15 【问题描述】:

我正在根据在 Segment Control 中点击的 Segment 隐藏和取消隐藏 dropDownView(由文本字段和按钮组成的 UIView)。以下是视图层次结构:-

以下是隐藏/取消隐藏 dropDownView 的代码:-

 private func animateView(view: UIStackView, toHidden hidden: Bool) 
    UIView.animate(withDuration: 0.25) 
    
    let firstView = view.arrangedSubviews[0]
    firstView.isHidden = hidden
    
    
func segmentValueChanged(_ sender: UISegmentedControl) 
        let segmentSelected = segmentControl.selectedSegmentIndex
        switch segmentSelected 
        case 0:
            animateView(view: mainStackView, toHidden: true)
        case 1:
         animateView(view: mainStackView, toHidden: true)
        case 2:
            animateView(view: mainStackView, toHidden: true)
        case 3:
           animateView(view: mainStackView, toHidden: false)
        default:
            break
        
    

我面临的问题是在更改段超过 10-15 次后,上述代码停止工作,并且 DropDown 视图与段控制重叠,我不知道为什么。任何有助于理解此问题的帮助表示赞赏。

我也已经尝试过1。设置需求布局, 2. setNeedsDisplay 和 3.将dropDownView的高度限制优先级从999降低 1000

【问题讨论】:

我注意到在堆栈视图中重复隐藏或取消隐藏视图似乎是累积的。尝试添加检查 isHidden 并仅在需要时更改状态:if view.isHidden view.isHidden = false if !view.isHidden view.isHidden = true 视图是 mainStackView。所以你的意思是我需要为下拉视图获取出口并检查它是否隐藏然后应用? @克里斯 是的,我想是这样 - 可能还有另一个问题,但这在一个更简单的上下文中对我有用,即在 tableview 单元格的堆栈视图中隐藏和取消隐藏排列的子视图。 您的前 3 个案例也可以表示为 case 0, 1, 2: 是的。会这样做的。然而你的建议没有奏效。 12 次尝试后,它不再起作用。感谢案例建议。 【参考方案1】:

似乎在 completionClosure 中的附加设置 isHidden 修复了该问题(Swift 5 语法):

private func animateView(view: UIStackView, toHidden hidden: Bool) 
    let firstView = view.arrangedSubviews[0]
    UIView.animate(withDuration: 0.25) 
        firstView.isHidden = hidden
        view.layoutIfNeeded()
     completion 
        firstView.isHidden = hidden
    

【讨论】:

【参考方案2】:

尝试不使用动画功能,因为 stackView 无论如何都应该动画隐藏和取消隐藏。添加隐藏状态检查并仅在必要时进行更改:

func segmentValueChanged(_ sender: UISegmentedControl) 
    let segmentSelected = segmentControl.selectedSegmentIndex
    let dropDown = mainStackView.arrangedSubviews.first!

    switch segmentSelected 
        case 0, 1, 2:
            if !dropDown.isHidden 
                dropDown.isHidden = true
            
        case 3:
            if dropDown.isHidden 
                dropDown.isHidden = false
            
        default:
            break
    


【讨论】:

这已经奏效了。我需要为下拉隐藏和取消隐藏的行为设置动画。 UIView 动画和过渡不起作用。 StackView 没有为该行为设置动画。 好的,抱歉。我需要考虑一下这个:) Np。你不必说对不起。【参考方案3】:

试试下面这个。希望能解决您的问题。

private func animateView(view: UIStackView, toHidden hidden: Bool) 
    let firstView = view.arrangedSubviews[0]
    UIView.animate(withDuration: 0.25) 
        firstView.isHidden = hidden
        view.layoutIfNeeded()
    

【讨论】:

即使我提到的代码也一切正常。继续换段 15 次,然后看看它是否有效。【参考方案4】:

以下是我实施的似乎可行的解决方案:-

private func animateView(view: UIStackView, toHidden hidden: Bool) 
        if !hidden
        
          mainStackView.insertArrangedSubview(view, at: 0)
          view.isHidden = true
          UIView.animate(withDuration: 0.25, animations: 
            view.isHidden = false
          )
         else 
            let firstView = mainStackView.arrangedSubviews[0]
            UIView.animate(withDuration: 0.25, animations: 
                if firstView == view 
                    firstView.isHidden = true
                
            , completion:  [weak self] _ in
                if firstView == view 
                    self?.mainStackView.removeArrangedSubview(firstView)
                    firstView.removeFromSuperview()
                
            )
        
    

以编程方式创建下拉视图(而不是在情节提要中创建)并在每次完成时删除相同的视图。我没有将此答案标记为正确的解决方法。我想了解为什么故事板 dropDownView 在 10-15 次尝试后失败。

【讨论】:

【参考方案5】:

我注意到,有时当您隐藏 arrangedSubview 时,它不会隐藏它的子视图,所以这里是适合我的解决方案(或者更确切地说是解决方法)(firstViewsecondView 这里是 @987654324 @ 一些UIStackView):

firstView.isHidden = false
firstView.subviews.forEach  $0.isHidden = false 

secondView.isHidden = true
secondView.subviews.forEach  $0.isHidden = true 

【讨论】:

以上是关于UIStackView 隐藏/取消隐藏排列的子视图问题的主要内容,如果未能解决你的问题,请参考以下文章

UIStackView 图层属性

取消隐藏 UIStackView 元素时的动画方向

为啥 UIStackView 调整排列的子视图的大小?

如何正确地为隐藏在 UITableViewCell 中的 UIStackView 设置动画?

当 UIStackView 更改其排列的子视图时,UITableViewCell 不会调整大小

如何在 UIStackView 内排列的子视图上设置自定义高度?