program story

뷰 사이의 가변 간격으로 UIStackView를 어떻게 만들 수 있습니까?

inputbox 2020. 12. 12. 10:42
반응형

뷰 사이의 가변 간격으로 UIStackView를 어떻게 만들 수 있습니까?


UIStackView내부에 여러 UIView가 쌓인 간단한 가로 가 있습니다. 내 목표는 뷰 사이에 가변 간격을 만드는 것입니다. "spacing"속성을 사용하여 하위 뷰 사이에 일정한 공간을 만들 수 있다는 것을 잘 알고 있습니다. 그러나 내 목표는 가변 공간을 만드는 것입니다. 가능하다면 스페이서 역할을하는 보이지 않는 뷰를 사용하지 않기를 바랍니다.

내가 생각 해낸 최선의 방법 UIViews은 별도의 으로 감싸고 내부 스택의 레이아웃 여백을 존중 UIStackView하는 layoutMarginsRelativeArrangement = YES사용 하는 것입니다. UIView이 추악한 해결 방법에 의지하지 않고 다른 사람과 비슷한 일을 할 수 있기를 바랐습니다 . 다음은 내 샘플 코드입니다.

// Create stack view
UIStackView *stackView = [[UIStackView alloc] init];
stackView.translatesAutoresizingMaskIntoConstraints = NO;
stackView.axis = UILayoutConstraintAxisHorizontal;
stackView.alignment = UIStackViewAlignmentCenter;
stackView.layoutMarginsRelativeArrangement = YES;

// Create subview
UIView *view1 = [[UIView alloc] init];
view1.translatesAutoresizingMaskIntoConstraints = NO;
// ... Add Auto Layout constraints for height / width
// ...
// I was hoping the layoutMargins would be respected, but they are not
view1.layoutMargins = UIEdgeInsetsMake(0, 25, 0, 0);

// ... Create more subviews
// UIView view2 = [[UIView alloc] init];
// ...

// Stack the subviews
[stackView addArrangedSubview:view1];
[stackView addArrangedSubview:view2];

결과는 간격을두고 서로 바로 옆에있는 뷰가있는 스택입니다.

여기에 이미지 설명 입력


iOS 11 용 업데이트, 사용자 지정 간격이있는 StackViews

Apple은 iOS 11에서 사용자 지정 간격을 설정하는 기능을 추가했습니다. 정렬 된 각 하위보기 다음에 간격을 지정하기 만하면됩니다. 불행히도 전에 간격을 지정할 수 없습니다.

stackView.setCustomSpacing(10.0, after: firstLabel)
stackView.setCustomSpacing(10.0, after: secondLabel)

자신의 견해를 사용하는 것보다 훨씬 낫습니다.

iOS 10 이하

스택 뷰에 투명 뷰를 추가하고 너비 제약을 추가 할 수 있습니다.

(레이블-UIView-레이블-UIView -Label)

계속 distribution채우면 UIViews에 가변 너비 제약 조건을 설정할 수 있습니다.

그러나 이것이 그렇다면 stackviews를 사용하는 것이 올바른 상황인지 고려할 것입니다. 자동 레이아웃을 사용하면보기간에 가변 너비를 매우 쉽게 설정할 수 있습니다.


SWIFT 4

lilpit 대답에 따라 여기에 UIStackView의 확장이 있습니다.

extension UIStackView {
    func addCustomSpacing(top: CGFloat, bottom: CGFloat) {

        //If the stack view has just one arrangedView, we add a dummy one
        if self.arrangedSubviews.count == 1 {
            self.insertArrangedSubview(UIView(frame: .zero), at: 0)
        }

        //Getting the second last arrangedSubview and the current one
        let lastTwoArrangedSubviews = Array(self.arrangedSubviews.suffix(2))
        let arrSpacing: [CGFloat] = [top, bottom]

        //Looping through the two last arrangedSubview to add spacing in each of them
        for (index, anArrangedSubview) in lastTwoArrangedSubviews.enumerated() {

            //After iOS 11, the stackview has a native method
            if #available(iOS 11.0, *) {
                self.setCustomSpacing(arrSpacing[index], after: anArrangedSubview)
                //Before iOS 11 : Adding dummy separator UIViews
            } else {
                guard let arrangedSubviewIndex = arrangedSubviews.firstIndex(of: anArrangedSubview) else {
                    return
                }

                let separatorView = UIView(frame: .zero)
                separatorView.translatesAutoresizingMaskIntoConstraints = false

                //calculate spacing to keep a coherent spacing with the ios11 version
                let isBetweenExisitingViews = arrangedSubviewIndex != arrangedSubviews.count - 1
                let existingSpacing = isBetweenExisitingViews ? 2 * spacing : spacing
                let separatorSize = arrSpacing[index] - existingSpacing

                guard separatorSize > 0 else {
                    return
                }

                switch axis {
                case .horizontal:
                    separatorView.widthAnchor.constraint(equalToConstant: separatorSize).isActive = true
                case .vertical:
                    separatorView.heightAnchor.constraint(equalToConstant: separatorSize).isActive = true
                }

                insertArrangedSubview(separatorView, at: arrangedSubviewIndex + 1)
            }
        }
    }
}

그런 다음 다음과 같이 사용합니다.

//Creating label to add to the UIStackview
let label = UILabel(frame: .zero)

//Adding label to the UIStackview
stackView.addArrangedSubview(label)

//Create margin on top and bottom of the UILabel
stackView.addCustomSpacing(top: 40, bottom: 100)

From Rob's response I created a UIStackView extension that might help:

extension UIStackView {
  func addCustomSpacing(_ spacing: CGFloat, after arrangedSubview: UIView) {
    if #available(iOS 11.0, *) {
      self.setCustomSpacing(spacing, after: arrangedSubview)
    } else {
      let separatorView = UIView(frame: .zero)
      separatorView.translatesAutoresizingMaskIntoConstraints = false
      switch axis {
      case .horizontal:
        separatorView.widthAnchor.constraint(equalToConstant: spacing).isActive = true
      case .vertical:
        separatorView.heightAnchor.constraint(equalToConstant: spacing).isActive = true
      }
      if let index = self.arrangedSubviews.firstIndex(of: arrangedSubview) {
        insertArrangedSubview(separatorView, at: index + 1)
      }
    }
  }
}

You can use and modify it any way you want, for exemplo if you want the "separatorView" reference, you can just return the UIView:

  func addCustomSpacing(_ spacing: CGFloat, after arrangedSubview: UIView) -> UIView?

I created a library LRCustomSpacingStackView to support UIStackView custom spacing on iOS 9 and above.

Simply replace UIStackView's builtin methods in your code with this library's extension methods, and specify spacing by setting any subview's lr_stackSpacing property:

import LRCustomSpacingStackView
stackView.lr_addArrangedSubview(view1)
view1.lr_stackSpacing = UIEdgeInsets(top: 20, left: 30, bottom: 10, right: 0)

All UIStackView's methods have their replacements:

lr_arrangedSubviews for arrangedSubviews

lr_addArrangedSubview(_:) for addArrangedSubview(_:)

lr_removeArrangedSubview(_:) for removeArrangedSubview(_:)

lr_insertArrangedSubview(_:at:) for insertArrangedSubview(_:at:)

lr_stackSpacing is more flexible and powerful than setCustomSpacing(_:after:). You are able to specify spacing of a view in 4 directions: top, right, bottom, left.

참고 URL : https://stackoverflow.com/questions/32999159/how-can-i-create-uistackview-with-variable-spacing-between-views

반응형