ReactNative使用bottom-tabs搭一个简单的框架

1.需求

使用ReactNative 的 bottom-tabs组件搭建一个App端框架,在实践的过程中,遇到了几个小问题,特此记录下。

项目需要安装以下组件。

    "react": "17.0.2",
    "react-native": "0.66.3",
    "@react-navigation/bottom-tabs": "^6.2.0",
    "@react-navigation/native": "^6.0.8",
    "@react-navigation/native-stack": "^6.5.0",
    "react-native-screens": "^3.12.0"

2.效果如下

 3.编码

项目结构如下,页面全部放置在了src/view目录下。

 

 

3.1欢迎页

一般App都会有欢迎页面,这里我的做法是在App注册的时候,直接指向欢迎页面。

如果项目不需要欢迎页,可以在App注册时,直接指向Nav.js

import {AppRegistry} from 'react-native';
import Welcome  from './src/view/welcome';
import {name as appName} from './app.json';

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

欢迎页代码如下

        主要逻辑是在欢迎页显示 2秒后,自动加载Nav.js,Nav文件里面是具体的底部Tab导航的实现以及项目的主要架构。

import React, {Component} from 'react';
import {ImageBackground, Text, View, 
  StatusBar,
} from 'react-native';
import Nav from './Nav'
export default class Welcome extends Component{
	constructor(props){
		super(props);
    this.state = {
      start: false,
    }
    setTimeout(()=>{
      this.setState({start: true})

		},2000)
	}
	render(){
		return(
      <View style={{flex:1}}>
        { this.state.start?<Nav/>:
        <View style={{width: '100%',height:'100%'}}>
          <StatusBar
          animated={false} //指定状态栏的变化是否应以动画形式呈现。目前支持这几种样式:backgroundColor, barStyle和hidden
          hidden={false}  //是否隐藏状态栏。
          networkActivityIndicatorVisible={false}//仅作用于ios。是否显示正在使用网络。
          showHideTransition={'fade'}//仅作用于ios。显示或隐藏状态栏时所使用的动画效果(’fade’, ‘slide’)。
          backgroundColor='rgba(255,255,255,0)'// {'transparent'} //状态栏的背景色
          translucent={true}//指定状态栏是否透明。设置为true时,应用会在状态栏之下绘制(即所谓“沉浸式”——被状态栏遮住一部分)。常和带有半透明背景色的状态栏搭配使用。
          barStyle={'light-content'} // enum('default', 'light-content', 'dark-content')
        />
          <ImageBackground source={require('../image/green.jpg')} 
          style={{width: '100%',height:'100%',justifyContent:'center',alignItems:'center'}} >
            <Text style={{fontSize:20,color:'blank'}}>Welcome</Text>
          </ImageBackground>
        </View>
      }
      </View>
		)
	}
}

 3.2 主体架构Nav文件

这里耗时比较久的是进入二级页面需要隐藏底部 Tab栏,比如进入详情页,需要隐藏底部的Tab导航栏,这里使用了自定义的组件(MyTabBar方法)来实现底部 Tab的隐藏和显示

Nav.js完整代码如下

import * as React from 'react';
import { Text, View ,StyleSheet,Image, StatusBar,
  TouchableOpacity
} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeView from './index/home'
import DetailView from './index/detail'
import SettingView from './setting/index'
//头部导航栏的配置
const headerOpt ={
  headerStyle: {
    backgroundColor: '#ED5100',
  },
  headerTintColor: '#fff',
  headerTitleStyle: {
    fontWeight: 'bold',
  },
}
const HomeStack = createNativeStackNavigator();

