1.react-navigation安装:
安装:npm i react-navigation --save
中文社区:https://reactnative.cn/docs/0.51/navigation.html#content
react navigation:官方文档:https://reactnavigation.org/
2.navigation&tab bar整合:
原理分析:首先无论tab bar还是navigation bar本质都是navigation,而RN与ios原生不同的是,它只有通过导航器来实现页面的跳转,区别于IOS有两种方式:push(针对navigation),present(一般跳转).而RN通过导航器跳转都会默认自带导航栏(可以手动通过UI隐藏,但是没有一般跳转).
一般操作:参考:https://www.jianshu.com/p/93d7838701db
里面有些方法已经过期:需要换成:
import { createStackNavigator, // TabNavigator, createBottomTabNavigator, } from 'react-navigation';
const MainScreentNavigator = createBottomTabNavigator({
const MyNavigatior = createStackNavigator({
然后把MyNavigatior注册成为组件,通过index.js入口进入.
AppRegistry.registerComponent('xxxx', () => MyNavigatior);
一般混合栈的逻辑是:tab stack<---in--navigation stack<--in---screen
3.StackNavigation:
这个是顶部的导航栏,形式如下:
const MainStack = createStackNavigator({ Home: { screen: HomeScreen },//展示的第一个页面 BookVC: { screen: BookVC }, });
首先引入页面:(页面要继承React.Component并且export才可以引入)
import HomeScreen from './HomeScreen'; import BookVC from './BookVC';
***刚开始踩坑,以为screen里面只能装组件,不能装navigation.其实不是的,报的object未定义的错,其实是js编译时从上到下,前面的stack调用了后面才定义的stack才会报错,只要把需要用到的stack放在前面定义即可.
这里有一个很容易混淆的问题:
BookVC: { screen: BookVC },
screen表示显示的页面,这容易理解.前面BookVC很容易出错.首先这里和tab bar不同,不能随便命名.一般使用的是你import进来的页面的命名import BookVC from './BookVC';如果另外命名,会跳转失效.
4.Tab bar(createBottomTabNavigator):
export const TabNavigator = createBottomTabNavigator({ Home: { screen: HomeScreen},//第一个tab Book: { screen: BookStack}, Mybook: {screen: MemberStack}, Member: {screen: MemberStack}, Record: {screen: RecordStack} });
Home: { screen: HomeScreen} Home就是tab的UI名称,同时也是tab stack的index,后面有用.
可以看到上面的tab stack除了Home,里面都装了navigation stack,那么效就是每一个tab里面的页面都可以通过导航器跳转了.
5.navigationOptions:
如果想隐藏导航栏,怎么做呢.两种方法:
一.在建栈的时候就通过如下方式:
const MemberStack = createStackNavigator({ Member: {screen: MemberScreen}, UpdateMemberScreeen: {screen: UpdateMemberScreeen, navigationOptions:{header: null}}, });
二.在类内:
export default class UpdateMemberScreeen extends React.Component { static navigationOptions = { header: null }
如果想隐藏tab bar呢.同理:
一.在建栈时:
const LoginTabNavigator = createBottomTabNavigator({ LoginScreen: { screen: LoginScreen, navigationOptions:{tabBarVisible:false}}, Record: {screen: RecordStack} });
二.在class内:
static navigationOptions = { header: null ,tabBarVisible: false}
这样是导航栏和tab bar都隐藏了.
上面对于单个stack来说操作navigationOptions都很简单,但是混合起来就很容易出现操作失败.
例如
const RecordStack = createStackNavigator({ RecordVC: {screen: RecordVC}, });
const LoginTabNavigator = createBottomTabNavigator({ LoginScreen: { screen: LoginScreen, navigationOptions:{tabBarVisible:false}}, Record: {screen: RecordStack} });
我这里把LoginScreen的tab bar隐藏了,那么如果我想跳转到RecordStack里面又把tab bar显示出来呢?
const RecordStack = createStackNavigator({ RecordVC: {screen: RecordVC, navigationOptions:{tabBarVisible:false}}, });
上面这样做,是不会显示回tab bar的,这是因为
createStackNavigator,createBottomTabNavigator
都是继承NavigationContainer,而navigationOptions是NavigationContainer的父类属性,所以子类在创建的时候都分别有各自的navigationOptions,上面的navigationOptions显然是针对RecordStack,然而createStackNavigator里面并没有tabBarVisible这个属性,所以修改失败.(虽然没有这个属性,但IDE并没有报错,很容易让人误解可以修改tabBarVisible.
综上,使用navigationOptions,要看清楚究竟是哪个stack的,跨stack是无效的.
6.tab bar& navigation跳转:
参考:https://reactnavigation.org/docs/en/tab-based-navigation.html
官方的是简单跳转,基本原理和上面说的一样.
实现点击按钮后跳到另外一个tab:
例如我上面的home页面:
render() { return ( <View style={{flex: 1, flexDirection: 'row', marginTop: 64}}> <Button style={{flex: 1, backgroundColor: 'red', justifyContent: 'center', alignItems: 'center'}} title="预约服务" onPress={() => this.props.navigation.navigate('Book', { title: '選擇服務', des: '我是返回点击我' })} /> <Button style={{flex: 1, backgroundColor: 'red', justifyContent: 'center', alignItems: 'center'}} title="我的预约" onPress={() => this.props.navigation.navigate('Mybook', { title: '選擇服務', des: '我是返回点击我' })} /> <Button style={{flex: 1, backgroundColor: 'red', justifyContent: 'center', alignItems: 'center'}} title="我的会籍" onPress={() => this.props.navigation.navigate('Member', { title: '選擇服務', des: '我是返回点击我' })} /> </View>
有三个按钮,因为home已经装进tab stack,所以点击相应按钮,就可以用
this.props.navigation.navigate('Member', { title: '選擇服務', des: '我是返回点击我' })}
跳转到Member标签里面了.this.props.navigation.push也是可以的.注意navigate('Member'这个参数就是上面你定义的tab stack的index名称.
难点来了,如果我想实现ios里present页面的效果呢.其实就是出栈另外进入一个页面,然后再重新进入原来的栈(因为出栈了,所以上下都没有bar).有些资料提示是混编,进入回ios,用present dismiss.但是纯RN要解决这个问题,就需要一些迂回的思路了.
首先尝试了一般的隐藏bar方法,但是因为上面说了tab和navigator的navigationOptions是分开的,在tab stack隐藏了,进入了login页面,但是login页面再跳转无法再重新显示回来.最烦人的是,RN无论如何都要建stack跳转.那么我们想到再建一个tab stack,只装login就可以.那么就可以在里面隐藏tab bar了.(后来看到另一篇文章讲了一种方法可以跨stack隐藏的,参考https://www.jianshu.com/p/97cafea3ca38?utm_source=desktop&utm_medium=timeline)
例如:
const LoginTabNavigator = createBottomTabNavigator({ LoginScreen: { screen: LoginScreen, navigationOptions:{tabBarVisible:false}}, }); export const TabNavigator = createBottomTabNavigator({ Home: { screen: HomeScreen}, Book: { screen: BookStack}, Mybook: {screen: LoginNavigator}, Member: {screen: MemberStack}, Record: {screen: RecordStack} },
然后在login里面button使用
this.props.navigation.navigate('Member', { title: '選擇服務', des: '我是返回点击我' })}
就可以跳转回原来的tab stack的Member里面了,而且tab bar又重新显示出来了.手动模拟了出栈进栈的效果.
后来再发现了createSwitchNavigator,更方便,不用navigationOptions:{tabBarVisible:false},直接跳进去就没有tab bar了.所以操作是:
onst LoginNavigator = createSwitchNavigator({ LoginScreen: { screen: LoginScreen}, }); // 通过TabNavigator做路由映射 export const TabNavigator = createBottomTabNavigator({ Home: { screen: HomeScreen}, Book: { screen: BookStack}, Mybook: {screen: 持久化结果?LoginNavigator:MemberStack,navigationOptions:{tabBarVisible:持久化结果?false:true}}, Member: {screen: MemberStack}, Record: {screen: RecordStack} },
上面的代码
持久化结果?LoginNavigator:MemberStack
想实现的是,如果我已经登录了,那么我肯定就不需要再跳进去login页面多一次了.怎么设计呢.我们这里可以通过三元运算符.第一次跳进去login页面了,然后登录后给一个已经登录的flag持久化.然后点击按钮跳回Mybook这个tab,里面获取持久化的值,如果已经登录了,就进入MemberStack里面.
最后发现不用再装一个栈这么麻烦,直接
export const TabNavigator = createBottomTabNavigator({ Home: { screen: HomeScreen}, Book: { screen: BookStack}, Mybook: {screen: 持久化结果?LoginScreen:MemberStack,navigationOptions:{tabBarVisible:持久化结果?false:true}}, Member: {screen: MemberStack}, Record: {screen: RecordStack} },
7.<Modal>
今天在最新研究上面这种出栈入栈操作时候,发现了Modal这种操作.一般这是用于弹出一个dialog的操作,但是如果我的dialog是整个页面,就可以实现login页面覆盖上去tab页面的效果了,类似IOS ModalAndView也就present的效果.
login页面:加上持久化(如果已经登录下次不进入login):
import React, { Component } from 'react'; import { Button, Text, View , Modal, AsyncStorage, Dimensions} from 'react-native'; export const deviceWidth = Dimensions.get('window').width; //设备的宽度,单位dp export const deviceHeight = Dimensions.get('window').height; export default class LoginScreen extends React.Component { state = { visible: false, transparent: true, }; getLoginFalg = function() { AsyncStorage.getItem("LoginFalg", (error, result) => { if (!error) { if(result == "true1"){ console.log('已经login' + result) this.setState({visible:false}) }else{ this.setState({visible:true}) } } }) }; loginClick = function() { console.log('Login页面') AsyncStorage.setItem("LoginFalg", "true1", (error) => { if (!error) { // Alert.alert("login success."); console.log('已经login success') this.setState({visible:true}) return } Alert.alert("login failed."); }) }; render() { this.getLoginFalg() console.log('Login页面') return ( <View style={{ flex: 1}}> <Modal visible={this.state.visible} animationType='slide' // transparent={this.state.transparent} onRequestClose={()=>{ // Alert.alert("Modal has been closed."); }} onShow={()=>{ // Alert.alert("Modal has been show."); }}> <View style={{justifyContent: 'center', alignItems: 'center',height:deviceHeight,width:deviceWidth,backgroundColor:'white'}}> <Button title='Login' onPress={()=>this.loginClick()}/> </View> </Modal> </View> ); } }
解释一下持久化:
获取:
AsyncStorage.getItem("LoginFalg", (error, result) => { if (!error) { if(result == "true1"){ console.log('已经login' + result) this.setState({visible:false}) }else{ this.setState({visible:true}) } } })getItem("LoginFalg", (error, result): LoginFalg是Key值,对应setItem的Key.
设置:
AsyncStorage.setItem("LoginFalg", "true1", (error) => { if (!error) { // Alert.alert("login success."); console.log('已经login success') this.setState({visible:true}) return } Alert.alert("login failed."); })setItem("LoginFalg", "true1", (error),=> {,"true1"就是设置的value值.
这样只要在login后的页面里引用一下控件:
import LoginScreen from './LoginScreen' <LoginScreen/>
即可Modal覆盖上去
8.<Navigator>
有一些资料是使用这个标签,重新写navigator的,例如一下项目:
https://github.com/chjwrr/RN-tabbar-navigation
这个标签在0.55版本已经过期了,只能在0.54一下版本使用,要使用的话就需要引入另外一个react-native-deprecate组件.
这里简单说一下,这个组件很多东西都要手动配置,重载方法,看起来是没有最新版本的stack清晰易懂.
creatNavigator (component){ return ( <Navigator initialRoute={{ name: component, component: component }}//默认加载的页面 configureScene={this.configureScene} renderScene={this.renderScene} style={{flex:1}} navigationBar={ <Navigator.NavigationBar style={HomePageNavStyle.navStyleBase} routeMapper={NavigationBarRouteMapper}/>} /> ) }
这个是核心部分.如果想去掉bar的话,不写navigationBar这个属性部分就可以了.
var NavigationBarRouteMapper = { // 标题 Title(route, navigator, index, navState) { return ( <View> <Text> 你好 </Text> </View> ); }, // 左键 LeftButton(route, navigator, index, navState) { if (index > 0) { return ( <View> <TouchableOpacity underlayColor='transparent' onPress={() => { if (index > 0) { navigator.pop() } }}> <Text style={HomePageNavStyle.navLeftButtonStyle}> 返回 </Text> </TouchableOpacity> </View> ); } else { return null; } }, RightButton(route, navigator, index, navState) { if (route.onPress) return ( <View> <TouchableOpacity onPress={() => route.onPress()}> <Text style={HomePageNavStyle.navRightButtonStyle}> right </Text> </TouchableOpacity> </View> ); }, };
这个部分是画navigator bar的ui的,通过style CSS可以控制位置样式等等.
只要在页面使用了
this.props.navigator.push({ component:FirstPage_first })
就可以跳转到下一个页面,而且也有navigator bar
在入口类render内使用:
import 类进来,然后
<HPTB_Navigator/>
会自动进入
相关推荐
在React-Native开发中,创建一个用户界面时,Tab导航是一种常见的设计模式,它允许用户在不同的视图之间轻松切换。本教程将详细介绍如何使用React-Native中的TabBar组件来实现点击Tab标签切换Tab页面的功能。 首先...
3. 自定义Tab Bar:`react-navigation`允许你通过` tabBarOptions`来自定义Tab Bar的样式,包括颜色、字体大小、图标等。例如: ```javascript <Tab.Navigator tabBarOptions={{ activeTintColor: 'tomato', ...
在React Native中,底部导航栏(Bottom Navigation Bar)是一种常见的用户界面元素,它允许用户在应用的多个主要视图之间轻松切换。这个组件是跨平台的,既支持Android也支持iOS,提供了统一的用户体验。在...
本文将深入探讨如何使用React Native配合`wix-react-native-navigation`库来实现导航条、制表符、抽屉和模态等关键组件。 首先,`wix-react-native-navigation`是一个强大的第三方库,它提供了原生级别的导航体验,...
:soap: react-native-bubble-tabbar React Native的Bubble标签栏组件,支持React Navigation V5和TypeScript :rocket: 行动 :package: 安装npm install react react-native styled-components# Or using yarnyarn ...
import { AppRegistry, StyleSheet, Button, Text, View, Image, StatusBar } from 'react-native'; import { StackNavigator, TabBarBottom, TabNavigator } from "react-navigation"; class Home extends React....
R-Design 是基于react native 和 antd-mobile的移动端RN UI Widget。 特性 基于 React Native 的多平台支持。 自由的视觉样式配置,适应各类产品风格。 提供类型定义文件index.d.ts,一看便知如何使用,方便自动提示。...
总的来说,EcoTrip应用是React Native新手开发者的一个良好实践案例,它整合了多个关键的React Native库,提供了一个用户友好的平台来探索和了解巴西的自然生态。对于想要学习React Native和移动应用开发的人来说,...
React本机Tabbar交互 使用React Native进行的滑动插入式FAB的精美Tabbar交互。 在Béhance上查看( ) 在Dribbble上查看( ) ...import TabBar from "@mindinventory/react-native-tab-bar-interacti
已安装React-Navigation v5: : :hammer_and_pick: 用法 const Tab = createBottomTabNavigator ( ) ; const tabBarIcon = ( name : string ) => ( { focused , color , size , } : { focused : boolean ; ...
对于React Native,可以使用`react-navigation`库中的`TabNavigator`或`createBottomTabNavigator`来创建底部导航。通过设置`screenOptions`中的`animationEnabled`和`unmountOnBlur`属性,控制页面滑动动画效果。...
1. **布局与样式设计**:在移动端,Tab页可能采用底部导航栏(Bottom Navigation Bar)或顶部滑动条等形式。炫酷的Tab页往往在颜色搭配、图标设计、文字样式等方面独具匠心,可能包含过渡动画和自定义字体等元素,以...
例如,React Native中的`react-native-tab-view`和Flutter的`flutter_tab_bar`。 总结,自定义TabBar是提高应用用户体验的重要手段,它涉及到界面设计、交互逻辑以及平台特性的理解。通过上述步骤和技巧,开发者...
- React Native:借助`react-native-tab-view`库,通过`TabNavigator`创建底部导航栏。 五、设计与用户体验 在设计`TabBar`时,应遵循以下原则: - 保持简洁:不要超过5个标签,过多的标签会使用户感到困惑。 - ...
在iOS系统中,导航通常分为两种主要类型:底部导航栏(Tab Bar)和顶部导航栏(Navigation Bar)。底部导航栏用于在多个主要功能之间切换,通常最多显示五个图标,点击每个图标可以快速跳转到相应的页面。顶部导航栏...
一些工具和框架,如React Native和Flutter,提供了跨平台开发的能力,允许开发者使用一套代码来实现多平台的UI。 为了优化跨平台的UI设计,开发者应该深入了解每个平台的用户习惯和设计原则。例如,iOS 用户可能更...
此外,支付宝导航代码可能使用了底部导航栏(Bottom Tab Bar)和侧滑抽屉菜单(Drawer Navigation)这两种常见的导航模式。底部导航栏常用于展示主要的功能模块,用户可以通过点击底部的图标在不同页面间切换。侧滑...