React Navigation 基本使用

React Navigation 基本使用

参考资料

https://reactnavigation.org/docs/

环境搭建

Minimum requirementsreact-native >= 0.63.0

  • expo >= 41 (if you use Expo)
  • typescript >= 4.1.0 (if you use TypeScript)

Installation

npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context

From React Native 0.60 and higher, linking is automatic. So you don’t need to run react-native link.

If you’re on a Mac and developing for iOS, you need to install the pods (via Cocoapods) to complete the linking.

npx pod-install ios

react-native-screens package requires one additional configuration step to properly work on Android devices. Edit MainActivity.java file which is located in android/app/src/main/java/<your package name>/MainActivity.java.

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(null);
}

and make sure to add an import statement at the top of this file:

import android.os.Bundle;

Hello React Navigation

React Navigation提供了不同于浏览器的a标签的方案,它提供了适用了IOS和Android合适的过渡动画。

安装原生栈导航库(Installing the native stack navigator library)

到目前为止我们已经安装的库仅仅构建了Navigation的基本快,然而每个Navigation都是有一个自己的库的,为了使用原声的导航栈,我们需要安装@react-navigation/native-stac

npm install @react-navigation/native-stack

@react-navigation/native-stack depends on react-native-screens and the other libraries that we installed in Getting started. If you haven’t installed those yet, head over to that page and follow the installation instructions.

创建一个原生栈导航(Creating a native stack navigator)

createNativeStackNavigator函数会返回一个包含两个属性ScreenNavigator的对象。他们都是用于配置配置navigator的React组件,Navigator应该包含Screen元素作为他们的子元素来为路由定义配置。

NavigationContainer是一个用来管理导航树(navigation tree)的组件并且它包含了 navigation state,这个组件必须包含所有导航的结构,通常的,我们在app的根去渲染这个组件,通常这个组件被App.js被导出。(export)

// In App.js in a new project
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen() {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
    </View>
  );
}

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

基本案例

// In App.js in a new project
import * as React from 'react';
import { View, Text, Button } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen({navigation}) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => {
          navigation.navigate('Details', {
            itemId: 86,
            otherParam: 'anything you want here'
          })
        }}
      />
    </View>
  );
}

function DetailsScreen({route,navigation}) {
  const { itemId, otherParam } = route.params;
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Text>itemId: {JSON.stringify(itemId)}</Text>
      <Text>otherParam: {JSON.stringify(otherParam)}</Text>
      <Button
        title="Go to Details... again"
        onPress={() =>
          navigation.push('Details', {
            itemId: Math.floor(Math.random() * 100),
          })
        }
      />
      <Button title="Go back" onPress={() => navigation.goBack()} />
      <Button
        title="Go back to first screen in stack"
        onPress={() => navigation.popToTop()}
      />
    </View>
  );
}


const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} options={{ title: '主页' }}/>
        <Stack.Screen name="Details" component={DetailsScreen} options={{ title: '详情' }}/>
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

携返回值案例

// In App.js in a new project
import * as React from "react";
import { View, Text, Button, TextInput } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";

function HomeScreen({ navigation, route }) {
  React.useEffect(() => {
    if (route.params?.post) {
      // Post updated, do something with `route.params.post`
      // For example, send the post to the server
    }
  }, [route.params?.post]);

  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
      <Button
        title="Create post"
        onPress={() => navigation.navigate("CreatePost")}
      />
      <Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
    </View>
  );
}

function CreatePostScreen({ navigation, route }) {
  const [postText, setPostText] = React.useState("");

  return (
    <>
      <TextInput
        multiline
        placeholder="What's on your mind?"
        style={{ height: 200, padding: 10, backgroundColor: "white" }}
        value={postText}
        onChangeText={setPostText}
      />
      <Button
        title="Done"
        onPress={() => {
          // Pass and merge params back to home screen
          navigation.navigate({
            name: "Home",
            params: { post: postText },
            merge: true,
          });
        }}
      />
    </>
  );
}



const Stack = createNativeStackNavigator();

function StackScreen() {
  const screenOptions = {
    headerStyle: {
      backgroundColor: "#f4511e",
    },
    headerTintColor: "#fff",
    headerTitleStyle: {
      fontWeight: "bold",
    },
  }
  return (
    <Stack.Navigator initialRouteName="Home">
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{
          title: "主页", ...screenOptions }}
      />
      <Stack.Screen
        name="CreatePost"
        component={CreatePostScreen}
        options={{
          title: "创建Post", ...screenOptions }}
      />
    </Stack.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <StackScreen />
    </NavigationContainer>
  );
}

export default App;

Replacing the title with a custom component

function LogoTitle() {
  return (
    <Image
      style={{ width: 50, height: 50 }}
      source={require('@expo/snack-static/react-native-logo.png')}
    />
  );
}

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ headerTitle: (props) => <LogoTitle {...props} /> }}
      />
    </Stack.Navigator>
  );
}

给标题来点样式

// In App.js in a new project
import * as React from "react";
import { View, Text, Button, TextInput } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";

function HomeScreen({ navigation, route }) {
  React.useEffect(() => {
    if (route.params?.post) {
      // Post updated, do something with `route.params.post`
      // For example, send the post to the server
    }
  }, [route.params?.post]);

  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
      <Button
        title="Create post"
        onPress={() => navigation.navigate("CreatePost")}
      />
      <Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
    </View>
  );
}

