Resizing React Native View with Pan Gesture
What is Pan Gesture?
Pan is like Drag of Desktop.
Maybe, You may confuse Pan and Swipe.
Swipe Gesture is shorter than Pan and Swipe can handle only one direction.
So how can we detect Pan gesture?
React-Native
React-Native provides PanResponder since 0.60.
To detect panning on your View, we should create PanResponder.
PanResponder has this event handlers.
- onStartShouldSetPanResponder
- onPanResponderGrant
- onMoveShouldSetPanResponder
- onPanResponderMove
- onPanResponderRelease
onPanResponderGrant is an event to notify that user has started panning.
onPanResponderMove is an event to indicate that user is moving his finger since beginning Pan gesture.
onPanResponderRelease is an event notifying that user has stopped panning and put off his finger from the screen.
onStartShouldSetPanResponder and onMoveShouldSetPanResponder indicate whether it responder fires the events.
gesture.dy means how far vertically from the panning start point.
If the user moved up their finger while panning, dy will be lower than 0.
Inject PanGesture into the target View like this.
Now we can receive pan gesture events from View.
Everything is OK??
Unfortunately, we can find a bug.
This caused by originViewHeight captured by PanResponder ref.
How can we solve this?
We can choice useMemo instead of useRef./
Replace useRef with useMemo like this.
useMemo will update PanResponder by originViewHeight.
And originViewHeight will be updated on PanResponderEnd.
If you want any threshold animations, use Animated.View.
I won’t talk about it here.
react-native-reanimated
If you are using react-native-reanimated, you can apply PanGestureHandler instead.
PanGestureHandler is a tag, you can’t create instance directly.
We can detect gesture by wrapping the view we want to detect.
To use PanGestureHandler, we should install packages
yarn add react-native-gesture-handler@1.10.3
yarn add react-native-reanimated@2.2.0
And follow installation guide
Import PanGestureHandler from react-native-gesture-handler
And wrap the handle with it.
Like PanResponder, we should attach handler.
In this time, we will attach useAnimatedGestureHandler.
useAnimatedGestureHandler has this events.
- onStart
- onActive
- onEnd
onActive is like onPanResponderMove.
import Animated from react-native-reanimated not from react-native.
import Animated from ‘react-native-reanimated’;
Replace our Text handle view with Animated.Text.
What is wrong?
We can’t move handle. why?
PanGestureHandler need GestureHandlerRootView as an root View.
Let’s replace our app’s root View with PanGestureHandler.
Now are pan events triggered? Unfortunately our app will be crashed when pressing the handle.
Wrap codes in the event handlers with runOnJS.
If the codes access another code affecting to UI without runOnJS, the app will be crashed.
Advanced
Animated.View supports special style for animation.
We can create style with useAnimatedStyle.
useAnimatedStyle can have normal style values and also special values for animations.
useAnimatedStyle usage is just like normal Style.
To use useSharedValue, we should apply it into useAnimatedGestureHandler also.
Now the animation is better.
Above sources is based react-native 0.63.4
TroubleShootings
Animated.event now requires a second argument for options
{ useNativeDriver: true }
Spread children are not supported in React.
{…panResponder.panHandlers}
config.onPanResponderMove is not a function.
useNativeDriver: false,
useAnimatedGestureHandler crash onStart
runOnJS(…)()
Element type is invalid: expected a string
reason : PanGestureHandler
CMake ‘3.18.1’ was not found in PATH or by cmake.dir property.
Android Studio > Tools > SDK Manger > Android SDK > SDK Tools > ShowPackage Details > CMake > 3.18.1 > Apply
Invalid revision: 3.18.1-g262b901
install react-native-reanimated 3.0.0-rc.3
Reanimated 2 failed to create a worklet, may be you forgot to add Reanimated’s babel plugin?
- babel.config.
Crash after enableHermes: true
- yarn add hermes-engine@0.5.2-rc1
PanGestureHandler can not assign to { children: Element
- goto defines of React.Component
- readonly props: Readonly<P> & Readonly<{ children?: ReactNode }>;
- check and modify @types/react version
References
cljsrn 2021-07-12 | Slack Archive
I've tried this but it doesn't work.
clojurians-log.clojureverse.org
https://developer.android.com/studio/projects/install-ndk#apply-specific-version