React Native学习之自定义NavigationBar

之前学习React Native的时候,版本还是0.20,问题一大堆,Navigation这个问题更是很多,首先,是NavigationBar的问题,NavigationIOS有NavigationBar,Navigation却需要自定义一个,最后,我想了想,还是自定义一个view,岂不更好,现在新公司不用RN,我正好有点时间,就把自定义的NavigationBar分享给大家。好了少废话,上代码;

// NavigationBar 导航条的自定义封装
// create by 小广
'use strict';
import React, { Component,PropTypes } from 'react';
import {
  Image,
  Text,
  View,
  Platform,
  TouchableOpacity,
} from 'react-native';

import styles from './NavigationBarStyle'

// 导航条和状态栏的高度
const STATUS_BAR_HEIGHT = 20
const NAV_BAR_HEIGHT = 44

export default class NavigationBar extends Component {
  static defaultProps = {
    title: 'title',
    titleTextColor: '#383838',
    titleViewFunc () {},
    barBGColor: '#f8f8f8',
    barOpacity: 1,
    barStyle: 0,
    barBorderBottomColor: '#D4D4D4',
    barBorderBottomWidth: 0.8,
    statusbarShow: true,
    leftItemTitle: '',
    leftTextColor: '#383838',
    leftItemFunc () {},
    rightItemTitle: '',
    rightTextColor: '#383838',
    rightItemFunc () {},
    //leftImageSource: require('./nav_back.png'),
  };
  static propTypes = {
    title: PropTypes.string,          // nav标题
    titleTextColor: PropTypes.string, // nav标题颜色
    titleView: PropTypes.node,        // nav自定义标题View(节点)
    titleViewFunc: PropTypes.func,    // nav的titleView点击事件
    barBGColor: PropTypes.string, // Bar的背景颜色
    barOpacity: PropTypes.number, // Bar的透明度
    barStyle: PropTypes.number,   // Bar的扩展属性,nav样式(暂未使用)
    barBorderBottomColor: PropTypes.string,  // Bar底部线的颜色
    barBorderBottomWidth: PropTypes.number,  // Bar底部线的宽度
    statusbarShow: PropTypes.bool,     // 是否显示状态栏的20高度(默认true)
    leftItemTitle: PropTypes.string,   // 左按钮title
    leftImageSource: PropTypes.node,   // 左Item图片(source)
    leftTextColor: PropTypes.string,   // 左按钮标题颜色
    leftItemFunc: PropTypes.func,      // 左Item事件
    rightItemTitle: PropTypes.string,  // 右按钮title
    rightImageSource: PropTypes.node,  // 右Item图片(source)
    rightTextColor: PropTypes.string,  // 右按钮标题颜色
    rightItemFunc: PropTypes.func,     // 右Item事件
  };

  render() {
    // 判断左Item的类型
    var onlyLeftIcon = false; // 是否只是图片
    if (this.props.leftItemTitle && this.props.leftImageSource) {
        onlyLeftIcon = true;
    } else if (this.props.leftImageSource) {
      onlyLeftIcon = true;
    }

    // 左侧图片title都没有的情况下
    var noneLeft = false;
    if (!(this.props.leftItemTitle.length > 0) && !(this.props.leftImageSource)) {
      noneLeft = true;
    }

    // 判断是否自定义titleView
    var hasTitleView = false;
    if (this.props.title && this.props.titleView) {
        hasTitleView = true;
    } else if (this.props.titleView) {
      hasTitleView = true;
    }

    // 判断右Item的类型
    var onlyRightIcon = false; // 是否只是图片
    if (this.props.rightItemTitle && this.props.rightImageSource) {
        onlyRightIcon = true;
    } else if (this.props.rightImageSource) {
      onlyRightIcon = true;
    }

    // 右侧图片title都没有的情况下
    var noneRight = false;
    if (!(this.props.rightItemTitle.length > 0) && !(this.props.rightImageSource)) {
      noneRight = true;
    }

    // 判断是否显示20状态栏高度
    let showStatusbar = this.props.statusbarShow;
    if (Platform.OS === 'android') {
      // 安卓不显示
      showStatusbar = false;
    }
    return (
      <View style={styles.nav_barView}>
        <View style={[styles.nav_bar,
          {
            backgroundColor: this.props.barBGColor,
            height: showStatusbar ? NAV_BAR_HEIGHT + STATUS_BAR_HEIGHT : NAV_BAR_HEIGHT,
            opacity: this.props.barOpacity
          },
          showStatusbar ? { paddingTop: STATUS_BAR_HEIGHT } : {}, this.props.barStyle]}>
          <View style={styles.nav_ItemView}>
            { // 左侧item
              !noneLeft
              ? <TouchableOpacity
                 style={styles.nav_leftItem}
                 onPress={this.props.leftItemFunc}>
                 { // 左侧是图片还是文字
                   onlyLeftIcon
                   ? <Image style={styles.nav_leftImage}
                              source={this.props.leftImageSource}/>
                   : <Text style={[styles.nav_leftTitle,{color: this.props.leftTextColor}]}>
                       {this.props.leftItemTitle}
                     </Text>
                 }
               </TouchableOpacity>
              : null
            }
          </View>
          {
            hasTitleView
            ? <TouchableOpacity style={styles.nav_titleView} onPress={this.props.titleViewFunc}>
                {this.props.titleView}
              </TouchableOpacity>
            : <View style={styles.nav_titleView}>
                <Text style={[styles.nav_title,{color:this.props.titleTextColor}]}>
                 {this.props.title}
                </Text>
              </View>
          }
          <View style={styles.nav_ItemView}>
            { // 右侧item
              !noneRight
              ? <TouchableOpacity
                 style={styles.nav_rightItem}
                 onPress={this.props.rightItemFunc}>
                 { // 右侧是图片还是文字
                   onlyRightIcon
                   ? <Image style={styles.nav_rightImage}
                              source={this.props.rightImageSource}/>
                   : <Text style={[styles.nav_rightTitle,{color: this.props.rightTextColor}]}>
                      {this.props.rightItemTitle}
                     </Text>
                 }
              </TouchableOpacity>
              : null
            }
          </View>
        </View>
        <View style={{height:this.props.barBorderBottomWidth,backgroundColor:this.props.barBorderBottomColor}}></View>
      </View>

    );
  }
}

