Overlapping Views in UIStackView

点点圈 提交于 2019-11-28 23:27:27

The documentation for the UIStackView class tells that:

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.

which is exactly what I experienced in the question. To over come my specific case I did the trick of changing the semantic of the view to be RTL as can bee seen here:

This is not covering the a generic case because a device may have been set a RTL language in its global settings. For the generic case I guess I will need to check the interface semantic and force an opposite direction to my stack view.

P.S. It's kind of hack so any ideas about how to reorder the Z-order of subviews in a different way will be most welcome!

future-adam

This Swift solution reverses the stack view subview order using the UIView method sendSubviewToBack(_:) (docs here):

@IBOutlet weak var stackView: UIStackView!

for view in stackView.arrangedSubviews {
    stackView.sendSubviewToBack(view)
}

As we advance through the stack view's arranged views (from bottom to top), the later (i.e. higher) views get pushed to the bottom, thereby reversing the order :-)

Since iOS 9.0 it's possible to set the z-order and arrangement of stack view subviews independently. Use the new arrangedSubviews property to specify the subviews arrangement along the stack view’s axis. And use subviews property to specify subviews z-order based on their index in the array.

The stack view ensures that its arrangedSubviews property is always a subset of its subviews property.

Documentation for arrangedSubviews

An other idea could be to set background color of the subviews (7 cells) to default (fully transparent). And only set the background of the stack view itself to white.

I have a similar issue but where every subview has to have a specific background. And in my case, your hack might help… 😉 Thanks for it!

Below is a simple extension on UIStackView to reverse the z-index of the UIStackView's subviews and optionally require layout:

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() }
    }
  }

}
user1039695

Programmatically when you add the subview, add height and width constant constraints. In the end call StackView's setNeedsLayout. It will calculate and try to adjust the views with spacing

After various attempts i am able to make it horizontally

 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()
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!