Posicionando visualizações com GeometryReader em SwiftUI
Eu tenho um conjunto de visualizações filho (GridView1 e GridView2) em um scrollview. As visualizações filho estão dentro de um VStack, pois preciso delas uma abaixo da outra. Eu tenho um GeometryReader envolvendo as visualizações filho e cada uma das visualizações filho tem um GeometryReader dentro delas. Preciso do GeometryReader dentro do modo de exibição filho para determinar a largura do espaçamento de coluna que preciso em um LazyVGrid.
O problema é que, usar um GeometryReader dentro das visualizações filho faz com que as duas visualizações filho sejam empilhadas uma sobre a outra. Tentei definir o tamanho do quadro da visualização secundária, mas isso limita a rolagem vertical e não está me dando o resultado correto.
Eu apreciaria qualquer ajuda para resolver este problema.
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 e GridView2 são essencialmente a mesma coisa)
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)
}
}
}
aqui está o que estou esperando:
Aqui está o que estou recebendo atualmente. Como você pode ver abaixo, as visualizações filhas estão se agrupando no topo.
Respostas
Em vez de usar o interno GeometryReaderque confunde o externo ScrollView, passe a largura do topo GeometryReaderpara as grades das visualizações secundárias.
Aqui está a solução trabalhada. Testado com 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)
}
}
}
}
}
}