Overlapping Views in UIStackView

后端 未结 7 1678
时光说笑
时光说笑 2020-12-14 17:24

I have an horizontal stack view that I added arranged sub views to it (7 cells). Each one of the cells in the stack has a circular badge that exceeds the view boundaries (ne

相关标签:
7条回答
  • 2020-12-14 17:28

    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

    0 讨论(0)
  • 2020-12-14 17:33

    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() }
        }
      }
    
    }
    
    0 讨论(0)
  • 2020-12-14 17:35

    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()
    
    0 讨论(0)
  • 2020-12-14 17:44

    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!

    0 讨论(0)
  • 2020-12-14 17:44

    I was looking to prevent overlapping all together. I tried the sendSubviewToBack method, but all that did was shift the overlap to the other side, unsurprisingly.

    In my case, this was caused by an image view on my subview being set to scaleToFill which meant some of the image was actually overlapping the next view. My solution to this was, in my subview class (the view that was going into the stack view), was to simply enable mask to bounds

    view.maskToBounds = true

    This means that it just crops out anything that is hanging outside.

    0 讨论(0)
  • 2020-12-14 17:51

    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…

    0 讨论(0)
提交回复
热议问题