【iOS开发】(五)react Native路由和导航20240421-22

【iOS开发】(五)react Native 路由和导航Navigation 20240421

在(一)(二)中我们 Reactnative搭建了开发环境、学习了 基础语法、状态管理,JSX、组件、状态和生命周期以及样式布局等。
在(三)(四) React native 我们介绍了 RN中的基础组件和第三方组件。

今天我们来学习基础语法中最后一块重要的内容,路由和导航。

目录标题

      • 〇 简介路由和导航
          • 路由(Routing)
          • React Navigation
          • 设置导航
          • React Navigation 学习前提条件
            • 1 React Native Express (第1至4节)
            • 2 React的主要概念
            • 3 React Hooks
            • 4 React Context (高级)
      • 一 简介
          • 1 安装组件库
          • 2 安装依赖
          • 3 链接
      • 二 基础组件
        • 1 添加头部组件 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/1c1d340b6d024a1bb5247832a80b2c07.png)
        • 2 添加导航容器
      • 三 几种基本导航类型
          • 1. 堆栈导航(Stack Navigation)
          • 2. 底部标签导航(Bottom Tab Navigation)
          • 3. 抽屉导航(Drawer Navigation)
          • 4. Material顶部标签导航(Material Top Tab Navigation)

〇 简介路由和导航

路由和导航是Web和移动应用中至关重要的概念,它们用于指导用户在应用的不同部分和页面之间移动。

路由(Routing)

路由通常指的是确定一个用户请求应该如何被处理的过程。在Web应用中,路由涉及到解析URL,并根据这个URL映射到相应的页面或视图上。对于复杂的前端Web应用,通常会使用客户端路由来在不同视图间切换而无需从服务器重新加载页面。

在React Native中,路由和导航指的是用户在 不同屏幕或视图(通常称为“路由”) 之间移动的方式。由于React Native是一个用于构建移动应用的框架,所以它的路由和导航是专门为触摸界面设计的,能够处理各种手势操作和过渡动画。

React Navigation

在React Native中,最流行的路由和导航库是React Navigation。它提供了多种导航方法:

  • 堆栈导航(Stack Navigator):
    管理一系列屏幕,用户可以在屏幕间前进和后退。
    使用push和pop操作来管理屏幕堆栈。
  • 底部标签导航(Bottom Tab Navigator):
    在屏幕底部显示标签栏,用户可以通过点击不同的标签来切换视图。
  • 抽屉导航(Drawer Navigator):
    提供从屏幕边缘滑入的导航菜单,类似于抽屉式的交互模式。
  • 顶部标签导航(Material Top Tabs Navigator):
    在屏幕顶部显示标签栏,用户可以通过滑动或点击标签来切换视图。
    这种风格常见于Android应用,使用了Material Design规范。
设置导航

要在React Native应用中设置导航,通常需要以下步骤:

安装React Navigation库及其依赖。
创建导航器(例如堆栈导航器或标签导航器)并定义路由。
使用NavigationContainer组件包裹应用的根组件。

学习本部分内容,建议查漏补缺:

React Navigation 学习前提条件

在开始学习React Navigation之前,确保你已经熟悉以下关键技术和概念。如果你已经有JavaScript、React和React Native的基础,你将能够快速上手React Navigation。如果你对这些还不够熟悉,建议先学习以下内容:

1 React Native Express (第1至4节)
  • 一个快速入门React Native的学习平台。
  • 包含设置开发环境、理解基础组件、状态管理、样式和布局等核心概念。
  • 推荐给刚开始接触React Native的开发者。
2 React的主要概念
  • React官方文档的主要概念部分提供了全面的介绍。
  • 学习内容包括JSX、组件、props、state、事件处理等基础知识。
  • 强烈建议理解组件生命周期和组件间的数据流。
3 React Hooks
  • React Hooks是React 16.8引入的新特性,允许在函数组件中使用state和其他React特性。
  • 重要的Hooks包括useState, useEffect, useContext等。
  • React官方文档提供了详细的Hooks介绍和使用指南。
4 React Context (高级)
  • Context API允许组件跨层级直接共享状态,而不是通过props链式传递。
  • 对于主题、用户认证、应用偏好等跨组件共享的数据非常有用。
  • 需要注意的是,不当使用可能会导致组件难以维护,因此建议在真正需要全局状态管理时才使用。

在了解了这些基础知识后,你将更好地准备学习React Navigation,并在你的React Native应用中实现复杂的导航逻辑。

