一、项目说明
本项目为模仿美团的项目,采用的是网上提供的API接口。导航采用
公司推荐的react-navigation,滚动条采用第三方组件react-native-scroll-tab-view。RN环境为0.50。
(先声明!!是在网上某位大神的博客上学习哒。自己做了改进!)
原github地址:https://github.com/huanxsd/MeiTuan
样式图如下:
二、项目管理
采用WebStorm的git功能来管理项目
1)在WebStorm中,选中菜单栏中的VCS,点击Enable Version Control Integration选项。
2)在弹出的弹窗中选择Git
3)接着会看见WebStrom底部弹出Version Control一栏,并且所有未加入到git的文件都已标红。此时,右击Unversion,选择Add to VCS,将文件添加到VCS中。
4)在WebStrom的右上角做提交和下载的操作
三、框架搭建
1)添加必要依赖
在命令行输入以下代码
yarn add react-navigation
yarn add react-native-scrollable-tab-view
当然,以上代码可以用npm代替
打开package.json文件,会发现这两个组件已经添加到项目当中。
2)添加项目需要的图片并建立分类建立文件夹和初始文件。
建立src文件夹
- 复制图片文件夹
- 建立scene文件夹,用于创建各类页面的文件夹及页面
- 建立widget文件夹,用于封装一下小的组件,比如说文字、颜色、标签栏等信息
- 建立common文件夹,用来处理各个文件共同的样式、请求数据等功能
- 建立初始文件RootScene
-
建立api文件,这里存储的是需要请求数据的接口。直接提供出来。
按照上述思维导图,将文件夹和文件建立好。并将新建的文件添加到VCS中
3)设置各个主页面也就是HomeScene、MineScene、NearbyScene、OrderScene的初始状态。以HomeScene为例,粘贴一段代码。其他页面以此类推
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
export default class HomeScene extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to HomeScene!
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'green',
}
});
- 将初始页面App.js指向RootScene
import React, { Component } from 'react';
import {Platform, StyleSheet, Text, View
} from 'react-native';
import RootScene from './src/RootScene'
export default class App extends Component {
render() {
return (
<RootScene />
);
}
}
5)在RootScene页面中搭建导航,实现Tab标签栏框架
- 引入实现导航的组件
要想让react-naviation组件发挥作用必定要引入它的子组件。StackNavigator组件用于设置导航,而TabNavigator则是用作设置标签栏,TabBarBottom用于设置标签栏的位置。
import { StackNavigator, TabNavigator, TabBarBottom } from 'react-navigation';
- 封装标签栏的item组件。
在widget文件夹中建立一个TabBarItem.js文件,这个小组件是为了对标签栏要显示的图做一些处理。
import React, {Component } from 'react'
import { Image } from 'react-native'
export default class TabBarItem extends Component {
render(){
// 设置当item选中时要展示的图片,如果图片库中有被选中的图片,则用选中的图片,否则可以把普通图片赋值给它
let selectedImage = this.props.selectedImage?this.props.selectedImage:this.props.normalImage
return (
<Image
source={this.props.focused? selectedImage:this.props.normalImage}
style={{tintColor:this.props.tintColor,width:25,height:25}}
/>
)
}
}
- 建立color组件
上文中提到,为了方便,项目中会创建出一些微小的组件。在widget中建立color.js文件。color是为了给项目设置主题颜色,边框颜色和背景颜色的
export default {
theme: '#06C1AE',
border: '#e0e0e0',
background: '#f3f3f3'
}
- 引入需要的文件
在RootScene文件中,引入四个主界面和封装好的TabBarItem组件以及React框架必须的组件
import React, { Component } from 'react'
import HomeScene from './scene/Home/HomeScene'
import OrderScene from './scene/Order/OrderScene'
import NearbyScene from './scene/Nearby/NearbyScene'
import MineScene from './scene/Mine/MineScene'
- 创建标签栏
在react-navigation这个组件中,标签栏是由TabNavigator组件创建的,将要加入到标签栏中的页面添加并设置标题、样式、图标等属性即可。这里只以Home为例。其他参考源码。
//创建标签栏
const Tab = TabNavigator(
{
//设置标签栏四个页面
Home: {
screen: HomeScene,
navigationOptions: ({ navigation }) => ({
tabBarLabel: '团购',
//设置标签栏的图标,需要给每一项都设置
tabBarIcon: ({ focused, tintColor }) => (
//自定义封装的Item
<TabBarItem
tintColor={tintColor}
focused={focused}
normalImage={require('./img/tabbar/pfb_tabbar_homepage.png')}
selectedImage={require('./img/tabbar/pfb_tabbar_homepage_selected.png')}
/>
)
}),
},
}
);
当然,在最后也要设置标签栏的通用属性,比如说整个标签栏的位置,是否懒加载,是否有动画,样式等。
{
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
swipeEnabled: true,
animationEnabled: true,
lazy: true,
tabBarOptions: {
activeTintColor: color.theme,
inactiveTintColor: '#979797',
style: { backgroundColor: '#ffffff' },
},
- 创建导航
导航和标签栏的创建方法相似,在StackNavigator里面加入要显示的页面即可。因为四个主页面都添加在Tab标签栏当中,所以只要将Tab加入到导航作为显示页面。
const Navigator = StackNavigator(
{
Tab: { screen: Tab }, //框架的页面
},
//设置用于适配StackNavigator的属性
{
navigationOptions: {
headerBackTitle: null,
headerTintColor: '#333333',
showIcon: true,
},
}
);
- 在render方法中返回导航
export default class RootScene extends Component {
render() {
return(
<Navigator/>
)
}
}
效果图如下:
四、状态栏的设置
从原型图上可以看出,只有当页面跳转在’首页‘和’我的‘两个页面时,状态栏的样式是亮色,其余时候都呈现了黑色。
- 要设置状态栏必须先导入StateBar组件
import { StatusBar } from 'react-native'
- 构造函数中,先将所有页面状态栏的状态都设置为亮色。
constructor() {
super()
StatusBar.setBarStyle('light-content')
}
- 定义一个常量,设置’首页‘和’我的‘两个页面为亮色
// 设置home和mine为的状态栏为亮色
const lightContentScenes = ['Home', 'Mine']
那么要如何确定界面展示的就是这两个页面的信息呢?这里就不得不用到路由。
- 设定一个方法,用于获取每个界面的路由。如何通过路由来设置页面状态栏的状态。
//得到路由的名称
function getCurrentRouteName(navigationState) {
if (!navigationState) {
return null;
}
const route = navigationState.routes[navigationState.index];
// dive into nested navigators
if (route.routes) {
return getCurrentRouteName(route);
}
return route.routeName;
}
导航Navigator中有一个方法叫onNavigationStateChange,常用来追踪screen的变化。组件会给该方法传入目前的界面场景与先前的场景。
- 用变量接受当前场景和上一个场景的路由,如果上一个场景不是当前场景,就是更换过一个场景。并且当前场景在亮色状态的数组中,就改为白色,否则改为黑色。
<Navigator
//用onNavigationStateChange来追踪screen的变化
onNavigationStateChange={
//可以传props也可以不传
// 传入两个参数 目前的场景和前一个场景
(prevState, currentState) => {
const currentScene = getCurrentRouteName(currentState);
const previousScene = getCurrentRouteName(prevState);
//若两个场景不相等
if (previousScene !== currentScene) {
//并且目前的场景包含在数组里面
if (lightContentScenes.indexOf(currentScene) >= 0) {
// 设置为白色
StatusBar.setBarStyle('light-content')
} else {
// 否则设置为暗色
StatusBar.setBarStyle('dark-content')
}
}
}
}
/>
效果图如下:
网友评论