美文网首页
react-navigation自定义header

react-navigation自定义header

作者: 莫伊剑客 | 来源:发表于2021-05-12 10:47 被阅读0次

模拟淘宝首页


模拟淘宝首页
// react/react-native
import React from 'react'
import {
    SafeAreaView,
    ScrollView,
    Text,
    View,
    Image,
    StatusBar,
    NativeModules,
    useColorScheme,
    Platform,
} from 'react-native'

// 获取安全区工具,自测只有ios好使
import {useSafeAreaInsets} from "react-native-safe-area-context";

// react-navigation
import {createStackNavigator} from "@react-navigation/stack";
const {Navigator: StackNavigator, Screen: StackScreen} = createStackNavigator();

// 页面
import Subscribe from '../../screens/Home/Subscribe';
import Recommend from '../../screens/Home/Recommend';

// 自定义HeaderLeft,Header,HeaderRight组件
import CustomHeaderLeft from './components/CustomHeaderLeft'
import CustomHeader from './components/CustomHeader'
import CustomHeaderRight from './components/CustomHeaderRight'

// 定义Navigator配置文件
const optionsConfig = (prop) => {

    // 动态获取状态栏高度
    const getStatusHeight:any = () => {
        if (Platform.OS === 'ios') {
            console.log('StatusBarMessage',useSafeAreaInsets());
            return useSafeAreaInsets().top
        } else {
            console.log('StatusBarMessage',StatusBar.currentHeight)
            // 由于安卓的header高度不包含状态栏高度,所以直接返回0,android刘海屏带测试
            return 0 //StatusBar.currentHeight
        }
    };

    return {
        // 直接将prop传给组件,
        // 注意 headerLeft: (prop) => <CustomHeaderLeft {...prop}/>, 不可取,亲测这种方式子组件获取不到navigation对象
        headerLeft: () => <CustomHeaderLeft {...prop}/>,
        headerTitle: () => <CustomHeader {...prop}/>,
        headerRight: () => <CustomHeaderRight {...prop}/>,
        headerMode: 'screen',
        // header整体样式设置
        headerStyle: {
            // header容器高度+状态栏高度,android不需要加状态栏高度
            height: 80 + getStatusHeight(),
            borderBottomWidth: 0,
            elevation: 0
            // backgroundColor:'blue',
        },
        // 左、中、右容器样式设置,高度均不含状态栏高度
        headerLeftContainerStyle: {
            height: 40,
            paddingLeft: 10
        },
        headerTitleContainerStyle:{
            paddingLeft:30,
            paddingRight:30,
            height:80
        },
        headerRightContainerStyle: {
            height: 40,
            paddingRight: 10
        },
    }
};
const HomeStack = () => {
    return (
        <StackNavigator screenOptions={optionsConfig}>
            <StackScreen name={'Subscribe'} component={Subscribe}/>
            <StackScreen name={'Recommend'} component={Recommend}/>
        </StackNavigator>
    )
};
export default HomeStack

CustomHeaderLeft

import React, {useState} from 'react'
import {
    SafeAreaView,
    ScrollView,
    Text,
    View,
    Image,
    StatusBar,
    useColorScheme,
    Platform,
    StyleSheet,
    TouchableWithoutFeedback
} from 'react-native'
import {Iconfont} from "../../../../assets/font";

const CustomHeaderLeft = () => {
    return (
      <SafeAreaView style={styles.safe}>
          <TouchableWithoutFeedback>
              <View style={[styles.container]}>
                  <Iconfont name="TRP-qiandao" size={20} color={'#F41B0C'}/>
                  <View style={{paddingLeft:4,paddingRight:10}}>
                      <Text style={{color:'#E1613C',fontWeight:'500'}}>签到</Text>
                  </View>
              </View>
          </TouchableWithoutFeedback>
      </SafeAreaView>
    )
};
const styles = StyleSheet.create({
    safe:{
        flex:1,
        // backgroundColor:'yellow'
    },
    container: {
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        flexDirection: "row",
        backgroundColor:'#FCEEDB',
        marginTop:6,
        marginBottom:6,
        paddingLeft:4,
        height:28,
        borderRadius:14
    }
})
export default CustomHeaderLeft

CustomHeader

import React, {useState} from 'react'
import {
    SafeAreaView,
    ScrollView,
    Text,
    View,
    Image,
    StatusBar,
    NativeModules,
    useColorScheme,
    Platform,
    StyleSheet,
    TouchableOpacity,
    TouchableWithoutFeedback,
    Dimensions
} from 'react-native'
import CustomHeaderInput from './CustomHeaderInput'