一 简介

在React Native中,路由和导航是管理应用中页面或视图之间切换的关键技术。要实现这一功能,通常会使用第三方库,因为React Native本身并不包括内建的导航系统。React Navigation:流行的路由和导航库的组件。。
这是React Native中最流行的导航库组件之一。
它支持堆栈导航、标签导航、抽屉导航等多种导航方式。
React Navigation易于使用,并且高度可定制,支持屏幕转换动画、传递参数到不同屏幕等功能。

1 安装组件库
npm install @react-navigation/native

2 安装依赖
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

这个命令会安装以下库:

  • react-native-reanimated:提供更为强大和灵活的动画库,用于创建复杂的动画和交互。
  • react-native-gesture-handler:一个用来处理触摸手势的库,它优化了触摸响应的性能和体验。
  • react-native-screens:利用原生平台的视图容器来优化内存使用和性能
  • react-native-safe-area-context:提供了一个安全区域的上下文,可以用来适配屏幕的安全区域,避免界面元素与设备特定的屏幕部位(如刘海、圆角等)冲突。
  • @react-native-community/masked-view:一个实现遮罩视图的库,可以用来在视图上创建遮罩效果。

确保React Native环境已经配置好,并且这些库与React Native版本兼容。在安装这些库后,可能需要链接某些库(如果你的React Native版本低于0.60),并对Android和iOS项目进行必要的配置,以确保一切正常工作。

3 链接
  • RN0.60 后安卓环境自动链接路由(Android 无需任何操作 )
  • ios下需要手动链接路由
npx pod-install ios

二 基础组件

1 添加头部组件 在这里插入图片描述

首先,需要在应用的最顶部导入react-native-gesture-handler。这是因为react-native-gesture-handler提供了一个可以更精细地控制手势和触摸事件的系统,这对于实现流畅的导航动画和用户体验至关重要。

导入这个模块的正确位置是在应用的入口文件中,通常是index.js或App.js。这需要放在任何其他代码之前,因为它要尽可能早地在应用中设置好手势处理的环境。

这里是一个示例代码:

// index.js 或 App.js
import 'react-native-gesture-handler'; // 这行代码要放在最上面
// 其他的导入和代码...
 
2 添加导航容器

导航容器(NavigationContainer)是一个组件,它管理着你的应用状态和导航树结构,它必须包裹在你的应用外层,这样React Navigation库才能正常工作。它通常也是放在index.js或App.js文件中。

这里是如何包裹你的应用:

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import MyStack from './MyStack'; // 假设你有一个堆栈导航器设置在另一个文件中

const App = () => {
  return (
    <NavigationContainer>
      <MyStack />
    </NavigationContainer>
  );
};

export default App;

在上面的例子中,MyStack是一个假设的组件,它表示你的应用的堆栈导航。当然,你可以根据需要替换为你自己的导航结构,无论是底部标签导航、抽屉导航还是其他类型的导航。

确保你的整个应用都被NavigationContainer包裹着,这样无论你在应用中的哪个部分,React Navigation都能访问当前的导航状态。这是启用导航功能的必备结构。

三 几种基本导航类型

详细介绍React Navigation中的几种基本导航类型:堆栈导航(Stack Navigation)、底部标签导航(Bottom Tab Navigation)、抽屉导航(Drawer Navigation)以及Material顶部标签导航(Material Top Tab Navigation)。

1. 堆栈导航(Stack Navigation)

堆栈导航允许应用维护一个页面的堆栈,类似于导航控制器。新的页面可以放到堆栈的顶部,并且可以返回到之前的页面。

主要特性

  • 页面间的无缝过渡。
  • 可以自定义过渡动画。
  • 支持页面传参。
 npm install @react-navigation/stack

// 引入所需的React Native组件
import {
  Text, // 用于显示文本
  StyleSheet, // 用于定义组件的样式
  View, // 用作容器,可以包裹其他组件
  Button, // 显示一个可点击的按钮
  TouchableOpacity, // 一个包装器,可以包含其他组件,并使它们可触摸
  Alert, // 提供弹出警告对话框的功能
} from 'react-native';
import React, {Component} from 'react'; // 引入React以及类组件的基类Component
import {createStackNavigator} from '@react-navigation/stack'; // 引入创建堆栈导航器的函数
import { NavigationContainer } from '@react-navigation/native'; // 引入包裹导航器的容器组件

