I'm trying to hide BottomRoundedRectangle() when I see the 2nd LazyVStack {…} on the screen, but it doesn't work.
value in .onPreferenceChange(OffsetKey.self) doesn't change as well.
struct OffsetKey: PreferenceKey {
typealias Value = CGFloat
static let defaultValue: Value = .zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value = nextValue()
}
}
struct OffsetKeyBackground: ViewModifier {
func body(content: Content) -> some View {
GeometryReader { reader in
content
.preference(
key: OffsetKey.self,
value: -reader.frame(in: .named("secondLazyStack")).origin.y
)
}
}
}
struct ScrollQuestion: View {
@State
private var elementValue: CGFloat = .zero
var body: some View {
ScrollView(.vertical) {
// Dynamic long text there
LazyVStack {
RoundedRectangle(cornerRadius: 12)
.fill(Color.gray.opacity(0.3))
.frame(height: 920) // dynamic text, 920 for example, may be bigger
}
// 2nd LazyVStack
LazyVStack {
RoundedRectangle(cornerRadius: 12)
.frame(height: 820)
}
.coordinateSpace(name: "secondLazyStack")
}
.safeAreaInset(edge: .bottom) {
// How to hide this correctly when we see second LazyVStack ?
BottomRoundedRectangle()
// .opacity(elementValue < 50 ? 1 : 0)
}
.modifier(OffsetKeyBackground())
.onPreferenceChange(OffsetKey.self) { value in
debugPrint(value)
elementValue = value
}
}
}
struct BottomRoundedRectangle: View {
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 8)
.frame(height: 40)
.foregroundStyle(.indigo)
.padding(.horizontal)
Text("Visible only in first LazyVStack")
.foregroundStyle(.white)
}
}
}
#Preview {
ScrollQuestion()
}
What do I need to do to hide BottomRoundedRectangle() correctly ?
You can detect this by wrapping the second
LazyVStackin aGeometryReader.If the scroll view's frame intersects the frame of the
LazyVStack, that means at least some part of theLazyVStackis on screen.Then you can do:
Note that in this particular case, it is also possible to just set the preference to
This is because
LazyVStacks are lazy - if they are not on screen, it literally doesn't exist. The geometry reader can't convert the scroll view's frame to a coordinate space that doesn't exist.