RN开发系列<6>--导航控制器

1. 导航控制器的使用

官方文档
我们要做的界面跳转如下:
A --> B --> C --> D

点击可以“跳转到首页”按钮,跳到栈底,
也可以跳转回上一个界面。

2. 我们为了实现上面的一些基础的跳转功能,我们实现是这样的:

  1. 我们先需要添加一些依赖

(1) yarn add @react-navigation/native
(2) yarn add react-native-screens react-native-safe-area-context

我们为了能使用这些依赖库,我们需要通过pod安装一下。

npx pod-install ios

  1. 整体的架构方面,我们需要用到一个导航容器的组件。
    如下图所示:
    一个大容器组件,里面是一个类似栈结构的组件。
    在这里插入图片描述
    所以我们需要安装创建栈的依赖库

yarn add @react-navigation/native-stack

我们点开package.json,我们可以看到我们的依赖设置如下:

"dependencies": {
    "@react-navigation/native": "^6.0.8",
    "@react-navigation/native-stack": "^6.5.0",
    "react": "17.0.2",
    "react-native": "0.67.3",
    "react-native-safe-area-context": "^4.1.3",
    "react-native-screens": "^3.13.1"
  },
  1. 项目源码如下:
import * as React from 'react';
import {
    View,
    Text,
    StyleSheet,
    Button
} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen({navigation}) {
    return (
        <View style={styles.textStyle}>
            <Text>Home Screen</Text>
            <Button
                title = '跳转'
                onPress = { () => navigation.navigate('Details')}
            />
        </View>
    )
}

const DetailsScreen = ({navigation}) => {
    return (
        <View style = {styles.textStyle}>
            <Text>Details Screen</Text>
            <Button
                title = "跳转到SubDetails"
                onPress = { () => navigation.navigate('SubDetails')}
            />
        </View>
    );
}

const SubDetails = ({navigation}) => {
    return (
        <View style = {styles.textStyle}>
            <Text>Details Screen</Text>
            <Button
                title = "跳转到FourthDetails"
                onPress = { () => navigation.navigate('FourthDetails')}
            />
        </View>
    )
}

const FourthDetails = ({navigation}) => {
    return (
        <View style = {styles.textStyle}>
            <Text>Details Screen</Text>
            <Button
                title = "跳转到首页"
                onPress = { () => navigation.popToTop()}
            />
            <Button
                title = "跳转到DetailsScreen"
                onPress = { () => navigation.navigate('SubDetails')}
            />
            <Button
                title = "手动返回上一个界面"
                onPress = { () => navigation.goBack()}
            />
        </View>
    )
}



const Stack = createNativeStackNavigator();

function  App() {
    return (
        <NavigationContainer>
            <Stack.Navigator initialRouteName = 'Home'>
                <Stack.Screen name = 'Home' component = {HomeScreen}/>
                <Stack.Screen name = 'Details' component = {DetailsScreen}/>
                <Stack.Screen name = 'SubDetails' component = {SubDetails}/>
                <Stack.Screen name = 'FourthDetails' component = {FourthDetails}/>
            </Stack.Navigator>
        </NavigationContainer>
    );
}

export default App;

const styles = StyleSheet.create({
    textStyle: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center'
    }
})

我们的代码入口函数如下:

import * as React from 'react';
import Container from './Navigator';

function App() {
    return (
        <Container/>
    );
}

export default App;

整个程序的入口函数:

/**
 * @format
 */

import {AppRegistry} from 'react-native';
import App from './App/Navigator/index';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

3. 导航控制器之间的传值(顺传)

function HomeScreen({navigation}) {
    return (
        <View style={styles.textStyle}>
            <Text>Home Screen</Text>
            <Button
                title = '跳转'
                onPress = { () => navigation.navigate('Details',{
                    param1: 18,
                    param2: "张三"
                })}
            />
        </View>
    )
}