const CustomHeader = (prop) => {
    const [data, setData] = useState([
        {
            name: '订阅',
            isActive: true
        },
        {
            name: '推荐',
            isActive: false
        }
    ]);
    const {width, height, scale} = Dimensions.get('window');
    const left:number = Math.floor((width - 146-20) / 2);
    // console.log('计算偏移量', width, height, scale, left)
    const click: any = (i) => {
        setData((data: any): any => {
            return data.map((em, index) => {
                if (index === i) {
                    em.isActive = true
                } else {
                    em.isActive = false
                }
                return em
            })
        });
        console.warn(data)
    };
    return (
        <SafeAreaView style={styles.safe}>
            <View style={styles.flexCloumn}>
                <View style={[styles.positionR]}>
                    <View style={styles.title}>
                        {
                            data.map((em, index) => {
                                return (
                                    <TouchableOpacity key={index} onPress={() => {
                                        click(index)
                                    }}>
                                        <View style={styles.item}>
                                            <Text style={[styles.text, (() => {
                                                if (em.isActive) return styles.active;
                                                return;
                                            })()]}>{em.name}</Text>
                                        </View>
                                    </TouchableOpacity>
                                )
                            })
                        }
                    </View>
                    <View style={[styles.positionA, styles.bottomLine, (() => {
                        const i = data.findIndex(em => em.isActive);
                        if (i === 0) {
                            return {left: 25}
                        } else {
                            return {right: 25}
                        }
                    })()]}></View>
                    <View style={{position: 'absolute', left: -left, right: left, bottom: -34}}>
                        <CustomHeaderInput {...prop}/>
                    </View>
                </View>
            </View>
        </SafeAreaView>
    )
};
const styles = StyleSheet.create({
    safe: {
        // flex: 1,
        // backgroundColor:'gray',
    },
    flexCloumn: {
        // flex: 1,
        // display: 'flex',
        // justifyContent: 'flex-start',
        alignItems: 'center',
        flexDirection: "column",
        // backgroundColor:'red'
    },
    title: {
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        flexDirection: "row",
        // height: 40,
        // backgroundColor: 'gray'
    },
    item: {
        paddingLeft: 15,
        paddingRight: 15,
        height:40,
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        flexDirection: "row",
    },
    itemActive: {},
    text: {
        fontSize: 20,
        color:'#333'
    },
    positionR: {
        position: 'relative'
    },
    positionA: {
        position: 'absolute'
    },
    bottomLine: {
        width: 24,
        height: 2,
        backgroundColor: '#E1613C',
        borderRadius: 1,
        bottom: 2,
        right: 25//23
    },
    active: {
        fontWeight: '500',
        fontSize: 22,
        color: '#E1613C'
    }
})
export default CustomHeader

CustomHeaderRight

import React, {useState} from 'react'
import {
    SafeAreaView,
    ScrollView,
    Text,
    View,
    Image,
    StatusBar,
    useColorScheme,
    Platform,
    StyleSheet,
    TouchableWithoutFeedback
} from 'react-native'
import {Iconfont} from "../../../../assets/font";

const CustomHeaderLeft = ({route,navigation}) => {
    return (
        <SafeAreaView style={styles.safe}>
            <TouchableWithoutFeedback>
                <View style={[styles.container]}>
                    <Iconfont name="TRP-huiyuanma" size={20} color={'#F41B0C'}/>
                    <View style={{paddingLeft: 4, paddingRight: 10}}>
                        <Text style={{color: '#E1613C', fontWeight: '500'}}>会员码</Text>
                    </View>
                </View>
            </TouchableWithoutFeedback>
        </SafeAreaView>
    )
};
const styles = StyleSheet.create({
    safe:{
        flex:1,
        height:28,
        // backgroundColor:'green'
    },
    container: {
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        flexDirection: "row",
        backgroundColor: '#FCEEDB',
        marginTop: 6,
        marginBottom: 6,
        paddingLeft:10,
        height: 28,
        borderRadius: 14
    }
})
export default CustomHeaderLeft

CustomHeaderInput

import React, {useState} from 'react'
import {
    SafeAreaView,
    ScrollView,
    Text,
    View,
    Image,
    StatusBar,
    useColorScheme,
    Platform,
    StyleSheet,
    TouchableWithoutFeedback,
    TextInput,
    Dimensions
} from 'react-native'
import {Iconfont} from "../../../../assets/font";

const CustomHeaderInput = ({route,navigation}) => {
    const {width, height, scale} = Dimensions.get('window');
    return (
        <SafeAreaView style={styles.safe}>
            <TouchableWithoutFeedback>
                <View style={[styles.container,{width:width-20}]}>
                    <View style={styles.saoma}><Iconfont name="TRP-Scancode" size={20} color={'#F41B0C'}/></View>
                    <TextInput style={styles.input}
                               placeholder={'短裤裙女夏'}
                               caretHidden={false}
                               clearButtonMode={'while-editing'}
                               autoCompleteType={'off'}
                               editable={false}
                    />
                    <TouchableWithoutFeedback onPress={()=>{
                        console.log('点击事件进来了')
                        console.warn(navigation)
                        navigation.navigate('Camera')
                    }}>
                        <View style={styles.xiangji}><Iconfont name="TRP-xiangji" size={20} color={'#F41B0C'}/></View>
                    </TouchableWithoutFeedback>
                    <View style={styles.button}>
                        <Text style={styles.buttonText}>搜索</Text>
                    </View>
                </View>
            </TouchableWithoutFeedback>
        </SafeAreaView>
    )
};
const styles = StyleSheet.create({
    safe: {
        flex: 1,
    },
    container: {
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        flexDirection: "row",
        height: 30,
        borderRadius: 15,
        borderWidth: 1,
        borderColor: '#F41B0C',
    },
    input: {
        flex: 1,
        padding: 0
    },
    saoma: {
        paddingLeft: 10,
        paddingRight: 10
    },
    xiangji: {
        paddingLeft: 10,
        paddingRight: 10
    },
    button: {
        width: 60,
        height: 26,
        backgroundColor: '#F41B0C',
        borderRadius: 13,
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        flexDirection: 'row',
        marginRight: 1,
    },
    buttonText: {
        color: '#fff'
    }
})
export default CustomHeaderInput

相关文章

网友评论

      本文标题:react-navigation自定义header

      本文链接:https://www.haomeiwen.com/subject/jnaodltx.html