List {
//I Want This Button To Appear When User Over Scroll To Top
Button(action: { ... }, label: {
Text("Archive")
})
ForEach(0..<5) { item in
ChatButton()
}
.listRowInsets(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.listRowPlatterColor(.clear)
Rectangle()
.frame(width: Sizes.width - 8, height: Sizes.h2)
.foregroundColor(Color("Background"))
.listRowInsets(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.listRowPlatterColor(.clear)
CenteredTextButton(
text: "Durumlar", textColor: Color("White"),
isLink: true, destinationKey: "statuses", buttonAction: {}
)
.listRowInsets(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.listRowPlatterColor(.clear)
}
In the above code, I want the Button that says Archive to appear when user scrolls to top when user already at the top (ex: on negative offset y)
I have found a solution like this, but I don't know it's the best way to do it.
struct ChatsView: View {
@State private var showArchived = false
@State private var scrollAmount: CGPoint = CGPoint(x: 0, y: 0)
var body: some View {
NavigationView {
ScrollView {
VStack {
// show with easeIn only if showArchived == true
if showArchived {
CenteredIconButton(
icon: "ArchiveIcon", text: "Archive",
textColor: Color("White"), backgroundColor: Color("Background")
)
.transition(.move(edge: .top))
.animation(.easeIn)
}
ForEach(0..<5) { item in
ChatButton()
}
.listRowInsets(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.listRowPlatterColor(.clear)
...
...
}
// observer y offset of VStack compare to ScrollView
.background(GeometryReader { geometry in
Color.clear
.preference(key: ScrollOffsetPreferenceKey.self, value: geometry.frame(in: .named("scroll")).origin)
})
// set showArchived variable
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
scrollAmount = value
if value.y > 50 {
showArchived = true
} else if value.y < 0 {
showArchived = false
}
}
}
.coordinateSpace(name: "scroll")
.navigationTitle("Sohbet")
}
}
}