【水滴石穿】rn_statusbar

先放项目地址https://github.com/hezhii/rn_statusbar
来看一下效果




咩有感觉很怎么样,看代码
根入口文件

//index.js
//看代码我们知道入口是app.js
import { AppRegistry } from 'react-native';
import App from './src/App';
import { name as appName } from './app.json';

AppRegistry.registerComponent(appName, () => App);

app.js

//src/App.js
//里面主要是引用了navigator.js
import React, { PureComponent } from 'react';

import Navigator from './Navigator'

export default class App extends PureComponent {
  render() {
    return <Navigator />
  }
}
//src/Navigator.js
import React from 'react'
import { createAppContainer, createStackNavigator, createBottomTabNavigator } from 'react-navigation'

import TabBarIcon from './components/TabBarIcon'

import Home from './pages/Home'
import My from './pages/My'
import Login from './pages/Login'
import Register from './pages/Register'

const Main = createBottomTabNavigator(
  {
    Home,
    My
  },
  {
    defaultNavigationOptions: ({ navigation }) => {
      const { routeName } = navigation.state;
      return {
        tabBarIcon: ({ focused }) => <TabBarIcon focused={focused} routeName={routeName} />,
      };
    },
    tabBarOptions: {
      activeTintColor: '#437dff',
      inactiveTintColor: '#888FA1',
      style: {
        borderTopColor: '#E6E8EB',
      },
    },
  }
)

export default createAppContainer(createStackNavigator(
  {
    Main: {
      screen: Main,
      navigationOptions: {
        header: null,
      },
    },
    Login,
    Register
  },
  {
    defaultNavigationOptions: {
      headerBackTitle: '返回'
    }
  }
))

//src/pages/Home.js
import React from 'react'
import { StyleSheet, View, ImageBackground, Button, StatusBar } from 'react-native'

import Header from '../components/Header'
import { setStatusBar } from '../components/HOC/StatusBar'

@setStatusBar({
  barStyle: 'light-content',
  translucent: true,
  backgroundColor: 'transparent'
})
export default class Home extends React.PureComponent {
  static navigationOptions = {
    title: '主页'
  }

  render() {
    return (
      <View style={styles.fill}>
        <ImageBackground style={styles.bg} source={require('../assets/imgs/bg.png')}>
          <Header title="主页" fullScreen />
        </ImageBackground>
        <View style={styles.buttonWrapper}>
          <Button
            title="退出登录"
            onPress={() => this.props.navigation.push('Login')}
            color="#437dff"
          />
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  fill: {
    flex: 1
  },
  bg: {
    height: 234,
  },
  text: {
    fontSize: 20,
    fontWeight: '500',
    color: '#437dff',
    textAlign: 'center'
  },
  buttonWrapper: {
    padding: 16
  }
})
//src/pages/Login.js
import React from 'react'
import { StyleSheet, View, Button } from 'react-native'

import { setStatusBar } from '../components/HOC/StatusBar'

@setStatusBar()
export default class Login extends React.PureComponent {
  static navigationOptions = {
    title: '登录',
  }

  render() {
    return (
      <View style={styles.fill}>
        <View style={styles.buttonWrapper}>
          <Button
            title="点击注册"
            onPress={() => this.props.navigation.push('Register')}
            color="#437dff"
          />
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  fill: {
    flex: 1
  },
  buttonWrapper: {
    padding: 16
  }
})

//src/pages/My.js
import React from 'react'
import { StyleSheet, View, Button } from 'react-native'

import Header from '../components/Header'
import { setStatusBar } from '../components/HOC/StatusBar'

@setStatusBar({
  barStyle: 'light-content',
  translucent: true,
  backgroundColor: 'transparent'
})
export default class My extends React.PureComponent {
  static navigationOptions = {
    title: '我的',
  }

  render() {
    return (
      <View style={styles.fill}>
        <Header title="我的" style={styles.header} fullScreen />
        <View style={styles.buttonWrapper}>
          <Button
            title="退出登录"
            onPress={() => this.props.navigation.push('Login')}
            color="#437dff"
          />
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  fill: {
    flex: 1
  },
  text: {
    fontSize: 20,
    fontWeight: '500',
    color: '#437dff',
    textAlign: 'center'
  },
  header: {
    backgroundColor: '#437dff',
  },
  buttonWrapper: {
    padding: 16
  }
})
//src/pages/Register.js
import React from 'react'
import { StyleSheet, View, Text, StatusBar } from 'react-native'

export default class Login extends React.PureComponent {
  static navigationOptions = {
    title: '注册',
    headerStyle: {
      backgroundColor: '#437dff',
    },
    headerTintColor: '#fff'
  }

