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

1.3 自定义NavigationBar

文章目录

  • 1.3 自定义NavigationBar
    • 一 介绍NavigationBar
      • 1. 什么是NavigationBar?
      • 2. 自定义NavigationBar如何实现?
      • 3. NavigationBar基本组成
      • Others
    • 二 实例代码
      • **Boy.js**
      • **NavigationBar.js**
      • **Girl.js**
    • 总结

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 = 
          
        
        let titleView = this.props.titleView?this.props.titleView:
          {this.props.title}
        let content = 
          {this.props.leftButton}
          
            {titleView}
          
          {this.props.rightButton}
        
        return (
          
            {status}
           {content}
          
        );
      }
    }
    
  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>
    }
    

你可能感兴趣的:(React)