ReactNative 自定义标题栏 ReactNative 自定义导航栏

先上代码,配合代码讲解一下使用方法,
我这有用到一个屏幕适配工具类,自己写的,使用方法和代码 请点这里

/**
 * Created by 卓原 on 2018/6/16.
 *
 */

import React from 'react';
import {
    Text,
    StyleSheet,
    View,
    TouchableOpacity,
    Image,
    Platform,
    StatusBar
} from 'react-native';

//如果不用react-navigation可不要
import {withNavigation} from 'react-navigation';
//ScreenUtil 为屏幕尺寸适配的工具类
import * as ScreenUtil from "../utils/ScreenUtil";
import PropTypes from 'prop-types';
//这个是我用来切换主题颜色的
//import {connect} from 'react-redux';

const NAV_BAR_HEIGHT_ANDROID = 50;
const NAV_BAR_HEIGHT_IOS = 44;

const StatusBarShape = {
    barStyle: PropTypes.oneOf(['light-content', 'default', 'dark-content']),
    hidden: PropTypes.bool,
    backgroundColor: PropTypes.string,
};

class NavigationBar extends React.Component {

    static propTypes = {
        style: View.propTypes.style,
        title: PropTypes.string,
        titleView: PropTypes.element,
        hide: PropTypes.bool,
        leftButton: PropTypes.element,
        rightButton: PropTypes.element,
        statusBar: PropTypes.shape(StatusBarShape),
        titleLayoutStyle: View.propTypes.style,
        leftTextStyle: View.propTypes.style,
        leftButton: PropTypes.element,
        leftTextStyle: View.propTypes.style,
        showLeft: PropTypes.bool,
        rightButton: PropTypes.element,
        rightTextStyle: View.propTypes.style,
        showRight: PropTypes.bool
    };

    static defaultProps = {
        statusBar: {
            barStyle: 'default',
            hidden: false,
        },
        showLeft: true,
        showRight: false,
    };

    constructor(props) {
        super(props);
        this.state = {
            title: '',
            hide: false,

        }
    }

    render() {
        // let {color} = this.props;
        let leftButton = this._renderLeft();
        let rightButton = this._renderRight();
        let statusBar = <View>
            <StatusBar {...this.props.statusBar}/></View>;
        let titleView = this.props.titleView ? this.props.titleView :
            <Text style={[styles.titleStyle, this.props.titleLayoutStyle]}>{this.props.title}</Text>;
        let content = <View style={styles.content}>
            {leftButton}
            <View style={styles.titleView}>{titleView}</View>
            {rightButton}
        </View>;
        return (
            //这里有一个{backgroundColor: color} 这个背景色可以写在styles.container样式中,颜色自己定义
            <View style={[styles.container,
                //{backgroundColor: color},
                this.props.style]}>
                {statusBar}
                {content}
            </View>
        )
    }

    _renderLeft() {
        let {leftButton, leftTextStyle, showLeft, navigation, onLeftClick} = this.props;
        if (!showLeft) {
            return null;
        }
        if (leftButton == null) {
            return (
                <TouchableOpacity onPress={() => {
                    if (onLeftClick) {
                        onLeftClick();
                    } else {
                        this.props.navigation.goBack()
                    }
                }}>
                    <View style={styles.leftContainer}>
                        <Text style={[styles.leftText, leftTextStyle]}>返回</Text>
                    </View>
                </TouchableOpacity>)
        }
        return leftButton;
    }

    _renderRight() {
        let {rightButton, rightTextStyle, showRight, onRightClick} = this.props;
        if (!showRight) {
            return null;
        }
        if (rightButton == null) {
            return (
                <TouchableOpacity onPress={() => {
                    if (onRightClick) {
                        onRightClick()
                    }
                }}>
                    <View>
                        <Text style={[styles.rightText, rightTextStyle]}>更多</Text>
                    </View>
                </TouchableOpacity>)
        }
        return rightButton;
    }
}

/**
 * //selector:这是你自己编写的一个函数。这个函数声明了你的组件需要整个 store 中的哪一部分数据作为自己的 props
 * 如果用不到redux这个方法可以删除
 * @param store
 * @returns {{color: *}}
 */
function changeColor(store) {
    return {
        color: store.changeColorReducer.color
    }
}


const styles = StyleSheet.create({
    container: {
        backgroundColor: 'green'
    },
    content: {
        justifyContent: 'space-between',
        flexDirection: 'row',
        alignItems: 'center',
        height: Platform.OS === 'ios' ? NAV_BAR_HEIGHT_IOS : NAV_BAR_HEIGHT_ANDROID,
    },
    titleView: {
        justifyContent: 'center',
        alignItems: 'center',
        position: 'absolute',
        left: 40,
        right: 40,
        top: 0,
        bottom: 0,
    },
    titleStyle: {
        fontSize: ScreenUtil.setSpText(28),
        color: 'white'

    },
    leftText: {
        color: 'white'
    },
    rightText: {
        color: 'white'
    },
    leftContainer: {
        marginLeft: ScreenUtil.scaleSize(20)
    }
});

// 包装 component ,注入 dispatch 和 state 到其默认的 connect(selector)(App) 中;
/**
 * 把这个组件用connect包裹住就能拿到store。
 注意export default已经拿到下面来了,上面的class前面的导出要删掉
 用redux的话需要第一种方法导出,已注释掉
 */
//export default connect(changeColor)(withNavigation(NavigationBar));
//用不到redux推荐在定义类的时候直接导出,类定义为 export default class ...
//withNavigation是一个更高阶的组件,它将导航道具传递给一个包装组件。
//当您无法直接将导航道具传递到组件时,或者在深度嵌套子节点的情况下不希望传递导航道具时,它非常有用。
export default withNavigation(NavigationBar);

在页面使用:

    render() {
        return (
            <View style={{flex: 1}}>
                {this._renderNav()}
                ...
            </View>
        )
    }

    _renderNav() {
        return (
            <NavigationBar
                    title={'Main'}
                    //showLeft={false}
                    onLeftClick={()=>{
                                   alert('a')
                               }}
                    leftButton={()=><View><Text>自定义左侧按钮</Text></View>}
                    statusBar={{
                        barStyle: 'dark-content',
                        backgroundColor: 'white',
                        hidden: false,//true则隐藏
                    }}

                />
        )
    }

讲解一下有以下几个方法:

style:整个标题栏的样式

titleView:自定义中间布局
title:中间的东西如果不自定义的话直接传入文字
titleLayoutStyle : 标题的文字样式

showLeft : 默认为true 显示返回键 我这里导航使用的是ReactNavigation,如果需要是其他导航需要返回键功能请改内层代码或者在onLeftClick中写方法,
leftTextStyle :“返回”文字的样式
leftButton:自定义的左面的View
onLeftClick:左面布局点击的方法,如果不传递默认是返回上层页面

rightButton, rightTextStyle, showRight, onRightClick 同理。
但是 showRight默认值为false,即没有右侧按钮

可以自己传入statusBar,默认值为:

 statusBar: {
            barStyle: 'default',
            hidden: false, //true则隐藏statusBar
        }

样式大概如此,颜色可以自己定义,
左侧按钮,中间文字,和右侧按钮都可以自己传入一个自己写的布局。
后续会完善功能和方法。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/u011272795/article/details/80722036