const DetailsScreen = ({route,navigation}) => {
    const { param1, param2} = route.params;
    return (
        <View style = {styles.textStyle}>
            <Text>Details Screen</Text>
            <Text>年龄:{JSON.stringify(param1)}</Text>
            <Text>姓名:{JSON.stringify(param2)}</Text>
            <Button
                title = "跳转到SubDetails"
                onPress = { () => navigation.navigate('SubDetails')}
            />
        </View>
    );
}

4. 导航控制器之间的传值(逆传)

function HomeScreen({navigation,route}) {
    React.useEffect(() => {
        if (route.params?.post) {

        }
    },[route.params?.post]);

    return (
        <View style={styles.textStyle}>
            <Text>Home Screen</Text>
            <Button
                title = '跳转'
                onPress = { () => navigation.navigate('CreatePost')}
            />
            <Text style = {{margin: 10}}>Post: {route.params?.post == null ? '空的': route.params.post}</Text>
        </View>
    );
}

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

    return (
        <>
            <TextInput
                multiline
                placeholder='你在想什么呢?'
                style = {styles.textInputStyle}
                value = {postText}
                onChangeText = {setPostText}
            />

            <Button
                title = "Done"
                onPress = {() => {
                    navigation.navigate({
                        name: 'Home',
                        params: {post: postText},
                        merge: false,
                    });
                }}
            />
        </>
    );
}

5.设置标题的两种方式

  1. 直接设置
<Stack.Screen name = 'Home' component = {HomeScreen} options = {{ title: '主页'}}/>
  1. 设置通过传参数
  • step1 : 增加参数
<Stack.Screen 
      name = 'Details' 
      component = {DetailsScreen} 
      options = {({ route }) => ({ title: route.params.name })}
 />
  • step2 :传参
<Button
      title = '跳转到details'
      onPress = { () => navigation.navigate('Details', { name: '详情页'})}
 />

6. 导航栏设置样式

  1. 单独设置
<Stack.Screen 
    name = 'Home' 
    component = {HomeScreen} 
    options = {{ 
        title: '主页',
        headerStyle: {
                 backgroundColor: 'green',
          },
          headerTintColor: 'blue',
                  headerTitleStyle: {
                  fontWeight: 'bold'
          }
}}/>
  1. 统一设置,一般来说,都是统一设置的,对每个导航栏都单独设置太麻烦了
            <Stack.Navigator 
                initialRouteName = 'Home'
                screenOptions = {{
                    headerStyle: {
                        backgroundColor: 'blue'
                    },
                    headerTintColor: 'black',
                    headerTitleStyle: {
                        fontWeight: 'bold'
                    }
                }}
  1. 自定义标题,比如把标题用一个图片替换
function LogoTitle() {
    return (
        <Image
            style = {{width: 50, height: 50}}
            source = {require('../assets/english.jpeg')}
        />
    );
}


<Stack.Screen name = 'SubDetails' component = {SubDetails}
         options = {{ 
          headerTitle: (props) => <LogoTitle {...props}/>
          }}
 />

7. 导航栏标题按钮

  1. 在标题中添加按钮
                <Stack.Screen name = 'SubDetails' component = {SubDetails}
                    options = {{ 
                        headerTitle: (props) => <LogoTitle {...props}/>,
                        headerRight: () => (
                            <Button
                                onPress = { () => alert ('点击右上角')}
                                title = "点我"
                                color = '#fff'
                            />
                        )
                    }}
                />
  1. 标题与屏幕交互
    在这里插入图片描述
const SecondScreen = ({navigation}) => {
    const [count, setCount] = React.useState(0);

    React.useLayoutEffect(() => {
        navigation.setOptions({
            headerRight: () => (
                <Button
                    onPress = { () => setCount( c => c + 1)}
                    title = "update count"
                />
            ),
        });
    },[navigation]);

    return (
        <View style = {styles.homeStyle}>
            <Text> 我是SecondScreen: {count} </Text>
            <Button
                title = '点击'
                onPress = {() => setCount ( e => e - 1)}
            />
        </View>
    );
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值