Expo와 React Navigation으로 Twitter 같은 슬라이드 메뉴 만들기

37007 단어 React NativeExpotech
트위터의 iOS 앱의 왼쪽 메뉴는 슬라이딩을 통해 열고 닫을 수 있다.
TwitterSlideMenu
평소 쓰는 데 익숙해져서 ExpoReact Native로 실현할 수 있는지 시험해 보고 싶어요.

React Navigation


Expo에서 탐색 또는 라우팅을 수행할 때React Navigation 사용할 수 있습니다추천을 받다.
이후 용어를 공식 문서와 일치시키기 위해 부제목 메뉴는'서랍', 메인 화면은'스크린'으로 작성한다.
다만, 정부 지침서는 매우 기본적인 내용에 머물러 기대 한 가지의 메뉴를 실현할 수 없다.실제로 여기에 적힌 내용 외에 많은 조합API를 준비했습니다.을 했다면 다음과 같은 맞춤형 제작이 가능하다.
  • 서랍을 열 때 화면도 함께 미끄러진다
  • 서랍의 너비 조절
  • 서랍의 내용을 독립된 보기로 바꾸기
  • 최종 예정은 다음과 같은 앱을 제작할 수 있다.
    CustomDrawer

    새 프로젝트 준비


    새 Expo 프로젝트템플릿은 Managed workflow의 blank를 선택합니다.
    $ expo init
    ✔ What would you like to name your app? … my-slide-menu
    ✔ Choose a template: › blank (TypeScript)    same as blank but with
    TypeScript configuration
    ✔ Downloaded and extracted project files.
    🧶 Using Yarn to install packages. Pass --npm to use npm instead.
    ⠙ Installing JavaScript dependencies.
    ...
    
    만든 항목 디렉터리로 이동하여 시작할 수 있는지 확인합니다.
    $ expo start
    

    필요한 패키지 설치


    다음은 필요한 포장을 설치합니다.먼저 React Navigation을 설치합니다.
    $ expo install @react-navigation/native
    
    이번에는 Expo의 Managed workflow에서 개발된 것이기 때문에 추가 포장이 필요하다.
    $ expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
    
    또한 @react-navigation/drawer에 서랍을 제공했기 때문에 마지막에 추가합니다.
    $ expo install @react-navigation/drawer
    

    기본 메뉴 만들기.


    다음은 공식 지침에 따라 기본적인 부하를 실현한다.문서의 샘플 코드에 TypeScript의 유형을 개편한 코드는 다음과 같습니다.[1]
    App.tsx
    import React from "react";
    import { StyleSheet, Button, Text, View } from "react-native";
    import {
      createDrawerNavigator,
      DrawerNavigationProp,
    } from "@react-navigation/drawer";
    import { NavigationContainer } from "@react-navigation/native";
    import { StatusBar } from "expo-status-bar";
    
    type HomeNavigationParamList = {
      Home: undefined;
      Notifications: undefined;
    };
    
    type HomeScreenNavigationProp = DrawerNavigationProp<
      HomeNavigationParamList,
      "Home"
    >;
    
    type NotificationsScreenNavigationProp = DrawerNavigationProp<
      HomeNavigationParamList,
      "Notifications"
    >;
    
    function HomeScreen({ navigation }: { navigation: HomeScreenNavigationProp }) {
      return (
        <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
          <Button
            onPress={() => navigation.navigate("Notifications")}
            title="Go to notifications"
          />
        </View>
      );
    }
    
    function NotificationsScreen({
      navigation,
    }: {
      navigation: NotificationsScreenNavigationProp;
    }) {
      return (
        <View style={styles.container}>
          <Button onPress={() => navigation.goBack()} title="Go back home" />
        </View>
      );
    }
    
    const Drawer = createDrawerNavigator<HomeNavigationParamList>();
    
    export default function App() {
      return (
        <NavigationContainer>
          <Drawer.Navigator initialRouteName="Home">
            <Drawer.Screen name="Home" component={HomeScreen} />
            <Drawer.Screen name="Notifications" component={NotificationsScreen} />
          </Drawer.Navigator>
          <StatusBar style="auto" />
        </NavigationContainer>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
      },
    });
    
    어쨌든 이동식 서랍을 설치할 수 있다.시동 걸어봐.
    InitialVersion
    하지만 이대로는 상상 속의 동작과는 거리가 멀다.

  • 서랍이 화면에 겹쳐서

  • 서랍의 폭이 너무 좁다

  • 고정 잠금장치(등록된 화면만 표시)
  • 순서대로 해결합시다.

    서랍을 열고 닫을 때 화면도 움직여야 한다


    서랍의 동작은 drawerType 속성에서 변경할 수 있습니다.원하는 운동을 실현하기 위해drawerType"slide"로 변경한다.
    <NavigationContainer>
      <Drawer.Navigator drawerType="slide">
        ...
      </Drawer.Navigator>
    
    빨리 운전해 봐.
    SlideDrawer
    기대했던 대로 움직이는 것 같아.이어서 서랍의 넓이를 넓히고 싶습니다.

    서랍의 너비를 조절하다


    지금 이러면 서랍의 폭이 너무 좁아서 좀 더 크게 하고 싶어요.이것은 drawerStyle에서 스타일을 자유롭게 지정할 수 있기 때문에 여기width를 지정하면 됩니다.
    export default function App() {
      return (
        <NavigationContainer>
          <Drawer.Navigator drawerType="slide" drawerStyle={styles.drawer}>
    ...
    const styles = StyleSheet.create({
      ...
      drawer: {
        width: "80%",
      },
    });
    
    이렇게 해도 폭을 확대할 수 있다.
    DrawerWidth
    이제 드디어 서랍 안의 물건을 독자적인 보기로 바꿔야 한다.

    사용자 정의 서랍 내용


    서랍에 표시된 내용은 drawerContentdrawerContentOptions로 맞춤형으로 제작할 수 있다.drawerContent에서 서랍 내용으로 표시된 보기를 덮어쓸 수 있지만 기본적으로 다음과 같습니다.
    import {
      DrawerContentScrollView,
      DrawerItemList,
    } from '@react-navigation/drawer';
    
    function CustomDrawerContent(props) {
      return (
        <DrawerContentScrollView {...props}>
          <DrawerItemList {...props} />
        </DrawerContentScrollView>
      );
    }
    
    기본 디스플레이는 drawerContentOptions에서 사용자 정의할 수 있습니다.예를 들어 다음과 같이 고쳐 써 보아라.
    <NavigationContainer>
      <Drawer.Navigator
        drawerType="slide"
        drawerStyle={styles.drawer}
        drawerContentOptions={{
          activeTintColor: "#e91e63",
          itemStyle: { marginVertical: 30 },
        }}
      >
      ...
    
    서랍에 표시된 메뉴 항목의 간격과 색깔이 바뀌었다는 것을 알아야 한다.추가 옵션은 API 참조을 참조하십시오.
    DrawerOptions
    물론 drawerContentOptions에서 하려고 했던'자신의 관점으로 서랍 안의 내용을 바꾸기'는 불가능하다.그것을 하려면 drawerContent를 사용하고 내용을 전부 바꾸어야 한다.drawerContent 서랍의 내용으로 되돌아오는 React 구성 요소의 함수를 지정합니다.느낌은 다음과 같다.
    export default function App() {
      return (
        <NavigationContainer>
          <Drawer.Navigator
            drawerType="slide"
            drawerStyle={styles.drawer}
            drawerContent={() => <View></View>}
          >
    ...
    
    navigation 대상을 포함하는props를 이 함수에 전달합니다.
    export default function App() {
      return (
        <NavigationContainer>
          <Drawer.Navigator
            drawerType="slide"
            drawerStyle={styles.drawer}
            drawerContent={props => <DrawerMenu {...props} />}
          >
    ...
    
    여기서 샘플로 아이콘 이미지와 메뉴 항목을 설정하고 그 모양의 보기를 만들어 보세요.여기서 주의해야 할 것은 서랍에 표시된 보기에 건네주는 프로포즈의 유형은 아마DrawerContentComponentProps일 것이다.
    import React from "react";
    import {
      StyleSheet,
      Button,
      Text,
      Image,
      View,
      TouchableOpacity,
    } from "react-native";
    import {
      createDrawerNavigator,
      DrawerNavigationProp,
      DrawerContentComponentProps,
    } from "@react-navigation/drawer";
    import { NavigationContainer } from "@react-navigation/native";
    import { StatusBar } from "expo-status-bar";
    import { Ionicons } from "@expo/vector-icons";
    
    // @ts-ignore
    import picture from "./assets/picture.png";
    ...
    function DrawerMenu({ navigation }: DrawerContentComponentProps) {
      return (
        <View style={styles.menuContainer}>
          <Image source={picture} resizeMode="contain" style={styles.picture} />
          <View>
            <Text style={styles.name}>takanori_is</Text>
            <Text style={styles.nickname}>@takanori_is</Text>
          </View>
          <TouchableOpacity
            style={styles.menuItem}
            onPress={() => {
              navigation.navigate("Home");
            }}
          >
            <Ionicons name="home-outline" size={24} />
            <Text style={styles.menuItemLabel}>ホーム</Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={styles.menuItem}
            onPress={() => {
              navigation.navigate("Notifications");
            }}
          >
            <Ionicons name="notifications-outline" size={24} />
            <Text style={styles.menuItemLabel}>通知</Text>
          </TouchableOpacity>
        </View>
      );
    }
    ...
    const styles = StyleSheet.create({
      ...
      menuContainer: { paddingVertical: 70, paddingHorizontal: 20 },
      picture: {
        width: 64,
        height: 64,
        borderRadius: 64 / 2,
        marginBottom: 7,
      },
      name: { fontSize: 18, fontWeight: "bold" },
      nickname: { fontSize: 15, color: "gray" },
      menuItem: { flexDirection: "row", marginTop: 24 },
      menuItemLabel: { marginLeft: 15, fontSize: 20, fontWeight: "300" },
    });
    
    expo start시뮬레이터로 동작을 확인한다.확실히 아이콘 이미지와 메뉴 항목이 있는 단독 보기를 설정합니다.
    CustomDrawer
    각주
    React Navigation의 Type Script 몰드에 대해서는 Type checking with TypeScript | React Navigation↩︎를 참조하십시오.

    좋은 웹페이지 즐겨찾기