// 定义HomeScreen组件,表示主屏幕
function HomeScreen(prop) {
  // 展示基本信息,并提供一个按钮用于跳转到NewsScreen页面
  return (
    <View style={styles.container}>
      <Text style={styles.text}>HomeScreen</Text>
      <Button
        title={'跳到新闻页面'}
        onPress={() => prop.navigation.navigate('News')} // 使用navigate方法跳转到指定的路由(页面)
      />
    </View>
  );
}

// 定义NewsScreen组件,表示新闻页面
function NewsScreen(prop) {
  // 类似HomeScreen,展示基本信息,并提供一个按钮用于返回HomeScreen页面
  return (
    <View style={styles.container}>
      <Text style={styles.text}>NewsScreen</Text>
      <Button
        title={'跳转到Home页面'}
        onPress={() => prop.navigation.navigate('Home')} // 使用navigate方法跳转回HomeScreen
      />
    </View>
  );
}

const Stack = createStackNavigator(); // 创建一个堆栈导航器

// 定义Index类组件,作为应用的主组件
export default class Index extends Component {
  render() {
    // 使用NavigationContainer包裹导航器,确保导航状态正确管理
    return (
      <NavigationContainer> 
        
        <Stack.Navigator  
        initialRouteName='News'   screenOptions={{headerShown:true}}>

          <Stack.Screen
            name="Home" // 路由名称
            component={HomeScreen} // 与此路由关联的组件
            options={{
              title: '首页', // 设置屏幕顶部导航条的标题
              headerStyle: {
                backgroundColor: 'tomato', // 自定义标题栏背景颜色
              },
              headerRight: () => (
                // 添加一个按钮在标题栏右侧
                <TouchableOpacity onPress={() => Alert.alert('Hello')}>
                  <Text style={{ marginRight: 15 }}>Hello</Text>
                </TouchableOpacity>
              ),
            }}
          />
          <Stack.Screen name="News" component={NewsScreen} />
        </Stack.Navigator>
      </NavigationContainer>
    );
  }
}

// 定义组件的样式
const styles = StyleSheet.create({
  container: {
    flex: 1, // flex: 1 使组件填满父容器的全部空间
    justifyContent: 'center', // 垂直居中显示
    alignItems: 'center', // 水平居中显示
  },
  text: {
    fontSize: 40, // 设置字体大小
  },
});

简介版

import { Text, StyleSheet, View, Button } from 'react-native';
import React, { Component } from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';

function HomeScreen(props) {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Home Screen</Text>
      <Button 
        title="跳转到新闻"
        onPress={() => props.navigation.navigate('News')}
      />
    </View>
  );
}

function NewsScreen(props) {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>News Screen</Text>
      <Button
        title="跳转到home主页"
        onPress={() => props.navigation.navigate('Home')}
      />
    </View>
  );
}

const Stack = createStackNavigator();

export default class Index extends Component {
  render() {
    return (
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen
            name='Home'
            component={HomeScreen}
          />
          <Stack.Screen
            name='News'
            component={NewsScreen}
          />
        </Stack.Navigator>
      </NavigationContainer>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center"
  },
  text: {
    fontSize: 40,
  }
});

关于navigation对象和navigate方法:
navigation是React Navigation传递给每个屏幕组件的对象,它包含了控制导航的多种方法。
navigate方法用于触发导航到应用中的其他屏幕,通常接受目标屏幕的名字作为参数,也可以传递附加数据。
<Stack.Screen />组件:
<Stack.Screen />是一个React Navigation的组件,用于在堆栈导航器中注册一个新的屏幕。
name属性定义了屏幕的标识符,用于编程时引用和导航到这个屏幕。
component属性指定当导航到这个屏幕时应该渲染哪个组件。