css样式:

// NavigationBarStyle 导航条的样式
// create by 小广
'use strict';
import {
  StyleSheet,
} from 'react-native';

export default  StyleSheet.create({
  // navBar
  nav_barView:{
    justifyContent: 'center',
  },
  nav_bar: {
    //flex:1,
    flex: 1,
    flexDirection:'row',
    justifyContent: 'center',
  },

  // 标题纯title
  nav_title: {
    fontSize:17,
  },

  // titleView
  nav_titleView: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },

  nav_ItemView:{
    width:80,
    justifyContent: 'center',
  },

  // 左Item
  nav_leftItem: {
    marginLeft:8,
    flex:1,
    justifyContent: 'center',
    alignSelf: 'flex-start',
    //backgroundColor:'#f00',
  },

  // 左Item为title
   nav_leftTitle: {
     marginRight:5,
      marginLeft:5,
      fontSize: 14,
   },

   // 左图片
   nav_leftImage: {
     margin:10,
     resizeMode:'contain',
   },

   // 右Item
   nav_rightItem: {
      marginRight:8,
      flex:1,
      justifyContent: 'center',
      alignSelf: 'flex-end',
      //backgroundColor:'#3393F2',
   },

   // 右Item为title
    nav_rightTitle: {
      marginRight:5,
      marginLeft:5,
      fontSize: 14,
    },

    // 右图片
    nav_rightImage:{
      margin:10,
      resizeMode:'contain',
      //backgroundColor:'#f00',
    },
    //resizeMode:'contain',
});

用法:引入之后

import NavigationBar from '你的存放路径/NavigationBar.js'

class XGRNDemo extends Component {

  _leftItemAction() {
    console.log('左侧按钮点击了');
  }

  _rightItemAction() {
    console.log('右侧按钮点击了');
  }

  render() {
    return (
      <View style={styles.container}>
        <NavigationBar
            title='这个是标题'
            leftImageSource={require('./nav_back.png')}
            rightItemTitle='按钮'
            rightTextColor='#3393F2'
            leftItemFunc={this._leftItemAction.bind(this)}
            rightItemFunc={this._rightItemAction.bind(this)}/>
        <ScrollView style={styles.container}
          automaticallyAdjustContentInsets={false}
          keyboardShouldPersistTaps={true}
          keyboardDismissMode='on-drag'
          >
          <Text style={styles.welcome}>
            Welcome to React Native!
          </Text>
          <Text style={styles.instructions}>
            To get started, edit index.ios.js
          </Text>
          <Text style={styles.instructions}>
            Press Cmd+R to reload,{'\n'}
            Cmd+D or shake for dev menu
          </Text>
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

其中可以自定义的属性

    title: PropTypes.string,          // nav标题
    titleTextColor: PropTypes.string, // nav标题颜色
    titleView: PropTypes.node,        // nav自定义标题View(节点)
    titleViewFunc: PropTypes.func,    // nav的titleView点击事件
    barBGColor: PropTypes.string, // Bar的背景颜色
    barOpacity: PropTypes.number, // Bar的透明度
    barStyle: PropTypes.number,   // Bar的扩展属性,nav样式(暂未使用)
    barBorderBottomColor: PropTypes.string,  // Bar底部线的颜色
    barBorderBottomWidth: PropTypes.number,  // Bar底部线的宽度
    statusbarShow: PropTypes.bool,     // 是否显示状态栏的20高度(默认true)
    leftItemTitle: PropTypes.string,   // 左按钮title
    leftImageSource: PropTypes.node,   // 左Item图片(source)
    leftTextColor: PropTypes.string,   // 左按钮标题颜色
    leftItemFunc: PropTypes.func,      // 左Item事件
    rightItemTitle: PropTypes.string,  // 右按钮title
    rightImageSource: PropTypes.node,  // 右Item图片(source)
    rightTextColor: PropTypes.string,  // 右按钮标题颜色
    rightItemFunc: PropTypes.func,     // 右Item事件


效果如图:

ps:之前想上传到npm服务器,但是自己没搞成功,就这了吧..

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值