CSSJavaScriptPythonReact-Native
thumbnail image

Animated sidebar with device back button handling in react native

By Manas Makde
import { useEffect, useRef, useState } from "react"; import { Pressable, View, StyleSheet, Button, Animated, Dimensions, BackHandler, Text } from "react-native"; const AnimatedPressable = Animated.createAnimatedComponent(Pressable); const sidebarWidth = Dimensions.get('window').width * 0.6; const duration = 200 const SideBar = ({ sideAni, backgroundAni, menuOpen, setMenuOpen }) => { useEffect(() => { Animated.timing(sideAni, { toValue: !menuOpen ? 0 : 1, duration, useNativeDriver: true }).start(); Animated.timing(backgroundAni, { toValue: !menuOpen ? 0 : 1, duration, useNativeDriver: true }).start(); const backHandler = BackHandler.addEventListener('hardwareBackPress', () => { setMenuOpen(val => menuOpen ? false : val) return menuOpen }); return () => backHandler.remove(); }, [menuOpen]) return (<AnimatedPressable style={{ ...styles.sidebarBackground, backgroundColor: backgroundAni.interpolate({ inputRange: [0, 1], outputRange: ['rgba(0,0,0,0)', 'rgba(0,0,0,0.5)'], }) }} onPress={() => setMenuOpen(false)} pointerEvents={!menuOpen ? "none" : "auto"}> <Animated.View style={{ ...styles.sidebar, transform: [{ translateX: backgroundAni.interpolate({ inputRange: [0, 1], outputRange: [-sidebarWidth, 0], }) }] }} onStartShouldSetResponder={(event) => true} onTouchEnd={(e) => { e.stopPropagation() }} pointerEvents={!menuOpen ? "none" : "auto"} > <Text style={styles.customText}>Sidebar</Text> </Animated.View> </AnimatedPressable>) } export default function App() { const backgroundAni = useRef(new Animated.Value(0)).current; const sideAni = useRef(new Animated.Value(0)).current; const [menuOpen, setMenuOpen] = useState(false) return (<View> <Button title="Toggle Sidebar" onPress={() => { setMenuOpen(val => !val) Animated.timing(sideAni, { toValue: menuOpen ? 0 : 1, duration, useNativeDriver: true }).start(); Animated.timing(backgroundAni, { toValue: menuOpen ? 0 : 1, duration, useNativeDriver: true }).start(); }} /> <Text style={[styles.customText]}>Main Page</Text> <SideBar {...{ sideAni, backgroundAni, menuOpen, setMenuOpen }} /> </View>) } const styles = StyleSheet.create({ sidebarBackground: { height: "100%", width: "100%", position: "absolute" }, sidebar: { height: "100%", width: "60%", backgroundColor: "white", elevation: 10, }, customText: { height: "100%", fontWeight: "bold", fontSize: 25, color: "gray", textAlign: "center", textAlignVertical: "center", } });