React Native技术精讲与高质量上线APP开发------1.3 自定义NavigationBar

1.3 自定义NavigationBar


Github地址: https://github.com/lenvo222/imooc_gp/tree/f646f658f5c2d263f45105181177ef726c3f437a

一 介绍NavigationBar

1. 什么是NavigationBar?

手机导航栏

2. 自定义NavigationBar如何实现?

3. NavigationBar基本组成

  1. RN中主要用于自定义组件属性的类型限定,或者叫做属性确认,当外部传入非法的属性类型,会有警告(不是IDE,而是控制台)。
  2. 网上说使用PropTypes定义的属性,会有提示。(然而我试了Atom & WebStorm,IDE并没有提示)

React v15.5,PropTypes被从react库中拿了出来,单独放在了一个名为prop-types的库中.

  • React v15.5之前,PropTypes属于react库.

    $ import { PropTypes } from ‘react’;

  • React v15.5开始,react库移除了PropTypes,转而使用prop-types库替代.

    $ import PropTypes from ‘prop-types’;

使用方式
React v15.5`之前

static propTypes = {
        autoPlay: React.PropTypes.bool.isRequired,
        maxLoops: React.PropTypes.number.isRequired,
};  // 注意这里有分号

React v15.5开始

static propTypes = {
        autoPlay: PropTypes.bool.isRequired,
        maxLoops: PropTypes.number.isRequired,
};  // 注意这里有分号

Others

PropTypes从react库移除之后,会导致老项目报错(属性找不到).
RN的版本更新很快,目前已经是0.51.0,随着React Native的升级,系统废弃了很多的东西,过去我们可以直接使用 React.PropTypes来进行属性确认,不过这个自React v15.5起就被移除了,转而使用prop-types库来进行替换.

为了保证RN代码高效运行,属性确认仅在开发环境中有效,正式发布的 App 运行时是不会进行检查的.

二 实例代码

Boy.js

import React, {Component} from 'react';
import {View, Text,StyleSheet} from 'react-native';
import Girl from './Girl';
import NavigationBar from './NavigationBar';
export default class Boy extends Component {
  constructor(props) {
    super(props);
    this.state = {
      what:''
    };
  }

  render() {
    let what = this.state.what===''?'':'我收到了女孩回赠的:' + this.state.what;
    return (
      <View style={styles.container}>
        <NavigationBar
          title='Boy'
          style = {{
            backgroundColor:'red',
          }}
        />
        <Text style={styles.tips}>I am boy</Text>
        <Text style={styles.tips}
          onPress={()=>{
            this.props.navigator.push({
              component:Girl,
              params:{
                what: '一支玫瑰',
                onCallBack:(what) => {
                  this.setState({
                    what:what ,
                  });
                }
              }
            })
          }}
        >送女孩一支玫瑰</Text>
        <Text style={styles.text}>{this.state.word}</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'gray',
  },
  tips: {
    fontSize: 29,
  }
});

NavigationBar.js

import React, {Component } from 'react';
import PropTypes from 'prop-types';
import {View, Text, StyleSheet, Image, Platform,StatusBar} from 'react-native';

const NAV_BAR_HEIGHT_ANDROID = 50;
const NAV_BAR_HEIGHT_IOS = 44;
const STATUS_BAR_HEIGHT = 20;
const StatusBarShape = {
  backgroundColor:PropTypes.string,
  barStyle:PropTypes.oneOf(['default','light-content', 'dark-content']),
  hidden:PropTypes.bool
}
export default class NavigationBar extends Component {
  static propTypes = { // 指定属性的约束
    style:PropTypes.style,
    title:PropTypes.string,
    titleView:PropTypes.element,  // 设置 titileView 为元素
    hide:PropTypes.bool,// 设置鼠标隐藏
    leftButton:PropTypes.element, // 左右侧按钮
    rightButton:PropTypes.element,
    statusBar: PropTypes.shape(StatusBarShape) // 允许用户指定状态栏,约束形状
  }

  static defaultProps = {
    statusBar:{
      barStyle:'light-content',
      hidden:false
    }
  }
  constructor(props) {
    super(props);
    this.state = {
      title:'',
      hide:false
    };
  }

  render() {
    let status = <View style={[styles.statusBar,this.props.statusBar]}>
      <StatusBar {...this.props.statusBar}/>
    </View>
    let titleView = this.props.titleView?this.props.titleView:
      <Text style={styles.title}>{this.props.title}</Text>
    let content = <View style={styles.navBar}>
      {this.props.leftButton}
      <View style={styles.titleViewContainer}>
        {titleView}
      </View>
      {this.props.rightButton}
    </View>
    return (
      <View style={[styles.container, this.props.style]}>
        {status}
       {content}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: 'gray',
  },
  navBar:{
    justifyContent:'space-between',// 两侧空格
    alignItems:'center', // 文字居中显示
    height:Platform.OS ==='ios' ?NAV_BAR_HEIGHT_IOS :NAV_BAR_HEIGHT_ANDROID,// 指定高度
    // backgroundColor: 'red',
    flexDirection:'row'// 文字显示在一排
  },
  titleViewContainer:{
    justifyContent:'center',
    alignItems:'center',
    position:'absolute',
    left:40,
    right:40,
    top:0,
    bottom:0
  },
  title:{
    fontSize:20,
    color:'white'
  },
  statusBar:{
    height:Platform.OS ==='ios' ?STATUS_BAR_HEIGHT :0,// 指定高度
  }
});

Girl.js

TouchableOpacity 包裹 前进/后退箭头的组件

import React, {Component} from 'react';
import {View, Text, Image, StyleSheet,TouchableOpacity} from 'react-native';
import NavigationBar from './NavigationBar';

export default class Girl extends Component {
  // 封装左右侧代码
  renderButton(image){
    return <TouchableOpacity
      onPress={()=>{
        this.props.navigator.pop() // 点击按钮时关闭当前窗口
      }}
    >
      <Image style={{width:22,height:22,margin:5}} source={image}></Image>
    </TouchableOpacity>
  }


  render() {
    return (
      <View style={styles.container}>
        <NavigationBar
          title='Girl'
          style = {{
            backgroundColor:'#EE6363',
          }}
          leftButton={
            this.renderButton(require('./res/images/ic_arrow_back_white_36pt.png'))
          }

          rightButton={
            this.renderButton(require('./res/images/ic_star.png'))
          }
        />
        <Text style={styles.text}>I am girl</Text>
        <Text style={styles.text}>我收到了男孩送的:{this.props.what}</Text>
        <Text style={styles.text}
              onPress={()=>{
                this.props.onCallBack('一盒巧克力')
                this.props.navigator.pop()
              }}
        >回赠巧克力</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
    // justifyContent:'center'
  },
  text: {
    fontSize: 22,
  }
});

总结

如何自定义NavigationBar?

  1. 创建js文件(组件): 放NavigationBar

  2. 设置属性的默认属性 , propTypes

  3. 渲染组件的结构

     render() {
        let status = <View style={[styles.statusBar,this.props.statusBar]}>
          <StatusBar {...this.props.statusBar}/>
        </View>
        let titleView = this.props.titleView?this.props.titleView:
          <Text style={styles.title}>{this.props.title}</Text>
        let content = <View style={styles.navBar}>
          {this.props.leftButton}
          <View style={styles.titleViewContainer}>
            {titleView}
          </View>
          {this.props.rightButton}
        </View>
        return (
          <View style={[styles.container, this.props.style]}>
            {status}
           {content}
          </View>
        );
      }
    }
    
  4. 安卓IOS,指定高度

    height:Platform.OS ==='ios' ?STATUS_BAR_HEIGHT :0,// 指定高度
    
  5. 对组件整体的把控, 以及将来总体上的应用都有一定要求,如果感觉比较难,请学过几章后回头看看.?

  6. 对函数的封装,节省了代码,使结构清晰

    1. return,使用
    2. 将图片作为参数传入

    精彩!

    leftButton={
    	this.renderButton(require('./res/images/ic_arrow_back_white_36pt.png'))
    }
    
    rightButton={
        this.renderButton(require('./res/images/ic_star.png'))
    }
    
    // 封装左右侧代码 
    renderButton(image){
        return <TouchableOpacity
          onPress={()=>{
            this.props.navigator.pop() // 点击按钮时关闭当前窗口
          }}
        >
          <Image style={{width:22,height:22,margin:5}} source={image}></Image>
        </TouchableOpacity>
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值