SwiftUI ScrollView VStack GeometryReader yüksekliği göz ardı edildi
Bir VStack dışında bir ScrollView kullanmak istiyorum, böylece VStack ekran boyutunun ötesine genişlerse içeriğim kaydırılabilir. Şimdi GeometryReaderVStack içinde kullanmak istiyorum ve bu problemlere neden oluyor, bu problemleri sadece GeometryReader çerçevesini ayarlayarak çözebilirim, bu da okuyucu ile görünüm boyutunu tanımlamak için kullandığım için bana pek yardımcı olmuyor.
İşte ScrollView olmayan kod ve güzel çalışıyor:
struct MyExampleView: View {
var body: some View {
VStack {
Text("Top Label")
.background(Color.red)
GeometryReader { reader in
Text("Custom Sized Label")
.frame(width: reader.size.width, height: reader.size.width * 0.5)
.background(Color.green)
}
Text("Bottom Label")
.background(Color.blue)
}
.background(Color.yellow)
}
}
Bu, aşağıdaki görüntü ile sonuçlanır:
Özel boyutlu etiket tam genişlikte, ancak yüksekliğin yarısı kadar genişlikte olmalıdır. Şimdi aynı kodu bir ScrollView'a sararsam, bu olur:
Her şey küçülmekle kalmadı, aynı zamanda Özel Boyutlu Etiketin yüksekliği de bir şekilde göz ardı edildi. GeometryReader'ın yüksekliğini ayarlarsam, bu davranışı ayarlayabilirim, ancak GeometryReader'ın içeriği kadar büyümesini istiyorum. Bunu nasıl başarabilirim?
Teşekkürler
Yanıtlar
Bunun GeometryReadersihirli bir araç olmadığı anlaşılmalıdır , sadece mevcut bağlamda mevcut alanı okur, ancak ... ScrollViewkendi kullanılabilir alanı yoktur, sıfırdır, çünkü gerekli alanı iç içerikten belirler ... bu yüzden GeometryReaderburada kullanarak döngünüz var - çocuk ebeveyne beden sorar, ancak ebeveyn çocuktan beden bekler ... SwiftUI oluşturucu bunu bir şekilde çözer (bilinen minimum boyutları bulur), sadece çökmemesi için.
İşte senaryonuz için olası çözüm - buradaki uygun araç, görünüm tercihleridir. Xcode 12 / iOS 14 ile hazırlanmış ve test edilmiştir.
struct DemoLayout_Previews: PreviewProvider {
static var previews: some View {
Group {
MyExampleView()
ScrollView { MyExampleView() }
}
}
}
struct MyExampleView: View {
@State private var height = CGFloat.zero
var body: some View {
VStack {
Text("Top Label")
.background(Color.red)
Text("Custom Sized Label")
.frame(maxWidth: .infinity)
.background(GeometryReader {
// store half of current width (which is screen-wide)
// in preference
Color.clear
.preference(key: ViewHeightKey.self,
value: $0.frame(in: .local).size.width / 2.0) }) .onPreferenceChange(ViewHeightKey.self) { // read value from preference in state self.height = $0
}
.frame(height: height) // apply from stored state
.background(Color.green)
Text("Bottom Label")
.background(Color.blue)
}
.background(Color.yellow)
}
}
struct ViewHeightKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
Not: ... ve görünümünüzün hangi bağlamda olduğundan emin değilseniz GeometryReader'ı kullanmayın.