function HomeStackScreen() {
  //headerShown 是否显示顶部标题栏
  return (
    <HomeStack.Navigator
      >
      <HomeStack.Screen options={{headerShown:false }} name="Home" component={HomeView} />
      <HomeStack.Screen options={headerOpt} name="Detail" component={DetailView} />
    </HomeStack.Navigator>
  );
}
const SettingStack = createNativeStackNavigator();
function SettingStackScreen(){
  return(
    <SettingStack.Navigator>
      <SettingStack.Screen name="Setting" component={SettingView} options={headerOpt}/>
    </SettingStack.Navigator>
  )
}
function renderBar(state,navigation){
  var array = [];
  let  iconName = '';
  let  title = '';
  const {routes,index} = state;
  let showTab = true; //是否显示底部 tab
  for(let i=0; i<routes.length; i++){
    const route = routes[i];
    const focused = state.index === i;
    if (route.name === 'HomeS') {
      iconName = focused
        ? require('../image/icon_home.png')
        : require('../image/icon_home_sel.png');
        title = "首页";
    } else if (route.name === 'SettingS') {
      iconName = focused ? require('../image/icon_tabbar_misc_selected.png') 
        : require('../image/icon_tabbar_misc.png');
      title = "设置";
    }
    const onPress = () => {
      const event = navigation.emit({
        type: 'tabPress',
        target: route.key,
        canPreventDefault: true,
      });
      if (!focused && !event.defaultPrevented) {
        navigation.navigate({ name: route.name, merge: true });
      }
    };
    
    if((route.state && route.state.routes.length >1) ){
      showTab = false;
    }
    array.push(<TouchableOpacity style={styles.barStyle} onPress={onPress} key={route.name}>
      <Image style={[styles.tabIcon,{width:20,height:20}]} source={iconName}/>
      <Text style={{color:focused?'#ED5100':'#aaa'}}>{title}</Text>
    </TouchableOpacity>)
  }
  return showTab?array:null;
}
function MyTabBar(props) {
  const { state, descriptors, navigation } = props;
  return (
    <View style={{ flexDirection: 'row',justifyContent:'space-around' }}>
      {renderBar(state,navigation)
      }
    </View>
  );
}
const Tab = createBottomTabNavigator();
export default function App() {
  return (
    <View style={{ flex: 1,}}>
        <StatusBar
          animated={false} //指定状态栏的变化是否应以动画形式呈现。目前支持这几种样式:backgroundColor, barStyle和hidden
          hidden={false}  //是否隐藏状态栏。
          networkActivityIndicatorVisible={false}//仅作用于ios。是否显示正在使用网络。
          showHideTransition={'fade'}//仅作用于ios。显示或隐藏状态栏时所使用的动画效果(’fade’, ‘slide’)。
          backgroundColor='rgba(255,255,255,0)'// {'transparent'} //状态栏的背景色
          translucent={true}//指定状态栏是否透明。设置为true时,应用会在状态栏之下绘制(即所谓“沉浸式”——被状态栏遮住一部分)。常和带有半透明背景色的状态栏搭配使用。
          barStyle={'light-content'} // enum('default', 'light-content', 'dark-content')
        />
      <NavigationContainer>
        <Tab.Navigator
          initialRouteName="Home"
          tabBar={props => <MyTabBar {...props} />}
          /** */
          screenOptions={({ route }) => ({
            tabBarActiveTintColor: '#ED5100',
            tabBarInactiveTintColor: '#aaa',
          })}>
          <Tab.Screen options={{headerShown:false}} name="HomeS" component={HomeStackScreen} />
          <Tab.Screen options={{headerShown:false}} name="SettingS" component={SettingStackScreen} />
        </Tab.Navigator>
      </NavigationContainer>
    </View>
  );
}
const styles = StyleSheet.create({
  barStyle:{
    height: 55,
    justifyContent:'center',
    alignItems:'center',
  },
  tabIcon:{
    width:24,
    height:24,
    resizeMode:'contain'
  },
});

3.3首页

首页非常简单,没什么好说的,代码如下

import React from 'react';
import {
  Text,
  View,
  Button,
} from 'react-native';
export default class Home extends React.Component {
  constructor(props){
    super(props);
  }
  onPress(){
    const {navigation} = this.props;
    if(navigation){
      navigation.push('Detail')
    }
  }
  render(){
		return(
			<View style={{backgroundColor:'#77ffee',flex:1,justifyContent:'center',alignItems:'center'}}>
        <Text>首页</Text>
        <Button onPress={()=>this.onPress()}
        title="点击进入详情页"></Button>
      </View>
    )
  }
}

3.4 详情页 

代码如下

import React from 'react';
import {
  Text,
  View,
} from 'react-native';
export default class Setting extends React.Component {
  constructor(props){
    super(props);
    props.navigation.setOptions({ title:'详情'});
  }
  render(){
		return(
			<View style={{backgroundColor:'#fff',flex:1,justifyContent:'center',alignItems:'center'}}>
        <Text>详情页</Text>
      </View>
    )
  }
}

3.5 设置页

设置页面右上角(顶部导航栏右边)加了一个小按钮,这里主要记录下导航栏按钮的使用方法。

代码如下

import React from 'react';
import {
  View,
  Image,
  TouchableOpacity,
  ToastAndroid,
} from 'react-native';
export default class Setting extends React.Component {
  constructor(props){
    super(props);
    props.navigation.setOptions({ title:'设置'});
    props.navigation.setOptions({ 
      headerRight:()=>
      <TouchableOpacity onPress={()=>this._add()}>
        <Image style={{width:20,height:20}} source={require('../../image/add.png')}/>
      </TouchableOpacity>
    })
  }
  _add=()=>{
    ToastAndroid.show("点击右上角",ToastAndroid.SHORT)
  }
  render(){
		return(
			<View style={{backgroundColor:'#fff',flex:1,}}>

      </View>
    )
  }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值