뷰 사이의 가변 간격으로 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.
'program story' 카테고리의 다른 글
클래스 및 인스턴스 메서드의 차이점 (0) | 2020.12.12 |
---|---|
사용중인 Play 버전을 확인하는 방법은 무엇입니까? (0) | 2020.12.12 |
모든 Java 바이트가 서명된다는 사실을 해결하는 가장 좋은 방법은 무엇입니까? (0) | 2020.12.12 |
여러 SVN 저장소를 하나로 결합 (0) | 2020.12.12 |
순수한 C로 RAII를 구현합니까? (0) | 2020.12.12 |