1. 程式人生 > >ReactNative 自定義標題欄 ReactNative 自定義導航欄

ReactNative 自定義標題欄 ReactNative 自定義導航欄

這裡寫圖片描述
這裡寫圖片描述

/**
 * Created by 李卓原 on 2018/7/6.
 * email: zhuoyuan93@gmail.com
 *
 */

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

//ScreenUtil 為螢幕尺寸適配的工具類
import * as ScreenUtil from "../utils/ScreenUtil"
; import PropTypes from 'prop-types'; 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 = { statusBar: PropTypes.shape(StatusBarShape), showBackgroundIMG: PropTypes.bool, style: ViewPropTypes.style, title: PropTypes.string, titleView: PropTypes.element, titleLayoutStyle: ViewPropTypes.style, showLeft: PropTypes.bool, leftText: PropTypes.string, leftTextStyle: ViewPropTypes.style, showleftImg: PropTypes.bool, leftButton: PropTypes.element, showRight: PropTypes.bool, rightText: PropTypes.string, rightTextStyle: ViewPropTypes.style, rightButton: PropTypes.element, }; static defaultProps = { statusBar: { barStyle: 'default'
, hidden: false, }, showLeft: true, showleftImg: true, //是否顯示返回箭頭 leftText: '', //返回鍵位置的文字 showRight: false, rightText: '更多', showBackgroundIMG: true //是否有背景圖片 }; constructor(props) { super(props); } render() { 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 ( <ImageBackground source={this.props.showBackgroundIMG ? require('IMG/app_bar.png') : null} style={[styles.container, this.props.style]}> {statusBar} {content} </ImageBackground> ) } _renderLeft() { let {leftButton, leftTextStyle, showLeft, navigation, onLeftClick, leftText, showleftImg} = this.props; if (!showLeft) { return null; } if (leftButton == null) { return ( <TouchableOpacity onPress={() => { if (onLeftClick) { onLeftClick(); } else { if (navigation) navigation.goBack() } }}> <View style={styles.leftContainer}> { showleftImg ? <Image source={require('IMG/back.png')} style={{ width: ScreenUtil.scaleSize(25), height: ScreenUtil.scaleSize(25) }}/> : null } <Text style={[styles.leftRightStyle, leftTextStyle]}>{leftText}</Text> </View> </TouchableOpacity>) } return leftButton; } _renderRight() { let {rightButton, rightTextStyle, showRight, onRightClick, rightText} = this.props; if (!showRight) { return null; } if (rightButton == null) { return ( <TouchableOpacity onPress={() => { if (onRightClick) { onRightClick() } }}> <View> <Text style={[styles.leftRightStyle, rightTextStyle]}>{rightText}</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', width: ScreenUtil.screenW, height: ScreenUtil.scaleSize(58), justifyContent: 'center', }, 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(18), color: 'white' }, leftRightStyle: { color: 'white', fontSize: ScreenUtil.setSpText(14) }, leftContainer: { marginLeft: ScreenUtil.scaleSize(17), flexDirection: 'row', alignItems: 'center' } }); // 包裝 component ,注入 dispatch 和 state 到其預設的 connect(selector)(App) 中; /** * 把這個元件用connect包裹住就能拿到store。 注意export default已經拿到下面來了,上面的class前面的匯出要刪掉 用redux的話需要第一種方法匯出,已註釋掉 */ //export default connect(changeColor)(withNavigation(NavigationBar)); //用不到redux推薦在定義類的時候直接匯出,類定義為 export default class ... //當這個元件拿不到this.props.navigation時,可使用withNavigation //withNavigation是一個更高階的元件,它將導航道具傳遞給一個包裝元件。 //當您無法直接將導航道具傳遞到元件時,或者在深度巢狀子節點的情況下不希望傳遞導航道具時,它非常有用。 //匯出方式:export default withNavigation(NavigationBar); export default 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則隱藏
                    }}

                />
        )
    }

配合ReactNavigation使用

const RootStack = createStackNavigator({
    TaskList: {screen: TaskListPage},
    TaskDetails: {screen: TaskDetailsPage}
}, {
    navigationOptions: ({navigation}) => ({
        header: <NavigationBar title={navigation.state.routeName}
                               showLeft={navigation.state.routeName !== 'TaskList'}
                               navigation={navigation}
        />
    })
});

屬性:

Prop Type Default Description
style ViewPropTypes.style - 標題欄的樣式
showBackgroundIMG bool true 背景為一個圖片
title string - 標題使用的字串
titleLayoutStyle ViewPropTypes.style - 標題文字的樣式
titleView PropTypes.element - 替換標題文字的元件
leftButton PropTypes.element - 自定義左側按鈕
leftText string - 左側返回按鈕的文字
leftTextStyle ViewPropTypes.style - 替換標題文字的元件
showLeft bool true 是否顯示返回按鈕
leftImg source的引數 ImageSourcePropType 左側圖片的地址
showleftImg bool true 是否顯示標題的後退按鈕,需自行替換成其他Image
showLeft bool true 是否顯示返回按鈕
onLeftClick func this.props.navigation.goBack() 左側按鈕的點選事件(預設為ReactNavigation的goback)
showRight bool false 是否顯示右側按鈕
rightText string 更多 右側按鈕的文字
rightImg source的引數 ImageSourcePropType 右側圖片的地址,預設不傳則不顯示
rightTextStyle ViewPropTypes.style - 是否顯示返回按鈕
rightButton PropTypes.element - 自定義右側按鈕
onRightClick PropTypes.func - 右側按鈕的點選事件
statusBar { barStyle: PropTypes.oneOf([‘light-content’, ‘default’, ‘dark-content’]), hidden: PropTypes.bool, backgroundColor: PropTypes.string,} { barStyle: ‘default’, hidden: false,} 自定義狀態列

可以自己傳入statusBar,預設值為:

 statusBar: {
            barStyle: 'default',
            hidden: false, //true則隱藏statusBar
        }

樣式大概如此,顏色可以自己定義,
左側按鈕,中間文字,和右側按鈕都可以自己傳入一個自己寫的佈局。
後續會完善功能和方法。