Предотвратить закрытие последних строк в списке другим представлением в ZStack
У меня есть List
частично закрывается полупрозрачным видом (назовем его наложением). Моя проблема в том, что для длинных списков последние строки недоступны, поскольку они закрыты наложением.
Я использую ZStack
для макета окончательного вида. Я подумал о добавлении какого-то заполнения в последние строки, которое могло бы сделать содержимое списка немного больше, чтобы он мог полностью прокручиваться из наложения, но я не знаю, как, или даже если использоватьZStack
это правильный способ делать списки.
import SwiftUI
struct ListWithBottomOverlay: View {
var body: some View {
GeometryReader { proxy in
ZStack {
List {
ForEach(1..<20) { number in
Text("\(number)")
}
}
VStack {
Spacer().frame(maxHeight: .infinity)
VStack {
HStack {
Button(action: {}, label: { Text("Hello") })
.frame(minHeight: 100)
}
HStack {
Button(action: {}, label: { Text("World!") })
.frame(minHeight: 100)
}
}
.frame(maxWidth: .infinity)
.background(Color(.yellow).opacity(0.8))
}
}
}
}
}
struct ListWithBottomOverlay_Previews: PreviewProvider {
static var previews: some View {
ListWithBottomOverlay()
}
}
Прошу прощения, если это повторяющийся вопрос, я только начал изучать SwiftUI, поэтому я еще не совсем понял, как искать правильные термины.
2 ответа
Возможное решение - вычислить высоту области наложения и добавить прозрачное изображение с этой высотой в конец списка.
Вот демонстрация подхода с использованием настроек просмотра. Протестировано с Xcode 12 / iOS 14
struct ListWithBottomOverlay: View {
@State private var height = CGFloat.zero
var body: some View {
GeometryReader { proxy in
ZStack {
List {
ForEach(1..<20) { number in
Text("\(number)")
}
Color.clear.frame(height: height) // injected empty space
}
VStack {
Spacer().frame(maxHeight: .infinity)
VStack {
HStack {
Button(action: {}, label: { Text("Hello") })
.frame(minHeight: 100)
}
HStack {
Button(action: {}, label: { Text("World!") })
.frame(minHeight: 100)
}
}
.frame(maxWidth: .infinity)
.background(GeometryReader {
// use color filled area in background to read covered frame
Color(.yellow).opacity(0.8)
.edgesIgnoringSafeArea(.bottom)
.preference(key: ViewHeightKey.self, value: $0.frame(in: .local).size.height)
})
}
}
.onPreferenceChange(ViewHeightKey.self) {
// view preferences transferred in one rendering cycle and
// give possibility to update state
self.height = $0
}
}
}
}
struct ViewHeightKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
Теперь вы можете добавить в список .safeAreaInset.
List {
// content
}
.safeAreaInset(.bottom) {
// view for bottom
}