SwiftUI 列表导航标题字体和填充更新?

问题描述 投票:0回答:1

我正在尝试更改标题(“我的标题”)上的字体和填充?因此,我将

.navigationTitle
设置为具有良好的列表行为,当您滚动经过标题时,它会更新导航栏标题。

注意:我也喜欢保留导航栏标题自动更改的行为

这是我的代码:

#Preview() {
    NavigationView {
        List {
            ForEach(1..<30) { number in
                Text("\(number)")
            }.navigationTitle("My Title")
        }
    }
}

swiftui navigationview
1个回答
0
投票

这是我想出的自定义解决方案。它使用 PreferenceKey 和 GeometryReader 来确定滚动偏移。

struct ContentView: View {
    
    @State var offsetValue: CGFloat = 1
    @State private var titlePlacement: Alignment = .topLeading
    
    var body: some View {
        NavigationStack {
            GeometryReader { proxy in
                let scrollViewHeight = proxy.frame(in: .scrollView(axis: .vertical)).height
                let minY = proxy.frame(in: .scrollView(axis: .vertical)).minY
                ScrollView {
                    ZStack {
                        LazyVStack {
                            ForEach(0...100, id: \.self) { index in
                                Text("Row \(index)")
                            }
                        }
                        .padding(.top, 40)
                        GeometryReader { proxy in
                            let offset = proxy.frame(in: .named("scroll")).minY
                            Color.clear.preference(key: OffsetKey.self, value: offset)
                        }
                    } //: ZSTACK
                } //: SCROLL
                .coordinateSpace(name: "scroll")
                .onPreferenceChange(OffsetKey.self) { scrollValue in
                    let progress = -minY / scrollValue
                    
                    /// Cap it between 1-0
                    let cappedScrollValue = min(max(abs(progress), 0), 1)
                    print("Capped: \(cappedScrollValue)")
                    
                    withAnimation( /* YOUR ANIMATON HERE */) {
                        if offsetValue >= 0.8 {
                            titlePlacement = .topLeading
                        } else {
                            titlePlacement = .top
                        }
                    }
                    offsetValue = cappedScrollValue
                }
            } //: GEOMETRY
            .overlay(alignment: titlePlacement) {
                Text("My Title")
                    .font(.title.bold())
                    .frame(maxWidth: .infinity, alignment: titlePlacement)
                    .padding(.leading, 20) // <-- Padding here
                    .background(alignment: .top) {
                        if titlePlacement == .top {
                            Rectangle()
                                .fill(.ultraThinMaterial)
                                .frame(maxWidth: .infinity)
                                .frame(height: 100)
                                .offset(y: -60)
                        }
                    }
                    
            }
        } //: NAVIGATION
    }
    
    
}

struct OffsetKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

我跟踪两个状态变量:当然是偏移量,还有标题的位置。当我拥有标准导航栏的外观和感觉时,我尝试尽可能多地复制。该解决方案允许进行更深入的自定义,因为您可以将任何所需的视图放置在标题所在的覆盖层中。但绝对还有改进的空间。结果:

让我知道这是否适合您!

© www.soinside.com 2019 - 2024. All rights reserved.