此代码中,

  <Text style={[styles.text]}>Home Screen</Text>
      <Button 

        title={'跳转到新闻'}


        /**
         * 
        
        prop:
        prop 是 React 中组件接收的参数,它包含了传递给组件的所有属性。
        在使用 React Navigation 时,所有通过导航器(Navigator)加载的组件会自动接收一个 navigation 属性。这个属性包含了一系列方法,用来编程式地控制导航行为,如跳转、后退等。
        
        prop.navigation:
        navigation 是 React Navigation 传递给每个屏幕组件的对象,包含了多种导航相关的方法和属性。通过这个对象,你可以控制应用的导航状态,执行如跳转、返回、参数传递等操作。
        navigate:
        navigate 是 navigation 对象中的一个方法,用于触发导航到应用中的其他屏幕。这个方法接受一个参数,通常是目标屏幕的名字(在代码中为 'News'),这个名字是在你设置导航器时定义的屏幕名。
        navigate 方法还可以接收第二个可选参数,用于传递数据到目标屏幕。这可以使你在不同的页面间传递需要的信息。
        简单来说,当你在 HomeScreen 组件中点击按钮时,onPress 事件会触发 prop.navigation.navigate('News') 调用,这会告诉 React Navigation 切换视图到 NewsScreen 组件。
         */

        //此处写一个具体的事件 onPress ,里面是回调函数   ()=>  
        // 可以通过传过来的参数 prop来跳转
        //prop 里面有 
        onPress={() => props.navigation.navigate('News')}
      />

在这里插入图片描述

2. 底部标签导航(Bottom Tab Navigation)

底部标签导航在屏幕底部显示多个标签,用户可以切换不同的视图或页面。

主要特性
适合快速切换不同视图的应用。
可定制标签样式和动画。

npm install @react-navigation/bottom-tabs

我们要使用icon图标 所以也装一下


react-native-vector-icons/Ionicons 是一个在 React Native 应用中广泛使用的库,它提供了一套丰富的矢量图标,可以轻松地在移动应用中使用。这些图标是基于矢量技术的,意味着它们在不同的屏幕分辨率和尺寸上都可以保持清晰。Ionicons 是这个库中的一个图标集,它包括了一系列优雅的、常用的图标,适用于多种用户界面设计。

主要特点
跨平台支持:这些图标可以在 iOS 和 Android 平台上使用,且看起来一致。
自定义和扩展性:你可以轻松地调整图标的大小、颜色和样式,使其适应你的应用设计。
丰富的图标资源:Ionicons 包括了数百个图标,涵盖了大多数常见的 UI 设计需求。

在这里插入图片描述

/* eslint-disable react/no-unstable-nested-components */
import {Text, StyleSheet, View, Button} from 'react-native';
import React, {Component} from 'react';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';
import { NavigationContainer } from '@react-navigation/native';

function HomeScreen(props) {  // 更正 prop 为 props,这是常规的参数命名约定
  return (
    <View style={styles.container}>
      <Text style={styles.text}>HomeScreen</Text>
      <Button
        title="跳到新闻页面"  // 保持引号的一致性
        onPress={() => props.navigation.navigate('News')}
      />
    </View>
  );
}

function NewsScreen(props) {  // 更正 prop 为 props
  return (
    <View style={styles.container}>
      <Text style={styles.text}>NewsScreen</Text>
      <Button
        title="跳转到Home页面"  // 保持引号的一致性
        onPress={() => props.navigation.navigate('Home')}
      />
    </View>
  );
}

const Tab = createBottomTabNavigator();

export default class Index extends Component {
  render() {
    return (
      <NavigationContainer>
        <Tab.Navigator
          screenOptions={({route}) => ({
            tabBarIcon: ({focused, color, size}) => {
              let iconName;
              if (route.name === 'Home') {
                iconName = focused ? 'add-circle' : 'add-circle-outline';
              } else if (route.name === 'News') {
                iconName = focused ? 'person' : 'person-outline';
              }
              return <Icon name={iconName} size={size} color={color} />;
            },
            tabBarActiveTintColor: 'tomato',  // 将 tabBarOptions 的设置迁移到 screenOptions 中
            tabBarInactiveTintColor: 'gray',
          })}
        >
          <Tab.Screen name="Home" component={HomeScreen} />
          <Tab.Screen name="News" component={NewsScreen} />
        </Tab.Navigator>
      </NavigationContainer>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 40,
  },
});

/* eslint-disable react/no-unstable-nested-components */
import {Text, StyleSheet, View, Button} from 'react-native';
import React, {Component} from 'react';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';
import { NavigationContainer } from '@react-navigation/native';

function HomeScreen(props) {  // 更正 prop 为 props,这是常规的参数命名约定
  return (
    <View style={styles.container}>
      <Text style={styles.text}>HomeScreen</Text>
      <Button
        title="跳到新闻页面"  // 保持引号的一致性
        onPress={() => props.navigation.navigate('News')}
      />
    </View>
  );
}

function NewsScreen(props) {  // 更正 prop 为 props
  return (
    <View style={styles.container}>
      <Text style={styles.text}>NewsScreen</Text>
      <Button
        title="跳转到Home页面"  // 保持引号的一致性
        onPress={() => props.navigation.navigate('Home')}
      />
    </View>
  );
}

