防止列表中的最后一行被 ZStack 中的其他视图覆盖
Prevent last rows in List to be covered by other view in ZStack
我有一个 List
部分被半透明视图覆盖(我们称它为 overlay)。我的问题是,对于长列表,最后一行无法访问,因为它们被覆盖层覆盖了。
我正在使用 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,所以我对如何搜索正确的术语有点迷茫。
可能的解决方案是计算覆盖区域的高度,并在列表底部添加一些具有该高度的透明视图。
这是使用视图首选项的方法演示。用 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: [=10=].frame(in: .local).size.height)
})
}
}
.onPreferenceChange(ViewHeightKey.self) {
// view preferences transferred in one rendering cycle and
// give possibility to update state
self.height = [=10=]
}
}
}
}
struct ViewHeightKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
我有一个 List
部分被半透明视图覆盖(我们称它为 overlay)。我的问题是,对于长列表,最后一行无法访问,因为它们被覆盖层覆盖了。
我正在使用 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,所以我对如何搜索正确的术语有点迷茫。
可能的解决方案是计算覆盖区域的高度,并在列表底部添加一些具有该高度的透明视图。
这是使用视图首选项的方法演示。用 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: [=10=].frame(in: .local).size.height)
})
}
}
.onPreferenceChange(ViewHeightKey.self) {
// view preferences transferred in one rendering cycle and
// give possibility to update state
self.height = [=10=]
}
}
}
}
struct ViewHeightKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}