react-native의 중첩 서랍 메뉴
70288 단어 androidreactreactnativeios
이 문서에서는 react-navigation을 사용하여 서랍 메뉴를 관리합니다.
여기에 있는 전체 앱 빌드의 코드는 https://github.com/Merlier/rn_example_menu_drawer_nested.git에서 사용할 수 있습니다.
참고: 여기서 app.js 표시는 단순화되었습니다. 깔끔하게 코딩하려면 모든 탐색 및 화면 기능을 분리된 jsx 파일로 내보내야 합니다.
시작하다
요구 사항:
먼저 새 react-native 프로젝트를 시작하십시오.
$ npx react-native init rn_example_menu_drawer_nested
react-navigation 모듈을 설치합니다:
$ npm install --save @react-navigation/native
$ npm install --save react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
app.js를 수정하여 두 개의 화면 홈 및 설정을 추가합니다.
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow strict-local
*/
import 'react-native-gesture-handler';
import React from 'react';
import {StyleSheet, View, Text} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
function HomeScreen() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Home Screen</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Settings Screen</Text>
</View>
);
}
const Stack = createStackNavigator();
const App: () => React$Node = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
const styles = StyleSheet.create({});
export default App;
그냥 심플한 서랍
이제 간단한 서랍 메뉴를 만들 것입니다.
먼저 해당 서랍 모듈을 설치합니다.
$ npm install --save @react-navigation/drawer
모든 드로어 경로 정의를 포함할 drawerItemsMain.js를 추가합니다.
export const drawerItemsMain = [
{
key: 'Home',
title: 'Home',
route: {nav: 'MainDrawer', routeName: 'Home', title: 'Home'},
},
{
key: 'Settings',
title: 'Settings',
route: {nav: 'MainDrawer', routeName: 'Settings', title: 'Settings'},
},
];
CustomDrawerContent.js를 생성하여 사용자 지정 서랍을 렌더링합니다.
import React from 'react';
import {
StyleSheet,
ScrollView,
View,
Text,
TouchableOpacity,
SafeAreaView,
Image,
} from 'react-native';
function CustomDrawerContent(props) {
const onItemPress = (key) => {
const filteredMainDrawerRoutes = props.drawerItems.find((e) => {
return e.key === key;
});
const selectedRoute = filteredMainDrawerRoutes.route;
props.navigation.toggleDrawer();
props.navigation.navigate(selectedRoute.nav, {
screen: selectedRoute.routeName,
});
};
const logOut = async () => console.log('log out');
function renderMainDrawer() {
return (
<View>
{props.drawerItems.map((parent) => (
<View key={parent.key}>
<TouchableOpacity
key={parent.key}
testID={parent.key}
onPress={() => {
onItemPress(parent.key);
}}>
<View style={styles.parentItem}>
<Text style={[styles.icon, styles.title]}>{parent.title}</Text>
</View>
</TouchableOpacity>
</View>
))}
{renderLogoutBtn()}
</View>
);
}
function renderLogoutBtn() {
return (
<View>
<TouchableOpacity onPress={logOut} testID="customDrawer-logout">
<View style={styles.parentItem}>
<Text style={styles.title}>{'Log out'}</Text>
</View>
</TouchableOpacity>
</View>
);
}
return (
<ScrollView style={styles.drawerContainer}>
<SafeAreaView
style={styles.container}
forceInset={{top: 'always', horizontal: 'never'}}>
<View style={styles.centered}>
<Image
source={{uri: 'https://reactjs.org/logo-og.png'}}
style={styles.logo}
/>
</View>
{renderMainDrawer()}
</SafeAreaView>
</ScrollView>
);
}
const styles = StyleSheet.create({
headerContainer: {
height: 100,
flexDirection: 'row',
paddingVertical: 28,
justifyContent: 'center',
alignItems: 'center',
},
logo: {
width: 100,
height: 75,
},
drawerContainer: {
backgroundColor: '#222222',
},
container: {
flex: 1,
zIndex: 1000,
},
centered: {
alignItems: 'center',
},
parentItem: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#F0F0F0',
paddingTop: 4,
paddingBottom: 4,
},
title: {
margin: 16,
fontWeight: 'bold',
color: '#F0F0F0',
textAlign: 'center',
},
});
export default CustomDrawerContent;
그런 다음 CustomHeader.js를 추가하여 사용자 지정 헤더를 만듭니다.
import React from 'react';
import {
StyleSheet,
TouchableOpacity,
View,
Text,
SafeAreaView,
} from 'react-native';
import {DrawerActions} from '@react-navigation/native';
function CustomHeader(props) {
const toggleDrawer = () =>
props.navigation.dispatch(DrawerActions.toggleDrawer());
return (
<SafeAreaView>
<View style={styles.headerContainer}>
<View style={styles.headerLeft}>
<TouchableOpacity
onPress={toggleDrawer}
style={styles.leftButton}
testID="CustomHeader-toggleDrawer">
<Text style={styles.buttonTxt}>MENU</Text>
</TouchableOpacity>
</View>
<View style={styles.header}>
<Text style={styles.headerTxt}>HEADER</Text>
</View>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
headerContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
backgroundColor: '#222222',
minHeight: 40,
},
headerLeft: {
flexDirection: 'row',
},
leftButton: {
marginLeft: 10,
},
header: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
paddingRight: 40,
},
buttonTxt: {
color: '#ddd',
fontWeight: 'bold',
},
headerTxt: {
color: '#ddd',
},
});
export default CustomHeader;
다음과 같이 app.js를 수정합니다.
...
import {createDrawerNavigator} from '@react-navigation/drawer';
import {drawerItemsMain} from './drawerItemsMain';
import CustomDrawerContent from './CustomDrawerContent.js';
import CustomHeader from './CustomHeader';
const Drawer = createDrawerNavigator();
...
function MainDrawerNavigation() {
return (
<Drawer.Navigator
initialRouteName="Home"
drawerContent={(props) => (
<CustomDrawerContent drawerItems={drawerItemsMain} {...props} />
)}>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Settings" component={SettingsScreen} />
</Drawer.Navigator>
);
}
const App: () => React$Node = () => {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerMode: 'screen',
headerTintColor: '#404554',
headerTitleStyle: {
fontWeight: 'bold',
},
header: (props) => {
return <CustomHeader {...props} />;
},
}}>
<Stack.Screen name="MainDrawer" component={MainDrawerNavigation} />
</Stack.Navigator>
</NavigationContainer>
);
};
...
마지막으로 중첩된 다단계 서랍
다음과 같이 draweritemsMain.js를 수정합니다.
export const drawerItemsMain = [
{
key: 'Home',
title: 'Home',
routes: [{nav: 'MainDrawer', routeName: 'Home', title: 'Home'}],
},
{
key: 'Settings',
title: 'Settings',
routes: [
{nav: 'MainDrawer', routeName: 'Settings1', title: 'Settings 1'},
{nav: 'MainDrawer', routeName: 'Settings2', title: 'Settings 2'},
],
},
];
CustomDrawerContent.js는 다음과 같습니다.
import React, {useState, useRef, useEffect} from 'react';
import {
StyleSheet,
ScrollView,
View,
Text,
TouchableOpacity,
SafeAreaView,
Image,
} from 'react-native';
function CustomDrawerContent(props) {
const [mainDrawer, setMainDrawer] = useState(true);
const [filteredItems, setFilteredItems] = useState([]);
const toggleMainDrawer = () => {
setMainDrawer(true);
setFilteredItems([]);
};
const onItemParentPress = (key) => {
const filteredMainDrawerRoutes = props.drawerItems.find((e) => {
return e.key === key;
});
if (filteredMainDrawerRoutes.routes.length === 1) {
const selectedRoute = filteredMainDrawerRoutes.routes[0];
props.navigation.toggleDrawer();
props.navigation.navigate(selectedRoute.nav, {
screen: selectedRoute.routeName,
});
} else {
setMainDrawer(false);
setFilteredItems(filteredMainDrawerRoutes);
}
};
const logOut = async () => console.log('log out');
function renderMainDrawer() {
return (
<View>
{props.drawerItems.map((parent) => (
<View key={parent.key}>
<TouchableOpacity
key={parent.key}
testID={parent.key}
onPress={() => {
onItemParentPress(parent.key);
}}>
<View style={styles.parentItem}>
<Text style={[styles.icon, styles.title]}>{parent.title}</Text>
</View>
</TouchableOpacity>
</View>
))}
{renderLogoutBtn()}
</View>
);
}
function renderFilteredItemsDrawer() {
return (
<View>
<TouchableOpacity
onPress={() => toggleMainDrawer()}
style={styles.backButtonRow}>
<Text style={[styles.backButtonText, styles.title]}>{'BACK'}</Text>
</TouchableOpacity>
{filteredItems.routes.map((route) => {
return (
<TouchableOpacity
key={route.routeName}
testID={route.routeName}
onPress={() =>
props.navigation.navigate(route.nav, {
screen: route.routeName,
})
}
style={styles.item}>
<Text style={styles.title}>{route.title}</Text>
</TouchableOpacity>
);
})}
</View>
);
}
function renderLogoutBtn() {
return (
<View>
<TouchableOpacity onPress={logOut} testID="customDrawer-logout">
<View style={styles.parentItem}>
<Text style={styles.title}>{'Log out'}</Text>
</View>
</TouchableOpacity>
</View>
);
}
return (
<ScrollView style={styles.drawerContainer}>
<SafeAreaView
style={styles.container}
forceInset={{top: 'always', horizontal: 'never'}}>
<View style={styles.centered}>
<Image
source={{uri: 'https://reactjs.org/logo-og.png'}}
style={styles.logo}
/>
</View>
{mainDrawer ? renderMainDrawer() : renderFilteredItemsDrawer()}
</SafeAreaView>
</ScrollView>
);
}
const styles = StyleSheet.create({
headerContainer: {
height: 100,
flexDirection: 'row',
paddingVertical: 28,
justifyContent: 'center',
alignItems: 'center',
},
logo: {
width: 100,
height: 75,
},
drawerContainer: {
backgroundColor: '#222222',
},
container: {
flex: 1,
zIndex: 1000,
},
centered: {
alignItems: 'center',
},
parentItem: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#F0F0F0',
paddingTop: 4,
paddingBottom: 4,
},
title: {
margin: 16,
fontWeight: 'bold',
color: '#F0F0F0',
textAlign: 'center',
},
backButtonRow: {
flexDirection: 'row',
alignItems: 'center',
paddingBottom: 17,
paddingLeft: 3,
borderBottomColor: '#F0F0F0',
borderBottomWidth: 1,
},
backButtonText: {
marginLeft: 10,
color: '#F0F0F0',
},
});
export default CustomDrawerContent;
그런 다음 app.js에 두 가지 다른 설정 화면을 추가합니다.
...
function Settings1Screen() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Settings 1 Screen</Text>
</View>
);
}
function Settings2Screen() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Settings 2 Screen</Text>
</View>
);
}
function MainDrawerNavigation() {
return (
<Drawer.Navigator
initialRouteName="Home"
drawerContent={(props) => (
<CustomDrawerContent drawerItems={drawerItemsMain} {...props} />
)}>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Settings1" component={Settings1Screen} />
<Drawer.Screen name="Settings2" component={Settings2Screen} />
</Drawer.Navigator>
);
}
$ npx react-native run-android
이제 react-native 앱에 완전히 중첩된 다중 레벨 서랍이 있습니다! :)
그것이 당신을 도울 수 있기를 바랍니다!
재미있게 보내세요 :)
Reference
이 문제에 관하여(react-native의 중첩 서랍 메뉴), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/merlier/nested-drawer-menu-in-react-native-44k8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)