1

我有List一个半透明视图部分覆盖(我们称之为覆盖)。我的问题是,对于长列表,最后一行是不可访问的,因为它们被覆盖层覆盖。

我正在使用 aZStack来布局最终视图。我考虑过在最后几行添加某种填充,可以使列表内容更大一些,所以它可以完全滚动出覆盖,但我不知道如何,或者即使使用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,所以我对如何搜索正确的术语有点迷茫。

4

1 回答 1

1

可能的解决方案是计算覆盖区域的高度,并在列表底部添加一些具有该高度的透明视图。

这是使用视图首选项的方法演示。使用 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()
    }
}

于 2020-08-23T15:57:59.547 回答