const Tab = createBottomTabNavigator();

export default class Index extends Component {
  render() {
    return (
      <NavigationContainer>
        <Tab.Navigator
          screenOptions={({route}) => ({
            tabBarIcon: ({focused, color, size}) => {
              let iconName;
              if (route.name === 'Home') {
                iconName = focused ? 'add-circle' : 'add-circle-outline';
              } else if (route.name === 'News') {
                iconName = focused ? 'person' : 'person-outline';
              }
              return <Icon name={iconName} size={size} color={color} />;
            },
            tabBarActiveTintColor: 'tomato',  // 将 tabBarOptions 的设置迁移到 screenOptions 中
            tabBarInactiveTintColor: 'gray',
          })}
        >
          <Tab.Screen name="Home" component={HomeScreen} />
          <Tab.Screen name="News" component={NewsScreen} />
        </Tab.Navigator>
      </NavigationContainer>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 40,
  },
});

3. 抽屉导航(Drawer Navigation)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

抽屉导航通过滑动或点击图标来展开一个从页面边缘滑出的导航面板。

主要特性
可以包含用户账户信息、链接列表等。
支持手势操作。

Uncaught Error [Reanimated] Failed to create a worklet. See https://docs.swmansion.com/react-native-reanimated/docsguides/troubleshooting#failed-to-create-a-workletfor more details. Source

看起来您遇到的错误与react-native-reanimated的工作单元(worklet)有关。这个问题通常发生在Reanimated的工作单元无法正确初始化时。下面是一些可能的解决步骤:

解决步骤
确认Reanimated插件:
确保babel.config.js中正确添加了react-native-reanimated/plugin。这一步是必要的,因为Reanimated 2 需要这个插件来正确转换工作单元代码。配置应如下所示:

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: ['react-native-reanimated/plugin'],
};

如果已经配置了插件,试着再次清理缓存:

yarn start --reset-cache

在项目目录内执行:

npx react-native start --reset-cache

在这里插入图片描述

import React, { Component } from 'react';
import { Text, StyleSheet, View, Button } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import Icon from 'react-native-vector-icons/Ionicons';

function HomeScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>HomeScreen</Text>
      <Button
        title="Open Drawer"
        onPress={() => navigation.openDrawer()}
      />
      <Button
        title="Toggle Drawer"
        onPress={() => navigation.toggleDrawer()}
      />
    </View>
  );
}

function NewsScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>NewsScreen</Text>
      <Button
        title="Open Drawer"
        onPress={() => navigation.openDrawer()}
      />
      <Button
        title="跳转到Home页面"
        onPress={() => navigation.navigate('Home')}
      />
    </View>
  );
}

const Drawer = createDrawerNavigator();

function Index() {
  return (
    <Drawer.Navigator
      screenOptions={{
        drawerStyle: {
            backgroundColor: '#c6cbef',
            width: 180,
          },
          drawerPosition: 'right',
          drawerType: 'slide',
          drawerActiveTintColor: 'red',
          drawerItemStyle: {
            marginVertical: 20,
          },
      }}>
      <Drawer.Screen
        options={{
          title: '首页',
          drawerIcon: ({ focused, color, size }) => (
            <Icon name={focused ? 'home' : 'home-outline'} size={size} color={color} />
          ),
        }}
        name="Home"
        component={HomeScreen}
      />
      <Drawer.Screen
        options={{
          title: '新闻',
          drawerIcon: ({ focused, color, size }) => (
            <Icon name={focused ? 'person' : 'person-outline'} size={size} color={color} />
          ),
        }}
        name="News"
        component={NewsScreen}
      />
    </Drawer.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <Index />
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 40,
  },
});

下面带注释

/* eslint-disable react/no-unstable-nested-components */
import {Text, StyleSheet, View, Button} from 'react-native';
import React, {Component} from 'react';
import {createDrawerNavigator} from '@react-navigation/drawer';
import Icon from 'react-native-vector-icons/Ionicons';
import { NavigationContainer } from '@react-navigation/native';

