onReceive(self.timer) 在 NavigationView 中不起作用
onReceive(self.timer) doesn't work inside a NavigationView
我有这个 Scrollview
的页面,其中包含一个自定义 header,只有当它滚动到一定高度时才会显示。我使用 GeometryReader
和 onReceive
来不断检查当前的滚动高度:
@State var userInfoUpateInterval = Timer.publish(every: 0.1, on: .current, in: .tracking).autoconnect()
@State var showHeader: Bool = false
var body: some View {
NavigationView {
ZStack(alignment: .top) {
ScrollView(.vertical) {
GeometryReader { geometry in
Text("User info component").onReceive(self.userInfoUpateInterval) { (_) in
self.onUserInfoLayoutChange(geometry)
}
}
VStack {
Text("content")
}.frame(width: UIScreen.screenWidth, height: 1500)
}
ProfileHeader(title: "user.userName", showHeader: $showHeader)
}
}
}
滚动和 header hiding/showing 完美运行,直到我将 ZStack
包裹在 NavigationView
中。 onReceive
根本就不再触发了。如果我将 NavigationView
与 ZStack
交换,一切都会再次按预期工作。
我看过这个 问题,但我没有条件成分。这是 SwiftUI 错误还是我做错了什么?
这是针对您的案例的可能解决方案的演示。使用 Xcode 11.4 / iOS 13.4 测试(向前兼容)
我们的想法不是通过计时器而是通过视图位置变化做出反应,这已经 read/tracked 通过视图首选项。
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout Value, nextValue: () -> Value) {
value = value + nextValue()
}
}
struct DemoView: View {
@State var showHeader: Bool = false
var body: some View {
NavigationView {
ZStack(alignment: .top) {
ScrollView(.vertical) {
Text("User info component")
.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self,
value: -[=10=].frame(in: .named("scroll_area")).origin.y) })
VStack {
Text("content")
}.frame(maxWidth: .infinity, minHeight: 1500)
}.coordinateSpace(name: "scroll_area")
if showHeader {
Text("ProfileHeader")
}
}
}
.onPreferenceChange(ViewOffsetKey.self) {
self.showHeader = [=10=] > 200 // << your condition
}
}
}
我有这个 Scrollview
的页面,其中包含一个自定义 header,只有当它滚动到一定高度时才会显示。我使用 GeometryReader
和 onReceive
来不断检查当前的滚动高度:
@State var userInfoUpateInterval = Timer.publish(every: 0.1, on: .current, in: .tracking).autoconnect()
@State var showHeader: Bool = false
var body: some View {
NavigationView {
ZStack(alignment: .top) {
ScrollView(.vertical) {
GeometryReader { geometry in
Text("User info component").onReceive(self.userInfoUpateInterval) { (_) in
self.onUserInfoLayoutChange(geometry)
}
}
VStack {
Text("content")
}.frame(width: UIScreen.screenWidth, height: 1500)
}
ProfileHeader(title: "user.userName", showHeader: $showHeader)
}
}
}
滚动和 header hiding/showing 完美运行,直到我将 ZStack
包裹在 NavigationView
中。 onReceive
根本就不再触发了。如果我将 NavigationView
与 ZStack
交换,一切都会再次按预期工作。
我看过这个
这是针对您的案例的可能解决方案的演示。使用 Xcode 11.4 / iOS 13.4 测试(向前兼容)
我们的想法不是通过计时器而是通过视图位置变化做出反应,这已经 read/tracked 通过视图首选项。
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout Value, nextValue: () -> Value) {
value = value + nextValue()
}
}
struct DemoView: View {
@State var showHeader: Bool = false
var body: some View {
NavigationView {
ZStack(alignment: .top) {
ScrollView(.vertical) {
Text("User info component")
.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self,
value: -[=10=].frame(in: .named("scroll_area")).origin.y) })
VStack {
Text("content")
}.frame(maxWidth: .infinity, minHeight: 1500)
}.coordinateSpace(name: "scroll_area")
if showHeader {
Text("ProfileHeader")
}
}
}
.onPreferenceChange(ViewOffsetKey.self) {
self.showHeader = [=10=] > 200 // << your condition
}
}
}