[ios] SwiftUI에서 VStack이 화면 너비를 채우도록합니다.

이 코드가 주어지면 :

import SwiftUI

struct ContentView : View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Title")
                .font(.title)

            Text("Content")
                .lineLimit(nil)
                .font(.body)

            Spacer()
        }
        .background(Color.red)
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

다음과 같은 인터페이스가 발생합니다.

시사

VStack레이블 / 텍스트 구성 요소에 전체 너비가 필요하지 않은 경우에도 화면 너비를 채우 려면 어떻게 해야합니까?

내가 찾은 트릭 은 다음과 같이 구조에 을 삽입하는 HStack것입니다.

VStack(alignment: .leading) {
    HStack {
        Spacer()
    }
    Text("Title")
        .font(.title)

    Text("Content")
        .lineLimit(nil)
        .font(.body)

    Spacer()
}

원하는 디자인을 산출합니다.

원하는 출력

더 좋은 방법이 있습니까?



답변

.frame 수정자를 다음 옵션과 함께 사용해보십시오.

.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
struct ContentView: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Hello World").font(.title)
            Text("Another").font(.body)
            Spacer()
        }.frame(minWidth: 0,
                maxWidth: .infinity,
                minHeight: 0,
                maxHeight: .infinity,
                alignment: .topLeading
        ).background(Color.red)
    }
}

이것은 전체 화면을 채우도록 확장되는 유연한 프레임 ( 문서 참조 )으로 설명되며 , 추가 공간이있을 때 내용을 중앙에 배치합니다.


답변

작동하고 아마도 좀 더 직관적 인 대체 스태킹 배열은 다음과 같습니다.

struct ContentView: View {
    var body: some View {
        HStack() {
            VStack(alignment: .leading) {
                Text("Hello World")
                    .font(.title)
                Text("Another")
                    .font(.body)
                Spacer()
            }
            Spacer()
        }.background(Color.red)
    }
}

Spacer()필요한 경우의 를 제거하여 콘텐츠의 위치를 ​​쉽게 변경할 수도 있습니다 .

위치 변경을위한 스페이서 추가 / 제거


답변

더 좋은 방법이 있습니다!

하려면 VStack채우기에게 그것의 부모의 폭을 당신은을 사용하여 GeometryReader프레임을 설정합니다. ( .relativeWidth(1.0)작동해야하지만 지금 당장은 작동하지 않습니다)

struct ContentView : View {
    var body: some View {
        GeometryReader { geometry in
            VStack {
                Text("test")
            }
                .frame(width: geometry.size.width,
                       height: nil,
                       alignment: .topLeading)
        }
    }
}

VStack실제 화면의 너비 를 만들기 위해 UIScreen.main.bounds.width를 사용하는 대신 프레임을 설정할 때 사용할 수 GeometryReader있지만 상위 뷰의 너비를 원했을 가능성이 높습니다.

또한,이 방법은에 간격을 추가하지의 추가 혜택이있다 VStack(당신이 간격 않은 경우) 당신이 추가 한 경우 어떤 발생할 수 HStackA를을 Spacer()받는 그것의 내용으로를 VStack.

업데이트-더 좋은 방법은 없습니다!

수락 된 답변을 확인한 후 수락 된 답변이 실제로 작동하지 않는다는 것을 깨달았습니다! 언뜻보기에는 작동하는 것처럼 보이지만 VStack녹색 배경을 갖도록 업데이트하면 VStack여전히 너비가 동일하다는 것을 알 수 있습니다.

struct ContentView : View {
    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {
                Text("Hello World")
                    .font(.title)
                Text("Another")
                    .font(.body)
                Spacer()
                }
                .background(Color.green)
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
                .background(Color.red)
        }
    }
}

이는 .frame(...)실제로 뷰 계층 구조에 다른 뷰를 추가하고 해당 뷰가 화면을 채우기 때문입니다. 그러나 VStack여전히 그렇지 않습니다.

또한이 문제는 아니라 내 대답에 동일하게 보인다 상기와 동일한 방법을 사용하여 확인할 수 있습니다 (이전과 이후에 다른 배경 색상을 넣어 .frame(...). 실제로에 나타납니다가를 확대하는 것이 유일한 방법은 VStack스페이서를 사용하는 것입니다 :

struct ContentView : View {
    var body: some View {
        VStack(alignment: .leading) {
            HStack{
                Text("Title")
                    .font(.title)
                Spacer()
            }
            Text("Content")
                .lineLimit(nil)
                .font(.body)
            Spacer()
        }
            .background(Color.green)
    }
}


답변

Swift 5.2 및 iOS 13.4를 사용하면 필요에 따라 다음 예제 중 하나를 사용 VStack하여 최상위 제약 조건 및 전체 크기 프레임 에 맞출 수 있습니다 .

아래의 코드 스 니펫은 모두 동일한 디스플레이를 표시하지만 뷰 계층을 디버깅하는 동안 나타날 VStack수있는 View요소 의 유효 프레임 이나 수를 보장하지는 않습니다 .


1. 사용 frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:)방법

