I'm trying to implement this custom drawer with animation effect while sliding (opening, closing), the MainLayout should be resizing with a shrinking / growing animation when toggeling the drawer but what it does is simply changing it's size after it reache the right or left end, infact if I'm using the close button insted of pull / push through touch, upon returning it isn't growing in full sceen.
Code for Drawer:
import 'react-native-gesture-handler';
import React, {useState} from 'react';
import {StyleSheet, TouchableOpacity, Image, Text, View} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import Animated from 'react-native-reanimated';
import {
createDrawerNavigator,
DrawerContentScrollView,
useDrawerProgress,
} from '@react-navigation/drawer';
import {icons} from '../constants';
// screens import
import MainLayout from '../screens/MainLayout';
const Drawer = createDrawerNavigator();
const CustomDrawerItem = ({icon, label}) => {
return (
<TouchableOpacity // drawer item button
style={[styles.drawerItem]}
onPress={() => console.log('drawer item')}>
<Image // drawer item icon
source={icon}
style={styles.drawerItemIcon}
/>
<Text // drawer item label
style={styles.drawerItemLabel}>
{label}
</Text>
</TouchableOpacity>
);
};
const CustomDrawerContent = ({navigation}) => {
return (
<DrawerContentScrollView
scrollEnabled={true}
contentContainerStyle={{flex: 1}}>
<View style={{flex: 1, paddingHorizontal: 20}}>
<View // close button container
style={styles.closeBtnContainer}>
<TouchableOpacity // close button
style={styles.closeBtn}
onPress={() => navigation.closeDrawer()}>
<Image // close button icon
source={icons.close}
style={styles.closeBtnIcon}
resizeMode="contain"
/>
</TouchableOpacity>
</View>
<TouchableOpacity // profile button
style={styles.profileButton}
onPress={() => console.log('profile')}>
<Image // profile image
source={icons.avatar}
style={styles.profileImage}
resizeMode="cover"
/>
<View // profile text container
style={{marginLeft: 10}}>
<Text // profile name
style={styles.commonTxt}>
John Doe
</Text>
<Text // profile email
style={[styles.commonTxt, {fontSize: 15}]}>
[email protected]
</Text>
</View>
</TouchableOpacity>
<View // drawer items container
style={styles.drawerItmContainer}>
<CustomDrawerItem // qr code
icon={icons.qr_code}
label="QR Code"
/>
<CustomDrawerItem // resource
icon={icons.resource}
label="Resource"
/>
<CustomDrawerItem // collection report
icon={icons.collection_report}
label="Collection Report"
/>
<CustomDrawerItem // change pin
icon={icons.change_pin}
label="Change Pin"
/>
<View // separator
style={styles.separator}
/>
</View>
<View // logout button container
style={{marginBottom: 20}}>
<CustomDrawerItem // logout
icon={icons.logout}
label="Logout"
/>
</View>
</View>
</DrawerContentScrollView>
);
};
const CustomDrawer = () => {
return (
<LinearGradient
colors={['#ff9933', '#3b5998', '#192f6a']}
style={styles.container}>
<Drawer.Navigator
screenOptions={{
headerShown: false,
drawerType: 'slide',
overlayColor: 'transparent',
drawerStyle: {flex: 1, width: '65%', backgroundColor: 'transparent'},
sceneContainerStyle: {backgroundColor: 'transparent'},
}}
drawerContent={props => {
return <CustomDrawerContent navigation={props.navigation} />;
}}
initialRouteName="MainLayout">
<Drawer.Screen name="MainLayout">
{props => <MainLayout {...props} />}
</Drawer.Screen>
</Drawer.Navigator>
</LinearGradient>
);
};
export default CustomDrawer;
const styles = StyleSheet.create({
drawerItem: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 20,
alignItems: 'center',
borderRadius: 10,
},
drawerItemIcon: {width: 20, height: 20, tintColor: '#fff'},
drawerItemLabel: {fontSize: 18, color: '#fff', marginLeft: 15},
profileButton: {flexDirection: 'row', alignItems: 'center', marginTop: 20},
profileImage: {width: 50, height: 50, borderRadius: 10},
closeBtnContainer: {alignItems: 'flex-start', justifyContent: 'center'},
closeBtn: {alignItems: 'center', justifyContent: 'center'},
closeBtnIcon: {width: 30, height: 30, tintColor: '#fff'},
commonTxt: {fontSize: 18, color: '#fff'},
drawerItmContainer: {flex: 1, marginTop: 20},
separator: {height: 1, backgroundColor: '#fff', marginVertical: 10},
container: {flex: 1, backgroundColor: '#ff9f1c'},
});
Code for MainLayout:
import 'react-native-gesture-handler';
import {StyleSheet, Text, View, SafeAreaView} from 'react-native';
import React from 'react';
import Animated from 'react-native-reanimated';
import {useDrawerProgress} from '@react-navigation/drawer';
const MainLayout = props => {
const progress = useDrawerProgress();
const scale = Animated.interpolateNode(progress.value, {
inputRange: [0, 1],
outputRange: [1, 0.75],
});
const borderRadius = Animated.interpolateNode(progress.value, {
inputRange: [0, 1],
outputRange: [0, 30],
});
const animatedStyle = {
borderRadius,
transform: [{scale}],
};
return (
<Animated.View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
...animatedStyle,
}}>
<Text>MainLayout</Text>
</Animated.View>
);
};
export default MainLayout;
const styles = StyleSheet.create({});
Animation Issue:
Closing Issue:
package.json
{
"name": "Dhananjaya",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"@react-native-masked-view/masked-view": "^0.2.6",
"@react-navigation/drawer": "^6.4.1",
"@react-navigation/native": "^6.0.10",
"@react-navigation/stack": "^6.2.1",
"axios": "^0.27.2",
"native-base": "^3.4.5",
"react": "17.0.2",
"react-native": "0.68.2",
"react-native-gesture-handler": "^2.4.2",
"react-native-linear-gradient": "^2.5.6",
"react-native-reanimated": "^2.8.0",
"react-native-safe-area-context": "^4.2.5",
"react-native-screens": "^3.13.1",
"react-native-svg": "^12.3.0"
},
"devDependencies": {
"@babel/core": "7.18.2",
"@babel/runtime": "7.18.3",
"@react-native-community/eslint-config": "2.0.0",
"babel-jest": "26.6.3",
"eslint": "7.32.0",
"jest": "26.6.3",
"metro-react-native-babel-preset": "0.67.0",
"react-test-renderer": "17.0.2"
},
"jest": {
"preset": "react-native"
}
}
babel.config.js (for reference to reanimated configuration)
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin'],
};
Looks like I fixed the problem, I just had to add "useLegacyImplementation" inside screenOptions prop of Drawer, Thats it.