I want display or hide items by scroll direction just like safari. Hide something when scroll up, and show it when scroll down.
Asked
Active
Viewed 9,930 times
15
-
1You can potentially calculate this using `.onAppear()` when your scrolled content appears. – Procrastin8 Dec 15 '19 at 09:27
4 Answers
11
You can use DragGesture value
ScrollView {
...
}
.gesture(
DragGesture().onChanged { value in
if value.translation.height > 0 {
print("Scroll down")
} else {
print("Scroll up")
}
}
)
kimigori
- 477
- 4
- 4
-
5Unfortunately, applying `DragGesture` to a `ScrollView` will result in the `onChanged` callback only being fired once since scroll views by default handle these events. Thus, this does not produce the correct behaviour. – Darius Cosden Jul 26 '21 at 18:00
10
You would use GeometryReader to get the global position of one in the views in the ScrollView to detect the scroll direction. The code below will print out the current midY position. Dependent on the +/- value you could display or hide other views.
struct ContentView: View {
var body: some View {
ScrollView{
GeometryReader { geometry in
Text("Top View \(geometry.frame(in: .global).midY)")
.frame(width: geometry.size.width, height: 50)
.background(Color.orange)
}
}.frame(minWidth: 0, idealWidth: 0, maxWidth: .infinity, minHeight: 0, idealHeight: 0, maxHeight: .infinity, alignment: .center)
}
}
Marc T.
- 4,460
- 1
- 20
- 36
-
4This looks promising and gets around the onChange being fired once. How can you use the midY value to detect the direction? Or set a state variable? – Yarm Jul 30 '21 at 07:20
10
I think, simultaneousGesture is a better solution because it's not blocking scrollView events.
ScrollView {
}
.simultaneousGesture(
DragGesture().onChanged({
let isScrollDown = 0 < $0.translation.height
print(isScrollDown)
}))
This method only detects a new scrool if the screen has stop scrolling
Iker Solozabal
- 712
- 6
- 12
Den
- 2,431
- 24
- 22
-
3Unfortunately, applying `DragGesture` to a `ScrollView` will result in the `onChanged` callback only being fired once since scroll views by default handle these events. Thus, this does not produce the correct behaviour. – Darius Cosden Jul 26 '21 at 18:00
0
You can use predictedEndLocation and location like this
/// A prediction, based on the current drag velocity, of where the final
/// location will be if dragging stopped now.
public var predictedEndLocation: CGPoint { get }
DragGesture()
.onChanged({ gesture in
if (gesture.location.y > gesture.predictedEndLocation.y){
print("up")
} else {
print("down")
}
})
Erwan
- 1
- 1