I am trying to implement a Bottom draggable drawer
like the one you find in Google Maps
or Apple Maps
.
I followed a tutorial from here: Tutorial but I still can't move my component on Y axis
.
Here is my code so far:
import React, { useRef } from 'react'
import { StyleSheet, View, Animated, PanResponder } from 'react-native'
import Colors from '../global/Colors'
import Constants from '../global/Constants'
import { BottomDrawerType } from '../global/Enumerations'
const BottomDrawerView = () => {
const y = useRef(new Animated.Value(BottomDrawerType.Closed)).current
const state = useRef(new Animated.Value(BottomDrawerType.Closed)).current
const margin = 0.05 * Constants.Size.screenHeight
/**
* Functionalities
*/
const movementValue = (moveY) => Constants.Size.screenHeight - moveY
const animateMove = (y, toValue, callback) => {
Animated.spring(y, {
toValue: -toValue,
tension: 20,
useNativeDriver: true,
}).start((finished) => {
finished && callback && callback()
})
}
const getNextState = (
currentState,
val,
margin,
) => {
switch (currentState) {
case BottomDrawerType.Peek:
return val >= currentState + margin
? BottomDrawerType.Open
: val <= BottomDrawerType.Peek - margin
? BottomDrawerType.Closed
: BottomDrawerType.Peek;
case BottomDrawerType.Open:
return val >= currentState
? BottomDrawerType.Open
: val <= BottomDrawerType.Peek
? BottomDrawerType.Closed
: BottomDrawerType.Peek;
case BottomDrawerType.Closed:
return val >= currentState + margin
? val <= BottomDrawerType.Peek + margin
? BottomDrawerType.Peek
: BottomDrawerType.Open
: BottomDrawerType.Closed;
default:
return currentState;
}
}
const onPanResponderMove = (PanResponderGestureState) => {
const val = movementValue(PanResponderGestureState)
animateMove(y, val)
}
const onPanResponderRelease = (PanResponderGestureState) => {
const valueToMove = movementValue(PanResponderGestureState)
const nextState = getNextState(state, valueToMove, margin)
state.setValue(nextState)
animateMove(y, nextState)
}
const onMoveShouldSetPanResponder = ( PanResponderGestureState) => Math.abs(PanResponderGestureState) >= 10
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder,
onStartShouldSetPanResponderCapture: onMoveShouldSetPanResponder,
onPanResponderMove,
onPanResponderRelease,
}),
).current
/**
* UI
*/
return (
<Animated.View
style={[styles.contentView, { transform: [{ translateY: y }] }]}
{...panResponder.panHandlers}>
<View style={styles.horizontalLine} />
</Animated.View>
)
}
const styles = StyleSheet.create({
contentView: {
position: 'absolute',
bottom: -Constants.Size.screenHeight + 70,
width: Constants.Size.screenWidth,
height: Constants.Size.screenHeight,
backgroundColor: Colors.turqoise,
borderRadius: Constants.Layout.borderRadius,
},
horizontalLine: {
marginTop: 25,
marginBottom: 15,
marginHorizontal: 0,
height: 2,
width: '100%',
backgroundColor: Colors.main
}
})
export default BottomDrawerView
And my BottomDrawerType
is like this:
const BottomDrawerType = {
Open: Constants.Size.screenHeight - 230,
Peek: 230,
Closed: 0
}
The component works as UI
, can be imported in another file, won't crash the app but the draggable action is not working.
Can someone help me understand better this Animations
and help me make this component be draggable?
Excuse me for any mistakes that might be found in code.