가장 간단한 방법은 VStack최대 너비와 높이로 프레임을 설정 하고 필요한 정렬을 전달하는 것입니다 frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:).

struct ContentView: View {

    var body: some View {
        VStack(alignment: .leading) {
            Text("Title")
                .font(.title)
            Text("Content")
                .font(.body)
        }
        .frame(
            maxWidth: .infinity,
            maxHeight: .infinity,
            alignment: .topLeading
        )
        .background(Color.red)
    }

}

또는에 대해 특정 정렬을 사용하여 최대 프레임을 설정 View하는 것이 코드베이스의 일반적인 패턴 인 경우 확장 메서드를 만들 수 있습니다 View.

extension View {

    func fullSize(alignment: Alignment = .center) -> some View {
        self.frame(
            maxWidth: .infinity,
            maxHeight: .infinity,
            alignment: alignment
        )
    }

}

struct ContentView : View {

    var body: some View {
        VStack(alignment: .leading) {
            Text("Title")
                .font(.title)
            Text("Content")
                .font(.body)
        }
        .fullSize(alignment: .topLeading)
        .background(Color.red)
    }

}

2. Spacers를 사용 하여 강제 정렬

당신은 추가 할 수 있습니다 VStack내부의 전체 크기 HStack와 사용 후행과 하단 Spacer당신의 강제들 VStack최고 선두 정렬 :

struct ContentView: View {

    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                Text("Title")
                    .font(.title)
                Text("Content")
                    .font(.body)

                Spacer() // VStack bottom spacer
            }

            Spacer() // HStack trailing spacer
        }
        .frame(
            maxWidth: .infinity,
            maxHeight: .infinity
        )
        .background(Color.red)
    }

}

3. ZStack및 전체 크기 배경 사용View

이 예에서는 VStackZStack 상단 행간 정렬이있는 내부 . Color보기를 사용하여 최대 너비 및 높이를 설정 하는 방법에 유의하십시오 .

struct ContentView: View {

    var body: some View {
        ZStack(alignment: .topLeading) {
            Color.red
                .frame(maxWidth: .infinity, maxHeight: .infinity)

            VStack(alignment: .leading) {
                Text("Title")
                    .font(.title)
                Text("Content")
                    .font(.body)
            }
        }
    }

}

4. 사용 GeometryReader

GeometryReader다음과 같은 선언이 있습니다 .

콘텐츠를 자체 크기 및 좌표 공간의 함수로 정의하는 컨테이너보기입니다. […]이보기는 부모 레이아웃에 유연한 선호 크기를 반환합니다.

아래 코드 스 니펫은 최상위 제약 조건 및 전체 크기 프레임 GeometryReader에 맞추는 데 사용하는 방법을 보여줍니다 VStack.

struct ContentView : View {

    var body: some View {
        GeometryReader { geometryProxy in
            VStack(alignment: .leading) {
                Text("Title")
                    .font(.title)
                Text("Content")
                    .font(.body)
            }
            .frame(
                width: geometryProxy.size.width,
                height: geometryProxy.size.height,
                alignment: .topLeading
            )
        }
        .background(Color.red)
    }

}

5. 사용 overlay(_:alignment:)방법

VStack기존 전체 크기 위에 상단 선행 제약 조건 을 맞추려면 다음 방법 View을 사용할 수 있습니다 overlay(_:alignment:).

struct ContentView: View {

    var body: some View {
        Color.red
            .frame(
                maxWidth: .infinity,
                maxHeight: .infinity
            )
            .overlay(
                VStack(alignment: .leading) {
                    Text("Title")
                        .font(.title)
                    Text("Content")
                        .font(.body)
                },
                alignment: .topLeading
            )
    }

}

디스플레이:


답변

문제를 해결하는 가장 간단한 방법은 ZStack + .edgesIgnoringSafeArea (.all)를 사용하는 것입니다.

struct TestView : View {

    var body: some View {
        ZStack() {
            Color.yellow.edgesIgnoringSafeArea(.all)
            VStack {
                Text("Hello World")
            }
        }
    }
}


답변

이것을 사용하십시오

.edgesIgnoringSafeArea(.all)


답변

사용하여 할 수 있습니다. GeometryReader

GeometryReader

암호:

struct ContentView : View {
    var body: some View {
        GeometryReader { geometry in
            VStack {
               Text("Turtle Rock").frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading).background(Color.red)
            }
        }
    }
}

출력은 다음과 같습니다.

여기에 이미지 설명 입력