function CreatePostScreen({ navigation, route }) {
  const [postText, setPostText] = React.useState("");

  return (
    <>
      <TextInput
        multiline
        placeholder="What's on your mind?"
        style={{ height: 200, padding: 10, backgroundColor: "white" }}
        value={postText}
        onChangeText={setPostText}
      />
      <Button
        title="Done"
        onPress={() => {
          // Pass and merge params back to home screen
          navigation.navigate({
            name: "Home",
            params: { post: postText },
            merge: true,
          });
        }}
      />
    </>
  );
}



const Stack = createNativeStackNavigator();

function StackScreen() {
  const screenOptions = {
    headerStyle: {
      backgroundColor: "#f4511e",
    },
    headerTintColor: "#fff",
    headerTitleStyle: {
      fontWeight: "bold",
    },
  }
  return (
    <Stack.Navigator initialRouteName="Home">
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{
          headerTitle: () => <Text>Text</Text>,
          headerRight: () => (
            <Button
              onPress={() => alert('This is a button!')}
              title="Info"
              color="black"
            />
          ),
        }}
      />
      <Stack.Screen
        name="CreatePost"
        component={CreatePostScreen}
        options={{
          headerTitle: () => <Text>Text</Text>,
          headerRight: () => (
            <Button
              onPress={() => alert('This is a button!')}
              title="Info"
              color="black"
            />
          ),
        }}
      />
    </Stack.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <StackScreen />
    </NavigationContainer>
  );
}

export default App;

Tab.Navigator

import * as React from 'react';
import { Text, View, Button } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

import Ionicons from 'react-native-vector-icons/Ionicons';
function HomeScreen({ navigation }) {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Home!</Text>
      <Button
        title="Go to Settings"
        onPress={() => navigation.navigate('Settings')}
      />
    </View>
  );
}

function SettingsScreen({ navigation }) {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Settings!</Text>
      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
    </View>
  );
}

export default function App() {
  const Tab = createBottomTabNavigator();
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions={({ route }) => ({
          tabBarIcon: ({ focused, color, size }) => {
            let iconName;

            if (route.name === 'Home') {
              iconName = focused
                ? 'ios-information-circle'
                : 'ios-information-circle-outline';
            } else if (route.name === 'Settings') {
              iconName = focused ? 'ios-list' : 'ios-list';
            }

            // You can return any component that you like here!
            return <Ionicons name={iconName} size={size} color={color} />;
          },
          tabBarActiveTintColor: 'tomato',
          tabBarInactiveTintColor: 'gray',
        })}
      >
        <Tab.Screen name="Home" component={HomeScreen} options={{ tabBarBadge: 3 }}/>
        <Tab.Screen name="Settings" component={SettingsScreen} />
      </Tab.Navigator>
     
    </NavigationContainer>
  );
}

隐藏顶部导航栏的一些办法

可以设置headerShown: false

<NavigationContainer>
	<Stack.Navigator initialRouteName="Index">
		<Stack.Screen
			name="Index"
      component={IndexScreen}
      options={{ title: "主页" }, {headerShown: false}}  
			/>
	</Stack.Navigator>
</NavigationContainer>
<Tab.Navigator>
	<Tab.Screen 
		name="Home" 
		component={HomeScreen} 
		options={{headerShown:false}}
	/>
	<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>

Stack Navigation常用配置

<Stack.Screen
// 具体参数设定请参考:https://reactnavigation.org/docs/native-stack-navigator#options
	name="Details"
	component={DetailsScreen}
	options={
		{title: "详情"},
		{animation: "slide_from_right"},// 划入方式
		// {headerTitleAlign:"center"}, // 标题居中(近Android,IOS默认居中)
		// {presentation: "formSheet"}, // 几乎仅IOS支持
		{headerShown: true } // 不要隐藏标题,放到最后面写
}  
/>

综合案例

import * as React from "react";
import { Text, View, Button, Dimensions } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import Ionicons from "react-native-vector-icons/Ionicons";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { SafeAreaView } from "react-native-safe-area-context";

// 主页
function IndexScreen({ navigation }) {
  function HomeScreen() {
    return (
      <SafeAreaView edges={['top', 'left', 'right']}
        style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}
      >
        <Button
          title="Go to Details"
          onPress={() => navigation.navigate("Details")}
        />
      </SafeAreaView>
    );
  }
  function SettingsScreen() {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <Text>Settings!</Text>
      </View>
    );
  }
  const Tab = createBottomTabNavigator();
  Tab.navigationOptions = ({navigation}) => {
    //  关键这一行设置 header:null
    return{
        header: null,
    }
  };
  return (
    <Tab.Navigator>
      <Tab.Screen 
        name="Home" 
        component={HomeScreen}
        options={{headerShown:false}}
      />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}

function DetailsScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
      <Text>Home Screen</Text>
      <Button title="Go back" onPress={() => navigation.goBack()} />
    </View>
  );
}

export default function App() {
  const Stack = createNativeStackNavigator();
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Index">
        <Stack.Screen
          name="Index"
          component={IndexScreen}
          options={
            // headerTitleAlign和 headerShown最好别混用
            {title: "主页"}, {animation: "slide_from_right"},
            {headerShown: false}
          }  
        />
        <Stack.Screen
          // 具体参数设定请参考:https://reactnavigation.org/docs/native-stack-navigator#options
          name="Details"
          component={DetailsScreen}
          options={
            {title: "详情"},
            // {headerTitleAlign:"center"}, // 标题居中(近Android,IOS默认居中)
            // {presentation: "formSheet"}, // 几乎仅IOS支持
            {animation: "slide_from_right"},// 划入方式
            {headerShown: true } // 不要隐藏标题
          }  
          
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值