Предотвратить закрытие последних строк в списке другим представлением в 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
}
Другие вопросы по тегам