React Native Custom Bottom Draggable Drawer

816 Views Asked by At

I am trying to implement a Bottom draggable drawer like the one you find in Google Maps or Apple Maps.

enter image description here

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. enter image description here

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.

0

There are 0 best solutions below