  render() {
    return (
      <View style={styles.fill}>
        <StatusBar translucent={false} backgroundColor='red' barStyle="light-content" />
        <Text style={styles.text}>注册页面</Text>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  fill: {
    flex: 1
  },
  text: {
    marginTop: 32,
    fontSize: 20,
    fontWeight: '500',
    color: '#437dff',
    textAlign: 'center'
  }
})

工具函数里面是做的适配

//src/utils/device.js
import { Platform, Dimensions } from 'react-native';

// iPhone X、iPhone XS
const X_WIDTH = 375;
const X_HEIGHT = 812;

// iPhone XR、iPhone XS Max
const XSMAX_WIDTH = 414;
const XSMAX_HEIGHT = 896;

const DEVICE_SIZE = Dimensions.get('window');
const { height: D_HEIGHT,  D_WIDTH } = DEVICE_SIZE;

export { DEVICE_SIZE };

export const isiOS = () => Platform.OS === 'ios'

export const isAndroid = () => Platform.OS === 'android'

export const isiPhoneX = () => {
  return (
    isiOS() &&
    ((D_HEIGHT === X_HEIGHT && D_WIDTH === X_WIDTH) ||
      (D_HEIGHT === X_WIDTH && D_WIDTH === X_HEIGHT)) ||
    ((D_HEIGHT === XSMAX_HEIGHT && D_WIDTH === XSMAX_WIDTH) ||
      (D_HEIGHT === XSMAX_WIDTH && D_WIDTH === XSMAX_HEIGHT))
  );
};

export const ifiPhoneX = (iPhoneXStyle, regularStyle) => isiPhoneX() ? iPhoneXStyle : regularStyle

封装的header

//src/components/Header/index.js
/**
 * 全屏页面中使用的 Header 组件。非全屏页面使用 react-nativetion 的 Header 即可。
 * 
 * 组件会根据当前运行的环境调整高度,考虑了状态栏。
 */

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

import { isiOS, isiPhoneX } from '../../utils/device'

const STATUS_BAR_HEIGHT = isiOS() ? (isiPhoneX() ? 34 : 20) : StatusBar.currentHeight
const HEADER_HEIGHT = 44

const Header = ({ title, left, right, color = '#fff', style, fullScreen }) => {
  const headerStyle = [
    styles.header,
    (fullScreen || isiOS()) && {
      height: STATUS_BAR_HEIGHT + HEADER_HEIGHT,
      paddingTop: STATUS_BAR_HEIGHT
    },
    style
  ]

  return (
    <View style={headerStyle}>
      <View style={styles.left}>
        {left}
      </View>
      <Text style={[styles.title, { color }]}>{title}</Text>
      <View style={styles.right}>
        {right}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  header: {
    height: HEADER_HEIGHT,
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 15,
  },
  title: {
    flex: 2,
    fontSize: 17,
    textAlign: 'center',
  },
  left: {
    flex: 1,
    flexDirection: 'row',
  },
  right: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'flex-end',
  },
});

export default Header;
//src/components/TabBarIcon/index.js
import React from 'react';
import { StyleSheet, Image } from 'react-native';

const styles = StyleSheet.create({
  image: {
    height: 24,
  },
});

export default ({ routeName, focused }) => {
  const images = {
    Home: focused
      ? require('../../assets/icons/home_fill.png')
      : require('../../assets/icons/home.png'),
    My: focused
      ? require('../../assets/icons/my_fill.png')
      : require('../../assets/icons/my.png'),
  };
  return (
    <Image style={styles.image} source={images[routeName]} resizeMode="contain" />
  );
}
//src/components/HOC/StatusBar.js
//这个是定义的高阶函数
import React from 'react'
import hoistNonReactStatics from 'hoist-non-react-statics'
import { StatusBar } from 'react-native'

import { isAndroid } from '../../utils/device'

export const setStatusBar = (statusbarProps = {}) => WrappedComponent => {
  class Component extends React.PureComponent {
    constructor(props) {
      super(props)
      this._navListener = props.navigation.addListener('willFocus', this._setStatusBar)
    }

    componentWillUnmount() {
      this._navListener.remove();
    }

    _setStatusBar = () => {
      const {
        barStyle = "dark-content",
        backgroundColor = '#fff',
        translucent = false
      } = statusbarProps
      StatusBar.setBarStyle(barStyle)
      if (isAndroid()) {
        StatusBar.setTranslucent(translucent)
        StatusBar.setBackgroundColor(backgroundColor);
      }
    }

    render() {
      return <WrappedComponent {...this.props} />
    }
  }

  return hoistNonReactStatics(Component, WrappedComponent);
}

just soso

原文地址:https://www.cnblogs.com/smart-girl/p/10916583.html