UIStackView에 더 많은 뷰를 추가하여 표시 할 수 있다고 가정 해 봅시다. UIStackView
스크롤을 만드는 방법은 무엇입니까?
UIStackView에 더 많은 뷰를 추가하여 표시 할 수 있다고 가정 해 봅시다. UIStackView
스크롤을 만드는 방법은 무엇입니까?
답변:
누구나 코드가없는 솔루션 을 찾고있는 경우 자동 레이아웃을 사용하여 스토리 보드에서 완전히 수행하는 예제를 만들었습니다.
github 에서 얻을 수 있습니다 .
기본적으로 예제를 다시 만들려면 (수직 스크롤) :
UIScrollView
만들고 제약 조건을 설정 하십시오 .UIStackView
받는UIScrollView
Leading
, Trailing
, Top
및 Bottom
의 것과 동일해야UIScrollView
Width
사이에 동일한 제한 조건을 설정하십시오 .UIStackView
UIScrollView
UIStackView
UIViews
하십시오UIStackView
4 단계에서 교환 Width
하고 5 단계에서 = 를 Height
설정 하여 수평 UIStackView를 가져 오십시오.Axis
Horizontal
Apple의 자동 레이아웃 안내서에는 스크롤보기 작업 에 관한 전체 섹션이 포함되어 있습니다. 관련 스 니펫 :
- 컨텐츠 뷰의 위쪽, 아래쪽, 앞쪽 및 뒤쪽 가장자리를 스크롤보기의 해당 가장자리에 고정합니다. 컨텐츠 뷰는 이제 스크롤 뷰의 컨텐츠 영역을 정의합니다.
- (선택 사항) 가로 스크롤을 비활성화하려면 컨텐츠보기의 너비를 스크롤보기의 너비와 동일하게 설정하십시오. 컨텐츠보기가 이제 스크롤보기를 가로로 채 웁니다.
- (선택 사항) 세로 스크롤을 비활성화하려면 컨텐츠보기의 높이를 스크롤보기의 높이와 동일하게 설정하십시오. 컨텐츠보기가 이제 스크롤보기를 가로로 채 웁니다.
더욱이:
레이아웃은 컨텐츠보기의 크기를 완전히 정의해야합니다 (5 및 6 단계에서 정의 된 경우 제외). … 컨텐츠보기가 스크롤보기보다 크면 스크롤보기에서 세로 스크롤이 가능합니다. 컨텐츠보기가 스크롤보기보다 넓은 경우, 스크롤보기는 가로 스크롤을 가능하게합니다.
(이 경우, 스택보기) 스크롤 뷰의 콘텐츠보기를 모서리에 고정되어야 요약하면 그리고 그 폭 및 / 또는 높이가 달리 제한이있다. 즉, 스택보기의 내용은 스크롤이 필요한 방향으로 (직접 또는 간접적으로) 제한되어야합니다. 예를 들어 세로 스크롤 스택보기의 각보기에 높이 제한을 추가 할 수 있습니다. 다음은 스택보기가 포함 된 스크롤보기의 세로 스크롤을 허용하는 방법의 예입니다.
// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
Need constraints for: Y position or height.
에서이 오류가 발생합니다 . 이 오류는 스택보기에 너비와 높이 제약 조건을 모두 설정 한 경우에만 사라져 세로 스크롤을 비활성화합니다. 이 코드는 여전히 당신을 위해 작동합니까?
여기에서 가장 인기있는 답변의 제약 조건이 저에게 도움이되었으며 스토리 보드에서 만든대로 제약 조건의 이미지를 붙여 넣었습니다.
다른 사람들이 알아야 할 두 가지 문제가 발생했습니다.
허용 된 답변과 비슷한 제약 조건을 추가하면 빨간색 자동 레이아웃 오류가 발생 Need constraints for: X position or width
합니다. 이는 스택 뷰의 하위 뷰로 UILabel을 추가하여 해결되었습니다.
프로그래밍 방식으로 하위 뷰를 추가하고 있으므로 원래 스토리 보드에 하위 뷰가 없었습니다. 자동 레이아웃 오류를 제거하려면 스토리 보드에 서브 뷰를 추가 한 다음 실제 서브 뷰 및 제약 조건을 추가하기 전에로드시 제거하십시오.
원래 UIButtons
UIStackView 에 추가하려고했습니다 . 버튼과 뷰는로드되지만 스크롤 뷰는 스크롤되지 않습니다 . 이것은 UILabels
버튼 대신 스택 뷰 에 추가함으로써 해결되었습니다 . 동일한 제약 조건을 사용하면 UILabels가있는이 뷰 계층 구조는 스크롤되지만 UIButton은 그렇지 않습니다.
UIButtons가 나는,이 문제로 혼란스러워하고있어 않습니다 (스택보기에서 사용)를 IntrinsicContentSize을 갖고있는 것 같다. 버튼이 작동하지 않는 이유를 아는 사람이 있다면 이유를 알고 싶습니다.
다음은 참조를위한 뷰 계층 구조 및 제약 조건입니다.
아이크는 말한다으로 UIStackView
하고 UIScrollView
친절하게 함께 플레이를 참조하십시오 여기 .
핵심은 UIStackView
핸들이 다른 내용에 대한 가변 높이 / 너비를 처리 UIScrollView
한 다음 해당 내용을 스크롤 / 수신 거부하는 작업을 잘 수행한다는 것입니다.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)
}
나는 똑같은 일을하려고했고이 훌륭한 지위를 우연히 발견했다 . 앵커 API를 사용하여 프로그래밍 방식으로이 작업을 수행하려면이 방법을 사용하십시오.
요약하면, 당신을 포함 UIStackView
하여에 UIScrollView
, 그리고의 앵커 제약 조건을 설정할 UIStackView
의 일치하도록 UIScrollView
:
stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
빈 화면 전체 화면
스크롤보기를 추가하십시오. 스크롤보기 에서 기본보기로 Control- 드래그하고 왼쪽-오른쪽 위-아래를 모두 0으로 추가하십시오.
스크롤보기에서 스택보기를 추가하십시오. 스택보기 에서 스크롤보기로 Control- 드래그하고 왼쪽-오른쪽 위-아래를 모두 0으로 추가하십시오.
스택보기 안에 2 개 또는 3 개의 레이블을 넣습니다.
명확성을 위해 레이블의 배경색을 빨간색으로 지정하십시오. 라벨 높이를 100으로 설정하십시오.
이제 각 UILabel 의 너비 를 설정하십시오 .
놀랍게도에서 컨트롤 드래그 UILabel
스크롤 뷰, 하지 스택보기가 하여 동일한 너비를 선택하십시오 .
반복하려면
그렇게 간단합니다. 그것이 비밀입니다.
비밀 팁-Apple 버그 :
그것은 작동하지 않습니다 하나 개의 항목에! 데모가 작동하도록 몇 가지 레이블을 추가하십시오.
끝났습니다.
팁 : 모든 새 항목에 높이를 추가해야합니다 . 스크롤 스택보기의 모든 항목은 고유 크기 (예 : 레이블)를 갖거나 명시 적 높이 제한을 추가해야합니다.
다른 접근법 :
위의 내용에서 놀랍게도 UILabels의 너비를 스크롤보기 (스택보기가 아닌)의 너비로 설정하십시오.
번갈아...
따라서 두 가지 옵션이 있습니다.
또는
명확하게하기 위해, 이들 방법 중 하나를 수행하십시오. 둘 다 수행하지 마십시오.
가로 스크롤 용. 먼저 a UIStackView
와 a UIScrollView
를 만들고 다음과 같은 방법으로 뷰에 추가하십시오.
let scrollView = UIScrollView()
let stackView = UIStackView()
scrollView.addSubview(stackView)
view.addSubview(scrollView)
을 설정 기억 translatesAutoresizingMaskIntoConstraints
에 false
온 UIStackView
과 UIScrollView
:
stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false
후행, 선행, 상단 및 하단 앵커에서 작동하는 모든 것이 앵커와 UIStackView
같아야합니다 UIScrollView
.
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
그러나의 너비 앵커는 앵커 너비 UIStackView
와 같거나 커야합니다 UIScrollView
.
stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true
이제 UIScrollView
예를 들어을 고정하십시오 .
scrollView.heightAnchor.constraint(equalToConstant: 80).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo:view.trailingAnchor).isActive = true
다음으로 UIStackView
정렬 및 분포에 대해 다음 설정을 시도하는 것이 좋습니다 .
topicStackView.axis = .horizontal
topicStackView.distribution = .equalCentering
topicStackView.alignment = .center
topicStackView.spacing = 10
마지막 addArrangedSubview:
으로이 메소드 를 사용 하여 UIStackView에 서브 뷰를 추가해야합니다.
당신이 유용하다는 사실을 발견 한 추가 기능은이 때문이다 UIStackView
내에서 개최되는 UIScrollView
지금 상황이 조금 더 예뻐 보이게하는 문자 세트에 액세스 할 수 있습니다.
let inset:CGFloat = 20
scrollView.contentInset.left = inset
scrollView.contentInset.right = inset
// remember if you're using insets then reduce the width of your stack view to match
stackView.widthAnchor.constraint(greaterThanOrEqualTo: topicScrollView.widthAnchor, constant: -inset*2).isActive = true
이것을 다음에 추가하십시오 viewdidload
:
let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets
당신은 ScrollableStackView 를 시도 할 수 있습니다 : https://github.com/gurhub/ScrollableStackView
Objective-C 및 Swift 호환 라이브러리입니다. CocoaPods를 통해 사용할 수 있습니다 .
샘플 코드 (Swift)
import ScrollableStackView
var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)
// add your views with
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...
샘플 코드 (Objective-C)
@import ScrollableStackView
ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];
UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];
// add your views with
[scrollable.stackView addArrangedSubview:rectangle];
// ...
수직 스택 뷰 / 스크롤 뷰의 예 ( EasyPeasy
자동 레이아웃에 사용) :
let scrollView = UIScrollView()
self.view.addSubview(scrollView)
scrollView <- [
Edges(),
Width().like(self.view)
]
let stackView = UIStackView(arrangedSubviews: yourSubviews)
stackView.axis = .vertical
stackView.distribution = .fill
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView <- [
Edges(),
Width().like(self.view)
]
각 서브 뷰의 높이가 정의되어 있는지 확인하십시오!
가장 먼저 스케치와 같은 방식으로 뷰를 디자인하거나 스크롤 가능한 컨텐츠로 무엇을 원하는지에 대한 아이디어를 얻으십시오.
그런 다음 뷰 컨트롤러를 자유 형식으로 만들고 (속성 관리자에서 선택) 뷰의 고유 컨텐츠 크기 (크기 관리자에서 선택)에 따라 높이와 너비를 설정하십시오.
뷰 컨트롤러 에서이 스크롤보기를 넣고 이것은 iOS에서 거의 항상 작동하는 것으로 밝혀진 논리입니다 (명령을 통해 얻을 수있는 뷰 클래스의 문서를 통과해야 할 수도 있습니다 + 클릭) 해당 수업 또는 인터넷 검색을 통해)
두 개 이상의보기로 작업하는 경우 먼저 이전에 소개되었거나 더 원시적 인보기로 시작한 다음 나중에 소개되었거나 더 현대적인보기로 이동하십시오. 스크롤보기가 먼저 소개되었으므로 먼저 스크롤보기로 시작한 다음 스택보기로 이동하십시오. 여기에는 스크롤보기 제약 조건이 슈퍼보기에 비해 모든 방향으로 0이됩니다. 모든 스크롤보기를이 스크롤보기 안에 넣고 스택보기에 넣으십시오.
스택 뷰로 작업하는 동안
먼저지면 위로 (아래쪽으로 접근) 시작하십시오. 즉, 뷰에 레이블, 텍스트 필드 및 이미지가있는 경우 이러한 뷰를 먼저 (스크롤 뷰 내부) 배치 한 다음 스택 뷰에 배치하십시오.
그 후 스택보기의 속성을 조정하십시오. 원하는보기가 여전히 이루어지지 않으면 다른 스택보기를 사용하십시오.
뷰를 만든 후에는 마더 스택 뷰와 스크롤 뷰 사이에 제약 조건을 설정하고, 하위 스택 뷰는 마더 스택 뷰와 함께 제약 조건 하위 스택 뷰를 갖습니다. 이 시점까지 잘 작동하거나 Xcode에서 제안을 제공하는 경고 메시지가 표시되고 그 내용을 읽고 구현할 수 있기를 바랍니다. 바라건대 이제 당신은 당신의 기대에 따라 작업 견해를 가져야합니다 :).
중첩 또는 단일 스택보기의 경우 스크롤보기는 루트보기로 고정 너비를 설정해야합니다. 스크롤보기 안에있는 기본 스택보기는 동일한 너비를 설정해야합니다. [내 스크롤보기는보기의 아래에 있습니다. 무시]
UIStackView와 UIScrollView 사이에 동일한 너비 제약 조건을 설정하십시오.
가로 스크롤보기를 찾는 사람이 있다면
func createHorizontalStackViewsWithScroll() {
self.view.addSubview(stackScrollView)
stackScrollView.translatesAutoresizingMaskIntoConstraints = false
stackScrollView.heightAnchor.constraint(equalToConstant: 85).isActive = true
stackScrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
stackScrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
stackScrollView.bottomAnchor.constraint(equalTo: visualEffectViews.topAnchor).isActive = true
stackScrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.topAnchor.constraint(equalTo: stackScrollView.topAnchor).isActive = true
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()
}
스크롤보기를 장면에 놓고 장면을 채우도록 크기를 조정하십시오. 그런 다음 스크롤보기 안에 스택보기를 배치하고 스택보기 안에 항목 추가 단추를 배치하십시오. 모든 것이 제자리에있는 즉시 다음 제한 조건을 설정하십시오.
Scroll View.Leading = Superview.LeadingMargin
Scroll View.Trailing = Superview.TrailingMargin
Scroll View.Top = Superview.TopMargin
Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
Stack View.Leading = Scroll View.Leading
Stack View.Trailing = Scroll View.Trailing
Stack View.Top = Scroll View.Top
Stack View.Bottom = Scroll View.Bottom
Stack View.Width = Scroll View.Width
코드 : Stack View.Width = Scroll View.Width
열쇠입니다.
macOS Catalyst에 대한 새로운 관점 추가. macOS 앱은 윈도우 크기 조정을 지원하므로 UIStackView
스크롤 할 수없는 상태에서 스크롤 가능한 상태로 또는 그 반대로 전환 될 수 있습니다. 여기에는 두 가지 미묘한 것들이 있습니다.
UIStackView
모든 영역에 맞도록 설계되었습니다.UIScrollView
내비게이션 바 (또는 macOS 앱의 경우 툴바) 아래에서 새로 얻거나 잃어버린 영역을 고려하여 경계의 크기를 조정합니다.불행히도 무한 루프가 생성됩니다. 나는 극단적으로 익숙하지 않은 생각 UIScrollView
하고 adjustedContentInset
있지만 내 로그에서 layoutSubviews
방법, 나는 다음과 같은 행동을보고하고있다 :
UIScrollView
도구 모음 아래 영역이 필요하지 않으므로 경계를 줄이려고합니다.UIStackView
다음과 같습니다.UIScrollView
불만족스럽고 더 큰 범위로 복원하기로 결정했습니다. 내가 통나무에서보고있는 것이 있기 때문에 이것은 나에게 매우 이상하게 느낀다.UIScrollView.bounds.height == UIStackView.bounds.height
.UIStackView
다음과 같습니다.두 가지 단계로 문제가 해결 될 것으로 보입니다.
UIStackView.top
에 UIScrollView.topMargin
.contentInsetAdjustmentBehavior
에 .never
.여기서 세로로 커지는 세로 스크롤 가능 뷰에 관심이 있습니다 UIStackView
. 수평 쌍의 경우 코드를 적절히 변경하십시오.
그것이 미래의 누군가를 돕기를 바랍니다. 인터넷에서 이것을 언급하는 사람을 찾을 수 없었으며 무슨 일이 있었는지 알아내는 데 오랜 시간이 걸렸습니다.