/**
 * drawer编译错误[Reanimated] `valueUnpacker` is not a worklet, js engine: hermes
 * 的解决办法 参考文章https://blog.csdn.net/lxyoucan/article/details/121851577
 * 第一步
 * 修改配置文件babel.config.js(在项目根目录)并增加plugins: ['react-native-reanimated/plugin'],
 * 示例:
 * module.exports = {
 *   presets: [‘module:metro-react-native-babel-preset’],
 *   plugins: [‘react-native-reanimated/plugin’],
 * };
 * 第二步
 * cmd命令行进入项目根目录,然后执行
 * yarn start --reset-cache
 * 清除缓存
 * 以上执行完毕之后
 * 关掉模拟器重新执行项目即可正常
 */

function HomeScreen(prop) {
  // 跳转方法prop.navigation.navigate参数是路由名称也就是Stack.Screen name
  return (
    <View style={[styles.container]}>
      <Text style={[styles.text]}>HomeScreen</Text>
      <Button
        title={'Open Drawer'}
        onPress={() => prop.navigation.openDrawer()}
      />
      <Button
        title={'Toggle Drawer'}
        onPress={() => prop.navigation.toggleDrawer()}
      />
    </View>
  );
}

function NewsScreen(prop) {
  return (
    <View style={[styles.container]}>
      <Text style={[styles.text]}>NewsScreen</Text>
      <Button
        title={'Open Drawer'}
        onPress={() => prop.navigation.openDrawer()}
      />
      <Button
        title={'跳转到Home页面'}
        onPress={() => prop.navigation.navigate('Home')}
      />
    </View>
  );
}

const Drawer = createDrawerNavigator();

export default class Index extends Component {
  render() {
    return (
      <NavigationContainer>

      <Drawer.Navigator
        // 这里新版本和教程有变化,新版本属性写在screenOptions里
        screenOptions={{
          drawerStyle: {
            backgroundColor: '#c6cbef',
            width: 180,
          },
          drawerPosition: 'right', // 控制菜单从左left或者右right弹出
          drawerType: 'slide', // 菜单的滑动形式
          drawerActiveTintColor: 'red', // 当前激活的菜单颜色
          // 设置菜单项的样式
          drawerItemStyle: {
            marginVertical: 20,
          },
        }}>
        <Drawer.Screen
          options={{
            title: '首页', // 自定义当前项的标题
            drawerIcon: ({focused, color, size}) => {
              let iconName = '';
              iconName = focused ? 'home' : 'home-outline';
              return <Icon name={iconName} size={size} color={color} />;
            },
          }}
          name="Home"
          component={HomeScreen}
        />
        <Drawer.Screen
          options={{
            title: '新闻', // 自定义当前项的标题
            drawerIcon: ({focused, color, size}) => {
              let iconName = '';
              iconName = focused ? 'person' : 'person-outline';
              return <Icon name={iconName} size={size} color={color} />;
            },
          }}
          name="News"
          component={NewsScreen}
        />
      </Drawer.Navigator>
      </NavigationContainer>

    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 40,
  },
});

4. Material顶部标签导航(Material Top Tab Navigation)

使用Material Design指南来实现顶部标签的滑动切换界面。

主要特性
支持滑动操作切换标签。
可定制动画和样式。

import {Text, StyleSheet, View} from 'react-native';
import React, {Component} from 'react';
import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs';
import Icon from 'react-native-vector-icons/Ionicons';
import { NavigationContainer } from '@react-navigation/native';
import PagerView from 'react-native-pager-view';

function OrderunpayScreen() {
  return (
    <View style={[styles.container]}>
      <Text style={[styles.text]}>待付款</Text>
    </View>
  );
}

function OrderPaidScreen() {
  return (
    <View style={[styles.container]}>
      <Text style={[styles.text]}>待发货</Text>
    </View>
  );
}

function OrderSentScreen() {
  return (
    <View style={[styles.container]}>
      <Text style={[styles.text]}>待收货</Text>
    </View>
  );
}

function OrderFinishScreen() {
  return (
    <View style={[styles.container]}>
      <Text style={[styles.text]}>待评价</Text>
    </View>
  );
}

const MTab = createMaterialTopTabNavigator();

