【问题标题】:UIStackView Hiding/UnHiding arrangedSubView issueUIStackView 隐藏/取消隐藏排列的子视图问题
【发布时间】: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 次尝试后,它不再起作用。感谢案例建议。

标签: ios swift uiview uistackview


【解决方案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 }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-23
        • 2018-12-16
        • 2017-05-31
        • 2018-03-01
        • 2018-08-19
        • 2016-02-12
        • 2019-05-31
        • 2010-11-04
        相关资源
        最近更新 更多