React Native自定义导航栏

之前我们学习了可触摸组件和页面导航的使用的使用:
从零学React Native之09可触摸组件

从零学React Native之03页面导航

经过之前的学习, 我们可以完成一个自定义导航栏了, 效果如下:

我们需要创建一个 NaviBar.js 用来显示顶部的导航栏, 还需要四个界面(Page1.js,Page2.js,Page3.js,Page4.js)。 当然还需要修改index.android.js或者index.ios.js 用来处理4个界面的切换。

导航栏NaviBar 实现

这里, 我们就假设应用有4个栏目, 每个按钮的宽高比为 4:3
直接贴代码了:

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    View,
    Text,
    TouchableHighlight,
} from 'react-native';

var Dimensions = require("Dimensions");
var totalWidth = Dimensions.get('window').width;// 屏幕宽度
let naviButtonWidth = totalWidth / 4;    //计算导航条每个宽度
let naviButtonHeight = naviButtonWidth * 0.75;   // 导航条每个高度
export  default class NaviBar extends Component {
    // 构造
    constructor(props) {
        super(props);
        this._tab0Pressed = this._tab0Pressed.bind(this);
        this._tab1Pressed = this._tab1Pressed.bind(this);
        this._tab2Pressed = this._tab2Pressed.bind(this);
        this._tab3Pressed = this._tab3Pressed.bind(this);
    }

    //四个按钮 被按下时处理函数
    _tab0Pressed() {
        this.props.onNaviBarPress(0);
    }

    _tab1Pressed() {
        this.props.onNaviBarPress(1);
    }

    _tab2Pressed() {
        this.props.onNaviBarPress(2);
    }

    _tab3Pressed() {
        this.props.onNaviBarPress(3);
    }

    render() {
        //通过属性得知哪个导航按钮是当前导航页, 这个导航用灰色背景
        //利用JavaScript数组的map函数,从一个数组对应生成另一个数组buttonColors
        // 看不懂该函数的,看下面的解释
        var buttonColors = this.props.naviBarStatus.map(function (aNumber) {
            if (aNumber == 0) return 'white';
            return 'gray';
        });
        return (
            //根View
            <View style={styles.naviRow}>
                <TouchableHighlight onPress={this._tab0Pressed}>
                    <View style={[styles.button,{backgroundColor:buttonColors[0]}]}>
                        <Text style={styles.textStyle1}>
                            条目一
                        </Text>
                    </View>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._tab1Pressed}>
                    <View style={[styles.button,{backgroundColor:buttonColors[1]}]}>
                        <Text style={styles.textStyle1}>
                            条目二
                        </Text>
                    </View>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._tab2Pressed}>
                    <View style={[styles.button,{backgroundColor:buttonColors[2]}]}>
                        <Text style={styles.textStyle1}>
                            条目三
                        </Text>
                    </View>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._tab3Pressed}>
                    <View style={[styles.button,{backgroundColor:buttonColors[3]}]}>
                        <Text style={styles.textStyle1}>
                            条目四
                        </Text>
                    </View>
                </TouchableHighlight>
            </View>
        );
    }
}
// 声明属性, 方便使用当前组件
NaviBar.propTypes = {
    naviBarStatus: React.PropTypes.arrayOf(React.PropTypes.number).isRequired,
    onNaviBarPress: React.PropTypes.func.isRequired
};

//样式
const styles = StyleSheet.create({
    naviRow: {
        flexDirection: 'row'
    },
    button: {
        width: naviButtonWidth,
        height: naviButtonHeight,
        justifyContent: 'center'
    },
    textStyle1: {
        fontSize: 20,
        textAlign: 'center'
    }
});

上面用到了, Map函数 ,
Map函数的作用是按照某种关系从原数组”映射”出新数组. 如下面求平方的例子:

var data= [1,2,3,4];
var newArray=data.map((item)=>{return item*item});
console.log(newArray);  //输出[1,4,9,16]

统一处理四个界面的切换

我们需要在index.android.js 或者index.ios.js 这个代码比较简单, 只需要导入四个界面, 用Navigator组件切换就可以了。

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Navigator
} from 'react-native';

import Page1 from './Page1';
import Page2 from './Page2';
import Page3 from './Page3';
import Page4 from './Page4';
class AwesomeProject extends Component {
    //告知Navigator 模块切换时的效果
    configureScene() {
        return Navigator.SceneConfigs.FadeAndroid;
    }
    //根据传递的信息, 处理界面的切换
    renderScene(router, navigator) {
        this._navigator = navigator;
        switch (router.name) {
            case 'Page1':
                return <Page1 navigator={navigator}/>;
            case 'Page2':
                return <Page2 navigator={navigator}/>;
            case 'Page3':
                return <Page3 navigator={navigator}/>;
            case 'Page4':
                return <Page4 navigator={navigator}/>;
        }
    }
    render() {
        return (
            //根View
            <Navigator
                initialRoute={{name:'Page1'}}
                configureScene={this.configureScene}
                renderScene={this.renderScene}/>
        );
    }
}
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

界面

上面的代码需要引入Page1 - Page4, 这个四个界面非常相似, 我们只贴其中一个了.
Page1.js

import React, { Component } from 'react';
import {
    View,
    StyleSheet,
} from 'react-native';
import NaviBar from './NaviBar';

