【问题标题】:Overlapping Views in UIStackViewUIStackView 中的重叠视图
【发布时间】:2016-04-21 23:27:41
【问题描述】:

我有一个水平堆栈视图,我向其中添加了排列的子视图(7 个单元格)。 堆栈中的每个单元格都有一个超出视图边界的圆形标志(负约束)。 运行时,如下所示,每个单元格都位于前一个单元格的徽章之上。我想更改顺序,以便徽章完全可见。

尝试使用 Z 索引,但没有帮助,因为图层不平坦,正如您在以下视图层次结构中看到的那样:

有什么想法或建议吗?

谢谢。

【问题讨论】:

  • 您也可以通过在单个框子视图上设置清晰的背景来做到这一点,但堆栈视图使用白色背景。

标签: ios uistackview


【解决方案1】:

documentation for the UIStackView class 告诉我们:

子视图数组的顺序定义了子视图的 Z 顺序。如果视图重叠,索引较低的子视图会出现在索引较高的子视图后面。

这正是我在这个问题中所经历的。为了解决我的具体情况,我将视图的语义更改为 RTL,如下所示:

这不涵盖一般情况,因为设备可能已在其全局设置中设置了 RTL 语言。对于一般情况,我想我需要检查接口语义并强制与我的堆栈视图相反。

附言这是一种 hack,因此任何关于如何以不同方式重新排列子视图的 Z 顺序的想法都将受到欢迎!

【讨论】:

    【解决方案2】:

    另一个想法可能是将子视图(7 个单元格)的背景颜色设置为默认值(完全透明)。并且只将堆栈视图本身的背景设置为白色

    我有一个类似的问题,但每个子视图都必须有特定的背景。就我而言,您的 hack 可能会有所帮助……? 谢谢!

    【讨论】:

      【解决方案3】:

      从 iOS 9.0 开始,可以独立设置堆栈视图子视图的 z 顺序和排列。使用新的arrangedSubviews 属性来指定沿堆栈视图轴的子视图排列。并使用subviews 属性根据它们在数组中的索引来指定子视图的z-order。

      堆栈视图确保其arrangedSubviews 属性始终是其subviews 属性的子集。

      Documentation for arrangedSubviews

      【讨论】:

      • 有关更改视图 z 顺序而不是排列顺序的快速示例,您可以执行类似 stackView.insertSubview(stackView.arrangedSubviews[0], at: 1) 的操作,这将交换第一个和第二个项目的绘制顺序,但不交换它们的显示顺序跨度>
      • 看起来它会在你的子视图中插入一个重复的视图给我
      【解决方案4】:

      下面是UIStackView 上的一个简单扩展,用于反转UIStackView 的子视图的z-index 并可选地要求布局:

      extension UIStackView {
      
        func reverseSubviewsZIndex(setNeedsLayout: Bool = true) {
          let stackedViews = self.arrangedSubviews
      
          stackedViews.forEach {
            self.removeArrangedSubview($0)
            $0.removeFromSuperview()
          }
      
          stackedViews.reversed().forEach(addSubview(_:))
          stackedViews.forEach(addArrangedSubview(_:))
      
          if setNeedsLayout {
            stackedViews.forEach { $0.setNeedsLayout() }
          }
        }
      
      }
      

      【讨论】:

      • 太棒了!谢谢一百万!
      【解决方案5】:

      此 Swift 解决方案使用 UIView 方法 sendSubviewToBack(_:) (docs here) 反转堆栈视图子视图顺序:

      @IBOutlet weak var stackView: UIStackView!
      
      for view in stackView.arrangedSubviews {
          stackView.sendSubviewToBack(view)
      }
      

      随着我们在堆栈视图的排列视图中前进(从下到上),后面的(即更高的)视图被推到底部,从而颠倒顺序:-)

      【讨论】:

        【解决方案6】:

        当您添加子视图时,以编程方式添加高度和宽度恒定约束。最后调用 StackView 的 setNeedsLayout。它将计算并尝试使用间距调整视图

        经过各种尝试,我能够使其水平

         stackView.leadingAnchor.constraint(equalTo: stackScrollView.leadingAnchor).isActive = true
         stackView.trailingAnchor.constraint(equalTo: stackScrollView.trailingAnchor).isActive = true
         stackView.bottomAnchor.constraint(equalTo: stackScrollView.bottomAnchor).isActive = true
         stackView.heightAnchor.constraint(equalTo: stackScrollView.heightAnchor).isActive = true
        
         stackView.distribution = .equalSpacing
         stackView.spacing = 5
         stackView.axis = .horizontal
         stackView.alignment = .fill
        
        
         for i in 0 ..< images.count {
             let photoView = UIButton.init(frame: CGRect(x: 0, y: 0, width: 85, height: 85))
        
             // set button image
             photoView.translatesAutoresizingMaskIntoConstraints = false
             photoView.heightAnchor.constraint(equalToConstant: photoView.frame.height).isActive = true
             photoView.widthAnchor.constraint(equalToConstant: photoView.frame.width).isActive = true
        
             stackView.addArrangedSubview(photoView)
         }
        
         stackView.setNeedsLayout()
        

        【讨论】:

          【解决方案7】:

          我希望防止所有内容重叠在一起。 我尝试了sendSubviewToBack 方法,但所做的只是将重叠转移到另一边,这并不奇怪。

          在我的情况下,这是由于我的子视图上的图像视图设置为 scaleToFill 这意味着某些图像实际上与下一个视图重叠。我对此的解决方案是,在我的子视图类(进入堆栈视图的视图)中,只需启用掩码到边界

          view.maskToBounds = true

          这意味着它只会剪掉任何挂在外面的东西。

          【讨论】:

            【解决方案8】:

            在我的情况下,UIStackView 位于 UITableViewCell 内,而我正把头发拉出来,为什么单元格会重叠。这是 prepareForReuse() 的解决方法

            extension UIStackView
            {
              func wipeClean() {
                arrangedSubviews.forEach {removeArrangedSubview($0)
                  // removeArrangedSubview does not removeFromSuperview
                  // hence do the explicit
                                          $0.removeFromSuperview() }
              }
            }
            

            大约两天浪费导致 removeArrangedSubview 不暗示 removeFromSuperview

            L 表示逻辑: 视图不参与堆栈布局,但显示在屏幕上。我会对 Apple 认为这可能有用的地方感兴趣。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-05-12
              • 2019-05-31
              • 1970-01-01
              • 1970-01-01
              • 2017-09-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多