SwiftUI에서 GeometryReader로 뷰 위치 지정

Nov 13 2020

scrollview 내에 자식 뷰 (GridView1 및 GridView2) 집합이 있습니다. 자식 뷰는 다른 하나 아래에 필요하기 때문에 VStack 내에 있습니다. 자식 뷰를 래핑하는 GeometryReader가 있고 각 자식 뷰에는 내부에 GeometryReader가 있습니다. LazyVGrid에서 필요한 열 간격의 너비를 결정하려면 자식 뷰 내부에 GeometryReader가 필요합니다.

문제는 Child 뷰 내에서 GeometryReader를 사용하면 두 개의 자식 뷰가 서로 겹쳐진다는 것입니다. 나는 자식보기의 프레임 크기를 설정하려고했지만 수직 스크롤을 제한하고 올바른 결과를 얻지 못했습니다.

이 문제를 해결하는 데 도움을 주시면 감사하겠습니다.

ContentView :

struct ContentView: View {
    var body: some View {
        GeometryReader { geo in
            ScrollView {
                VStack(spacing: 20) {
                    GridView1()
                    GridView2()
                }//.frame(minHeight: 0, maxHeight: .infinity)
            }
        }
        .padding()
    }
}

GridView1 :

struct GridView1: View {
    var body: some View {
        GeometryReader { g in
            let maxwidth = g.size.width/6 > 100 ? g.size.width/6 : 100
            let columns = Array(repeating: GridItem(.flexible(minimum: 100, maximum: maxwidth), spacing: 0), count: 6)
            
            ScrollView(.horizontal) {
                LazyVGrid(columns: columns, alignment: .leading, spacing: 10, pinnedViews: [.sectionHeaders]) {
                    Section(header: Text("Grid 1").font(.title)) {
                        ForEach(0...200, id:\.self) { index in
                            Text("\(index)").frame(maxWidth: .infinity)
                        }
                    }
                }
            }
            .background(Color.blue)
        }
    }
}

GridView2 (GridView1과 GridView2는 본질적으로 동일 함)

struct GridView2: View {
    var body: some View {
        GeometryReader { g in
            let maxwidth = g.size.width/10 > 100 ? g.size.width/10 : 100
            let columns = Array(repeating: GridItem(.flexible(minimum: 100, maximum: maxwidth), spacing: 0), count: 10)
            ScrollView(.horizontal) {
                LazyVGrid(columns: columns, alignment: .leading, spacing: 20, pinnedViews: [.sectionHeaders]) {
                    Section(header: Text("Grid 2").font(.title)) {
                        ForEach(1000...1200, id:\.self) { index in
                            ZStack {
                                Text("\(index)")
                            }
                            .frame(maxWidth: .infinity)
                            .background(Color.green)
                        }
                    }//.frame(minHeight: 0, maxHeight: .infinity)
                }
            }//.frame(minHeight: 1000, maxHeight: .infinity)
            //.frame(maxWidth: .infinity, maxHeight: .infinity)
            //.background(Color.red)
        }
    }
}

내가 기대하는 것은 다음과 같습니다.

여기 내가 현재 얻고있는 것입니다. 아래에서 볼 수 있듯이 자식 뷰가 맨 위에 뭉쳐 있습니다.

답변

1 Asperi Nov 13 2020 at 12:10

GeometryReader외부를 혼동 하는 내부 를 사용하는 대신 ScrollView상단 GeometryReader에서 하위 뷰 그리드로 너비를 전달하십시오 .

여기에 작동하는 솔루션이 있습니다. Xcode 12.1 / iOS 14.1로 테스트 됨

struct ContentView: View {
    var body: some View {
        GeometryReader { geo in
            ScrollView {
                VStack(spacing: 20) {
                    GridView1(width: geo.size.width)
                    GridView2(width: geo.size.width)
                }
            }
        }
        .padding()
    }
}

struct GridView1: View {
    let width: CGFloat
    var body: some View {
        let maxwidth = width/6 > 100 ? width/6 : 100
        let columns = Array(repeating: GridItem(.flexible(minimum: 100, maximum: maxwidth), spacing: 0), count: 6)
        
        ScrollView(.horizontal) {
            LazyVGrid(columns: columns, alignment: .leading, spacing: 10, pinnedViews: [.sectionHeaders]) {
                Section(header: Text("Grid 1").font(.title)) {
                    ForEach(0...200, id:\.self) { index in
                        Text("\(index)").frame(maxWidth: .infinity)
                    }
                }
            }
        }
        .background(Color.blue)
    }
}

struct GridView2: View {
    let width: CGFloat
    var body: some View {
        let maxwidth = width/10 > 100 ? width/10 : 100
        let columns = Array(repeating: GridItem(.flexible(minimum: 100, maximum: maxwidth), spacing: 0), count: 10)
        ScrollView(.horizontal) {
            LazyVGrid(columns: columns, alignment: .leading, spacing: 20, pinnedViews: [.sectionHeaders]) {
                Section(header: Text("Grid 2").font(.title)) {
                    ForEach(1000...1200, id:\.self) { index in
                        ZStack {
                            Text("\(index)")
                        }
                        .frame(maxWidth: .infinity)
                        .background(Color.green)
                    }
                }
            }
        }
    }
}