export default class index extends Component {
  render() {
    // tabBarPosition 导航条的位置top|bottom默认是top
    return (

      <NavigationContainer>
      <MTab.Navigator
        tabBarPosition="bottom"
        screenOptions={{
          // tabBar的整体样式
          tabBarStyle: {
            borderWidth: 1,
            borderColor: 'grey',
          },
          // 标签样式
          tabBarLabelStyle: {
            fontSize: 20,
          },
          tabBarActiveTintColor: 'red', // 当前标签页标签激活时的颜色
          tabBarInactiveTintColor: '#666', // 当前标签页标签未激活时的颜色
          tabBarShowIcon: true, //是否显示图标
        }}>
        <MTab.Screen
          name="OrderUnpay"
          component={OrderunpayScreen}
          options={{
            title: '待付款',
            tabBarIcon: ({focused, color}) => {
              return <Icon name="hammer-outline" color={color} size={20} />;
            },
          }}
        />
        <MTab.Screen
          name="OrderPaid"
          component={OrderPaidScreen}
          options={{
            title: '待发货',
            tabBarIcon: ({focused, color}) => {
              return (
                <Icon
                  name="arrow-redo-circle-outline"
                  color={color}
                  size={20}
                />
              );
            },
          }}
        />
        <MTab.Screen
          name="OrderSent"
          component={OrderSentScreen}
          options={{
            title: '待收货',
            tabBarIcon: ({focused, color}) => {
              return <Icon name="arrow-redo-outline" color={color} size={20} />;
            },
          }}
        />
        <MTab.Screen
          name="OrderFinish"
          component={OrderFinishScreen}
          options={{
            title: '待评价',
            tabBarIcon: ({focused, color}) => {
              return (
                <Icon
                  name="chatbubble-ellipses-outline"
                  color={color}
                  size={20}
                />
              );
            },
          }}
        />
      </MTab.Navigator>
      </NavigationContainer>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 40,
  },
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/569097.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024 OceanBase 开发者大会:OceanBase 4.3正式发布,打造PB级实时分析数据库

4月20日&#xff0c;2024 OceanBase开发者大会盛大召开&#xff0c;吸引了50余位业界知名的数据库专家和爱好者&#xff0c;以及来自全国各地的近600名开发者齐聚一堂。他们围绕一体化、多模、TP与AP融合等前沿技术趋势展开深入讨论&#xff0c;分享场景探索的经验和最佳实践&a…

STM32H750外设ADC之动态低功耗特性

目录 概述 1 模式实现&#xff08;AUTDLY&#xff09; 2 自动注入模式 (JAUTO1) 3 AUTDLY 模式 4 实现案例 概述 本文主要介绍STM32H750外设ADC之动态低功耗特性相关的内容。包括&#xff1a;模式实现&#xff08;AUTDLY&#xff09;、自动注入模式 (JAUTO1)、 AUTDLY 模…

【1646】医院人员管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 医院人员管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

力扣经典150题(3)

文章目录 17.电话号码的字母组合77.组合46.全排列74.搜索二维矩阵215.数组中的第K个最大元素 17.电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相…

金融风控信用评分卡建模(Kaggle give me credit数据集)

1 数据预处理数据 数据来源于Kaggle的Give Me Some Credit&#xff0c;包括25万条个人财务情况的样本数据 1.1 导包读数据 import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.ensemble import RandomForestRegressor import seaborn as …

STM32 学习13 低功耗模式与唤醒

STM32 学习13 低功耗模式与唤醒 一、介绍1. STM32低功耗模式功能介绍2. 常见的低功耗模式&#xff08;1&#xff09;**睡眠模式 (Sleep Mode)**:&#xff08;2&#xff09;**停止模式 (Stop Mode)**:&#xff08;3&#xff09;**待机模式 (Standby Mode)**: 二、睡眠模式1. 进入…

Android视角看鸿蒙第十二课-鸿蒙的布局之相对布局RelativeContainer

Android视角看鸿蒙第十二课-鸿蒙的布局之相对布局RelativeContainer 导读 相对布局和线性、层叠布局一样都是类似于Android布局的&#xff0c;之前两篇文章已经了解线性、层叠布局的使用方法&#xff0c;这篇文章一起来学习下鸿蒙中的相对布局。 之前的文章中&#xff0c;我偶…

C#基础|对象属性Property基础使用,业务特性

哈喽&#xff0c;你好&#xff0c;我是雷工。 探究OOP中属性的奥秘 认识类的属性&#xff08;Property&#xff09; 01 属性的使用 作用&#xff1a;在面向对象&#xff08;OOP&#xff09;中主要用来封装数据。 要求&#xff1a;一般采用Pascal命名法&#xff08;首字母要…

解决Linux CentOS 7安装了vim编辑器却vim编辑器不起作用、无任何反应

文章目录 前言一、解决vim不起作用&#xff08;卸载重新安装&#xff09;1.重新安装vim2.测试vim是否能正常使用 二、解决vim: error while loading shared libraries: /lib64/libgpm.so.2: file too short报错三、解决vim编辑器不能使用方向键和退格键问题 remove vim-common …

QT绘制。矩形A绕点B旋转。要求B点与矩形的角相连的直线,始终保持最短

矩形A绕点B旋转。要求B点与矩形的角相连的直线&#xff0c;始终保持最短 已知矩形4个角的坐标&#xff08;H0,H1,H2,H3&#xff09;&#xff0c;B点的坐标. 思路&#xff1a; 判断矩形的位置&#xff0c;在B点的左上&#xff0c;左下&#xff0c;右上&#xff0c;右下 怎么判断…

ubuntu 使用conda 创建虚拟环境总是报HTTP错误,转换多个镜像源之后仍报错

最近在使用Ubuntu conda创建虚拟环境时&#xff0c;总是报Http错误&#xff0c;如下图所示&#xff1a; 开始&#xff0c;我以为是conda 镜像源的问题&#xff0c;但是尝试了好几个镜像源都不行&#xff0c;还是报各种各样的HTTP错误。后来查阅很多&#xff0c;总算解决了。解…

简化图卷积 笔记

1 Title Simplifying Graph Convolutional Networks&#xff08;Felix Wu、Tianyi Zhang、Amauri Holanda de、 Souza Jr、Christopher Fifty、Tao Yu、Kilian Q. Weinberger&#xff09;【ICML 2019】 2 Conclusion This paper proposes a simplified graph convolutional m…

栈和队列-介绍与实现(超级!!!详解-C语言)

目录 栈 栈的介绍 栈的概念 栈的结构 栈的实现 初始化栈 StackInit 销毁栈 StackDestroy 入栈 StackPush 出栈 StackPop 获取栈顶元素 StackTop 检查栈是否为空 StackEmpty 获取栈中有效元素个数 StackSize 队列 队列的介绍 队列的概念 队列的结构 队列的应用 队列的实现 …

上位机图像处理和嵌入式模块部署(树莓派4b用skynet实现进程通信)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;在工业系统上面一般都是使用多进程来代替多线程。这后面&#xff0c;主要的原因还是基于安全的考虑。毕竟一个系统里面&a…

吴恩达机器学习笔记:第 8 周-13 聚类(Clustering)13.3-13.5

目录 第 8 周 13、 聚类(Clustering)13.3 优化目标13.4 随机初始化 第 8 周 13、 聚类(Clustering) 13.3 优化目标 K-均值最小化问题&#xff0c;是要最小化所有的数据点与其所关联的聚类中心点之间的距离之和&#xff0c;因此 K-均值的代价函数&#xff08;又称畸变函数 Dis…

如何从架构层面降低公有云多可用区同时故障的概率

阿里云和腾讯云都曾出现过因一个组件故障而导致所有可用区同时瘫痪的情况。本文将探讨如何从架构设计的角度减小故障域&#xff0c;在故障发生时最小化业务损失&#xff0c;并以 Sealos 的稳定性实践为例&#xff0c;分享经验教训。 抛弃主从&#xff0c;拥抱点对点架构 从腾…

如何安全高效地进行网点文件下发?

随着IT技术的飞速发展&#xff0c;以银行为代表的企业数字化技术转型带来了大量的电子化文档传输需求。文件传输数量呈几何级数增长&#xff0c;传统集中式文件传输模式在爆炸式的增长需求下&#xff0c;银行网点文件下发的效率、可靠性、安全性等方面&#xff0c;都需要重点关…

Spring Boot:Web应用开发之增删改查的实现

Spring Boot 前言实现增删改查功能 前言 增删改查功能作为 Web 应用中的基础且重要的组成部分&#xff0c;是基本的数据库操作&#xff0c;也是实现业务逻辑和功能的关键要素。下面简单介绍使用 Spring Boot 实现增删改查的功能。 实现增删改查功能 在上一章 Spring Boot&am…

jvm(JVM快速入门、stack栈、堆、GC垃圾回收、Arthas)

文章目录 1. JVM快速入门1.1. 结构图1.2. 类加载器ClassLoader1.3. 执行引擎Execution Engine1.4. 本地接口Native Interface1.5. Native Method Stack1.6. PC寄存器(程序计数器)1.7. Method Area方法区 2. stack栈3. 堆3.1. 堆体系概述3.1.1. 新生区3.1.2. 老年代3.1.3. 永久代…

分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测

分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测 目录 分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类…