export  default class Page1 extends Component {
    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.onNaviBarPress = this.onNaviBarPress.bind(this);
    }

    render() {
        // 不同的Page,需要修改下面的这个数组, 通过数组控制导航栏条目显示状态
        var naviStatus = [1, 0, 0, 0];
        return (
            <View style={styles.container}>
                <NaviBar naviBarStatus={naviStatus}
                         onNaviBarPress={this.onNaviBarPress}/>
                <View style={styles.whatLeft}/>
            </View>
        );
    }
    //不同的page需要修改返回值
    onNaviBarPress(aNumber) {
        switch (aNumber) {
            case 0:
                return;
            case 1:
                //通过replace切换
                this.props.navigator.replace({
                    name: 'Page2'
                });
                return;
            case 2:
                this.props.navigator.replace({
                    name: 'Page3'
                });
                return;
            case 3:
                this.props.navigator.replace({
                    name: 'Page4'
                });
                return;
        }
    }
}
const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    whatLeft: {  // 组件定义了一个上边框
        flex: 1,
        borderTopWidth: 1,
        borderColor: 'black',
        backgroundColor:'red' //每个界面背景颜色不一样
    }
});

顺便指出两点: 当根View没有指定背景色时, 默认值是一种灰色; 当子View没有指定背景色时,会继承父View的背景色。

更多精彩请关注微信公众账号likeDev,公众账号名称:爱上Android。

时间: 2024-10-25 09:16:49

React Native自定义导航栏的相关文章

ios-iOS隐藏系统导航栏用自定义导航栏

问题描述 iOS隐藏系统导航栏用自定义导航栏 前提:1.navigationBarHidden = YES; 2.不要在每个ViewController中addSubView一次,继承父类的方法也不行. 就是想做一个绝对灵活的导航栏,高度不是44,样式也不是只有左右中三个部分.我听一个大神说这是iOS常识,让我查百度,可是我真的查不到,求助啊. 解决方案 iOS系统导航栏的自定义化 解决方案二: 给一个你想要视图作为导航栏不就行了? 解决方案三: 你自定义一个导航栏 隐藏系统的 再添加到UINa

ios开发碰到自定义导航栏leftBarButtonItems导致滑动返回失效问题解决方法

通常使用导航控制器 navigationController 跳转到另一页面时,除了可以点击左上角的返回按钮,还可以通过在屏幕左侧向右滑动来返回到上一层.但如果自定义了 self.navigationItem.leftBarButtonItems 后会发现,滑动返回(swipe back)失效了. (如何自定义导航栏左侧按钮可以看这篇文章:Swift - 修改导航栏"返回"按钮文字,图标) 开发碰到自定义导航栏leftBarButtonItems导致滑动返回失效问题解决方法-leftb

分别用ToolBar和自定义导航栏实现沉浸式状态栏

一.ToolBar 1.在build.gradle中添加依赖,例如: compile 'com.android.support:appcompat-v7:23.4.0' 2.去掉应用的ActionBar.可以是修改主题theme为"NoActionBar",例如: <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> 或者不修改主题为"NoAct

百度应用 android客户端(一)自定义导航栏

title布局activity_main_title.xml     <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height=

如何在React Native中写一个自定义模块

前言 在 React Native 项目中可以看到 node_modules 文件夹,这是存放 node 模块的地方,Node.js 的包管理器 npm 是全球最大的开源库生态系统.提到npm,一般指两层含义:一是 Node.js 开放式模块登记和管理系统,另一种是 Node.js 默认的模块管理器,是一个命令行软件,用来安装和管理 node 模块.本文旨在探讨如何在 React Native 中写一个自定义的 npm 模块(类似于插件),并上传到 npm 上供他人使用. npm 使用介绍 np

Android自定义View实现字母导航栏的代码_Android

思路分析: 1.自定义View实现字母导航栏 2.ListView实现联系人列表 3.字母导航栏滑动事件处理 4.字母导航栏与中间字母的联动 5.字母导航栏与ListView的联动 效果图: 首先,我们先甩出主布局文件,方便后面代码的说明 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/re

Android自定义View实现字母导航栏_Android

很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章. 思路分析: 1.自定义View实现字母导航栏 2.ListView实现联系人列表 3.字母导航栏滑动事件处理 4.字母导航栏与中间字母的联动 5.字母导航栏与ListView的联动 效果图: 首先,我们先甩出主布局文件,方便后面代码的说明 <!--?xml version="1.0" encoding=&qu

如何在 React Native 中写一个自定义模块

前言 在 React Native 项目中可以看到 node_modules 文件夹,这是存放 node 模块的地方,Node.js 的包管理器 npm 是全球最大的开源库生态系统.提到npm,一般指两层含义:一是 Node.js 开放式模块登记和管理系统,另一种是 Node.js 默认的模块管理器,是一个命令行软件,用来安装和管理 node 模块.本文旨在探讨如何在 React Native 中写一个自定义的 npm 模块(类似于插件),并上传到 npm 上供他人使用. npm 使用介绍 np

【REACT NATIVE 跨平台应用开发】环境搭建问题记录&amp;&amp;XCODE7模拟器上COMMAND+R失效的几种替换方法

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2147.html React Native 这里不多介绍,其实就是个跨平台开发原生应用的开源引擎. 更详细的介绍,大家可以搜索"facebook react native" 或 "taobao react native" 附上 React Native 官方网站:http://react