SwiftUI: заставить лист отображать заголовок содержимого или полный контент

Я хотел бы иметь лист SwiftUI, который показывает либо заголовок, либо полное содержимое. Требуется iOS 16 — это нормально.

Я уже получаю правильные два измеренных значения высоты в презентации.

      import Foundation
import SwiftUI

struct ContentView: View {
    @State private var showSheet = false
    @State private var headerSize: CGSize = .zero
    @State private var overallSize: CGSize = .zero
    
    var body: some View {
        Button("View sheet") {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            Group {
                VStack(alignment: .leading) {
                    Text("Header")
                        .background(
                            GeometryReader { geometryProxy in
                                Color.clear
                                    .preference(key: HeaderSizePreferenceKey.self, value: geometryProxy.size)
                            }
                        )
                    Text("")
                    Text("Some very long text ...")
                    Text("Some very long text ...")
                    Text("Some very long text ...")
                    Text("Some very long text ...")
                    Text("Some very long text ...")
                    Text("Some very long text ...")
                    Text("Some very long text ...")
                    Text("Some very long text ...")
                } // VStack
                .padding()
                .background(
                    //measure without spacer
                    GeometryReader { geometryProxy in
                        Color.clear
                            .preference(key: SizePreferenceKey.self, value: geometryProxy.size)
                    }
                )
                Spacer()
            } // Group
            .onPreferenceChange(SizePreferenceKey.self) { newSize in
                overallSize.height = newSize.height
            }
            .onPreferenceChange(HeaderSizePreferenceKey.self) { newSize in
                headerSize.height = newSize.height
            }
            .presentationDetents([
                .height(headerSize.height),
                .height(overallSize.height)
            ]
            )
            
        } // sheet content
    }
}

struct HeaderSizePreferenceKey: PreferenceKey {
    static var defaultValue: CGSize = .zero
    static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() }
}

struct SizePreferenceKey: PreferenceKey {
    static var defaultValue: CGSize = .zero
    static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() }
}

struct MySheet_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Этот код основан на идеях из статьи «Создание листа с точным размером содержимого внутри».

Это почти работает. Это полный размер содержимого:

Это размер содержимого заголовка:

Что я могу сделать, чтобы в последнем случае отображалась верхняя часть содержимого («Заголовок»), а не центр содержимого?

0 ответов

Другие вопросы по тегам