UIStackView 中的重叠视图
Overlapping Views in UIStackView
我有一个水平堆栈视图,我向其中添加了排列好的子视图(7 个单元格)。
堆栈中的每个单元格都有一个超出视图边界的圆形标记(负约束)。
当 运行 时,如下所示,每个单元格都位于前一个单元格的标记之上。我想更改顺序 以便徽章完全可见。
尝试使用 Z 索引但没有帮助,因为图层在某种程度上并不平坦,正如您在以下视图层次结构中看到的那样:
有什么想法或建议吗?
谢谢。
documentation for the UIStackView class 表示:
The order of the subviews array defines the Z-order of the subviews. If the views overlap, subviews with a lower index appear behind subviews with a higher index.
这正是我在问题中所经历的。为了克服我的具体情况,我采用了将视图的语义更改为 RTL 的技巧,如下所示:
这不涵盖一般情况,因为设备可能已在其全局设置中设置了 RTL 语言。对于一般情况,我想我需要检查接口语义并强制向我的堆栈视图相反的方向。
P.S。这是一种 hack,因此欢迎任何关于如何以不同方式重新排序 Z-order 子视图的想法!
另一个想法可能是将子视图(7 个单元格)的背景颜色设置为默认值(完全透明)。并且只将 堆栈视图本身的背景设置为白色 .
我有一个类似的问题,但每个子视图都必须有特定的背景。就我而言,您的技巧可能会有所帮助……谢谢!
从 iOS 9.0 开始,可以独立设置堆栈视图子视图的 z 顺序和排列。使用新的 arrangedSubviews
属性 指定沿堆栈视图轴的子视图排列。并使用 subviews
属性 根据数组中的索引指定子视图的 z 顺序。
堆栈视图确保其 arrangedSubviews
属性 始终是其 subviews
属性.
的子集
下面是 UIStackView
上的一个简单扩展,用于反转 UIStackView
子视图的 z-index 并可选择要求布局:
extension UIStackView {
func reverseSubviewsZIndex(setNeedsLayout: Bool = true) {
let stackedViews = self.arrangedSubviews
stackedViews.forEach {
self.removeArrangedSubview([=10=])
[=10=].removeFromSuperview()
}
stackedViews.reversed().forEach(addSubview(_:))
stackedViews.forEach(addArrangedSubview(_:))
if setNeedsLayout {
stackedViews.forEach { [=10=].setNeedsLayout() }
}
}
}
此 Swift 解决方案使用 UIView 方法反转堆栈视图子视图顺序 sendSubviewToBack(_:)
(docs here):
@IBOutlet weak var stackView: UIStackView!
for view in stackView.arrangedSubviews {
stackView.sendSubviewToBack(view)
}
当我们推进堆栈视图的排列视图(从下到上)时,后面的(即更高的)视图被推到底部,从而颠倒顺序:-)
2022 年的事情:
甚至Swift更高...
@IBOutlet weak var stackView: UIStackView!
stackView.arrangedSubviews.forEach({ stackView.sendSubviewToBack([=11=]) })
在添加子视图时以编程方式添加高度和宽度常量约束。最后调用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()
我一直在寻找防止重叠在一起的方法。
我尝试了 sendSubviewToBack
方法,但不出所料,所做的只是将重叠转移到另一侧。
在我的例子中,这是由于我的子视图上的图像视图被设置为 scaleToFill
,这意味着某些图像实际上与下一个视图重叠。我对此的解决方案是,在我的子视图 class(进入堆栈视图的视图)中,简单地启用掩码到边界
view.maskToBounds = true
这意味着它只会裁掉挂在外面的任何东西。
在我的例子中,UIStackView 位于 UITableViewCell 内部,我一直在想为什么单元格会重叠。这是prepareForReuse()
的治疗方法:
extension UIStackView
{
func wipeClean() {
arrangedSubviews.forEach {
removeArrangedSubview([=10=])
// removeArrangedSubview does not removeFromSuperview
// hence do the explicit
[=10=].removeFromSuperview() }
}
}
大约浪费了两天因为removeArrangedSubview
并不意味着
removeFromSuperview
.
L 代表逻辑:
该视图不参与堆栈布局,但显示在屏幕上。我对 Apple 认为这可能有用的地方感兴趣。
我有一个水平堆栈视图,我向其中添加了排列好的子视图(7 个单元格)。 堆栈中的每个单元格都有一个超出视图边界的圆形标记(负约束)。 当 运行 时,如下所示,每个单元格都位于前一个单元格的标记之上。我想更改顺序 以便徽章完全可见。
尝试使用 Z 索引但没有帮助,因为图层在某种程度上并不平坦,正如您在以下视图层次结构中看到的那样:
有什么想法或建议吗?
谢谢。
documentation for the UIStackView class 表示:
The order of the subviews array defines the Z-order of the subviews. If the views overlap, subviews with a lower index appear behind subviews with a higher index.
这正是我在问题中所经历的。为了克服我的具体情况,我采用了将视图的语义更改为 RTL 的技巧,如下所示:
这不涵盖一般情况,因为设备可能已在其全局设置中设置了 RTL 语言。对于一般情况,我想我需要检查接口语义并强制向我的堆栈视图相反的方向。
P.S。这是一种 hack,因此欢迎任何关于如何以不同方式重新排序 Z-order 子视图的想法!
另一个想法可能是将子视图(7 个单元格)的背景颜色设置为默认值(完全透明)。并且只将 堆栈视图本身的背景设置为白色 .
我有一个类似的问题,但每个子视图都必须有特定的背景。就我而言,您的技巧可能会有所帮助……谢谢!
从 iOS 9.0 开始,可以独立设置堆栈视图子视图的 z 顺序和排列。使用新的 arrangedSubviews
属性 指定沿堆栈视图轴的子视图排列。并使用 subviews
属性 根据数组中的索引指定子视图的 z 顺序。
堆栈视图确保其 arrangedSubviews
属性 始终是其 subviews
属性.
下面是 UIStackView
上的一个简单扩展,用于反转 UIStackView
子视图的 z-index 并可选择要求布局:
extension UIStackView {
func reverseSubviewsZIndex(setNeedsLayout: Bool = true) {
let stackedViews = self.arrangedSubviews
stackedViews.forEach {
self.removeArrangedSubview([=10=])
[=10=].removeFromSuperview()
}
stackedViews.reversed().forEach(addSubview(_:))
stackedViews.forEach(addArrangedSubview(_:))
if setNeedsLayout {
stackedViews.forEach { [=10=].setNeedsLayout() }
}
}
}
此 Swift 解决方案使用 UIView 方法反转堆栈视图子视图顺序 sendSubviewToBack(_:)
(docs here):
@IBOutlet weak var stackView: UIStackView!
for view in stackView.arrangedSubviews {
stackView.sendSubviewToBack(view)
}
当我们推进堆栈视图的排列视图(从下到上)时,后面的(即更高的)视图被推到底部,从而颠倒顺序:-)
2022 年的事情:
甚至Swift更高...
@IBOutlet weak var stackView: UIStackView!
stackView.arrangedSubviews.forEach({ stackView.sendSubviewToBack([=11=]) })
在添加子视图时以编程方式添加高度和宽度常量约束。最后调用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()
我一直在寻找防止重叠在一起的方法。
我尝试了 sendSubviewToBack
方法,但不出所料,所做的只是将重叠转移到另一侧。
在我的例子中,这是由于我的子视图上的图像视图被设置为 scaleToFill
,这意味着某些图像实际上与下一个视图重叠。我对此的解决方案是,在我的子视图 class(进入堆栈视图的视图)中,简单地启用掩码到边界
view.maskToBounds = true
这意味着它只会裁掉挂在外面的任何东西。
在我的例子中,UIStackView 位于 UITableViewCell 内部,我一直在想为什么单元格会重叠。这是prepareForReuse()
的治疗方法:
extension UIStackView
{
func wipeClean() {
arrangedSubviews.forEach {
removeArrangedSubview([=10=])
// removeArrangedSubview does not removeFromSuperview
// hence do the explicit
[=10=].removeFromSuperview() }
}
}
大约浪费了两天因为removeArrangedSubview
并不意味着
removeFromSuperview
.
L 代表逻辑: 该视图不参与堆栈布局,但显示在屏幕上。我对 Apple 认为这可能有用的地方感兴趣。