我在navigationView
中有一个List
,每当滚动列表并且navigationBarTitle
变成.inline
或.large
时,我想更改List
Section
文本
这是我的代码:
import SwiftUI
struct ContentView: View {
@State private var scrolledUp = false
var body: some View {
NavigationView {
if scrolledUp {
List {
Section(header: Text("Moved UP"))
{
Text("Line1").bold()
Text("Line2").bold()
Text("Line2").bold()
}
.navigationBarTitle("Setting")
}
} else {
List {
Section(header: Text("Not Moved"))
{
Text("Line1").bold()
Text("Line2").bold()
Text("Line2").bold()
}
}
.navigationBarTitle("Setting")
}
}
}
}
我怎么能发现list
被滚动,而navigationBar
被更改为.title
?
目前我使用geometryReader
来检测List
section
header
的y位置。在滚动过程中。如果位置小于80,则navigationBarTitle
变为.title
。
它工作得很好。然而,我仍在寻找更好的解决方案。
以下是一个粗略的实现,用于在从.large
转到.inline
时打开其他导航栏项目。它并不完美,但在某些情况下已经足够了。
import SwiftUI
struct ContentView: View {
@State private var navIsInline = false
var body: some View {
NavigationView {
ScrollView {
ZStack {
LazyVStack {
ForEach(1..<100) { val in
Text("Hello, NavBar! (val)")
}
}
GeometryReader { proxy in
let offset = proxy.frame(in: .named("scroll")).minY
Color.clear.preference(key: ViewOffsetKey.self, value: offset)
}
}
}
.coordinateSpace(name: "scroll")
.onPreferenceChange(ViewOffsetKey.self) { value in
print(value)
if navIsInline != (value < 0) {
navIsInline.toggle()
}
}
.navigationBarTitleDisplayMode(.large)
.navigationTitle("Nav title")
.toolbar {
if navIsInline {
ToolbarItem(placement: .navigationBarLeading) {
Text("leading")
}
ToolbarItem(placement: .navigation) {
Text("Navigation")
.font(.headline)
}
ToolbarItem(placement: .navigationBarTrailing) {
HStack {
Text("Trailing").font(.headline)
}
.padding(.horizontal)
}
}
}
//.toolbar(navIsInline ? .hidden : .visible, for: .navigationBar)
}
}
}
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}