代码之家  ›  专栏  ›  技术社区  ›  ZeroBased_IX

如何在react导航中使用用户指定的主题?

  •  1
  • ZeroBased_IX  · 技术社区  · 8 年前

    我一直在尝试为我的react导航器设定主题,这很容易用硬编码的颜色,例如。 Colours.background , Colours.accent .

    当用户通过身份验证时,我提供了他们的基本细节和一个主题对象。使用redux将其存储在我的应用程序状态中( state.auth.user.theme

    我有一个AppNavigation,其中创建了我的导航器。

    应用导航。js公司

    import React from 'react'
    import { Text, Animated, Easing, Image, View } from 'react-native'
    import { StackNavigator, DrawerNavigator, addNavigationHelpers } from 'react-navigation'
    import Icon from 'react-native-vector-icons/EvilIcons'
    import { connect } from 'react-redux'
    
    import DrawerContainer from '../Containers/DrawerContainer'
    import ScreenTwoScreen from '../Containers/ScreenTwoScreen'
    import ScreenOneScreen from '../Containers/ScreenOneScreen'
    import DashboardScreen from '../Containers/DashboardScreen'
    import LoginScreen from '../Containers/LoginScreen'
    
    import styles from './Styles/NavigationStyles'
    import ThemeProvider from '../Themes/ThemeProvider';
    import Images from '../Themes/Images';
    
    const Colors = ThemeProvider()
    
    const DrawerStack = DrawerNavigator({
      screenOneScreen: { screen: ScreenOneScreen },
      dashboardScreen: { screen: DashboardScreen },
    }, {
        gesturesEnabled: false,
        contentComponent: DrawerContainer
      })
    
    const drawerButton = (navigation) =>
        <Text
          style={{ padding: 5, color: 'white' }}
          onPress={() => {
            // Coming soon: navigation.navigate('DrawerToggle')
            // https://github.com/react-community/react-navigation/pull/2492
            if (navigation.state.index === 0) {
              navigation.navigate('DrawerOpen')
            } else {
              navigation.navigate('DrawerClose')
            }
          }
          }><Icon name="navicon" color={Colors.headerText} size={24} /></Text>
    
    
    // login stack
    const LoginStack = StackNavigator({
      loginScreen: { screen: LoginScreen },
    }, {
        headerMode: 'none',
        navigationOptions: {
        }
      })
    
    const logoStyle = {
      height: 45,
      width: 45,
      marginLeft: 10,
      resizeMode: 'contain'
    }
    const DrawerNavigation = StackNavigator({
      DrawerStack: { screen: DrawerStack }
    }, {
        headerMode: 'float',
        navigationOptions: ({ navigation }) => ({
          headerStyle: { backgroundColor: Colors.brand },
          title: 'Welcome!',
          headerTintColor: Colors.headerText,
          gesturesEnabled: false,
          headerRight: drawerButton(navigation),
          headerLeft: <Image source={Images.clubLogo} style={logoStyle} />
        })
      })
    
    
    // Manifest of possible screens
    const PrimaryNav = StackNavigator({
      loginStack: { screen: LoginStack },
      drawerStack: { screen: DrawerNavigation }
    }, {
        // Default config for all screens
        headerMode: 'none',
        initialRouteName: 'loginStack',
        navigationOptions: {
          headerStyle: styles.header
        }
      })
    
    export default PrimaryNav
    

    这在ReduxNavigation中使用。js:

    ReduxNavigation。js公司

    import React from 'react'
    import * as ReactNavigation from 'react-navigation';
    import { connect } from 'react-redux'
    import AppNavigation from './AppNavigation'
    import Colors from '../Themes/Colors'
    import ThemeProvider from '../Themes/ThemeProvider'
    // here is our redux-aware our smart component
    class ReduxNavigation extends React.Component {
      static navigationOptions = ({ navigation, screenProps }) => {
        console.log(navigation)
        return {
          headerStyle: {
            backgroundColor: this.props.user ? this.props.user.club.brand : Colors.brand
          }
        }
      }
      render() {
        const { dispatch, nav, user } = this.props
        const navigation = ReactNavigation.addNavigationHelpers({
          dispatch,
          state: nav
        })
    
    
        // if (user) {
        //   theme = ThemeProvider(user.club.theme)
        // }
        return <AppNavigation navigation={navigation} />
      }
    
    }
    
    const mapStateToProps = state => ({ nav: state.nav, user: state.auth.user })
    export default connect(mapStateToProps)(ReduxNavigation)
    

    没什么特别的:

    import Colors from './Colors';
    
    const ThemeProvider = (other ={}) => {
        return Object.assign({}, Colors, other)
    }
    
    export default ThemeProvider;
    

    我试过的事情

    • 创建了一个主题提供者方法,将用户主题合并到颜色中,它起了作用,但并不正确。
    • 将AppNavigation的核心转移到ReduxNavigation的渲染方法中,但这使得应用程序没有响应,这是可以理解的。
    • 试图找到一种将主题作为道具传递给PrimaryNav的方法,react navigation不喜欢额外的道具。

    想法和想法?此外,应用程序的核心是由 InfiniteRed/ignite 如果有什么用的话。

    1 回复  |  直到 8 年前
        1
  •  4
  •   ZeroBased_IX    8 年前

    找到了一种方法,使用 screenProps 在ReduxNavigation中:

    class ReduxNavigation extends React.Component {
    
      render() {
        const { dispatch, nav, user } = this.props
        const navigation = ReactNavigation.addNavigationHelpers({
          dispatch,
          state: nav
        })
        return <AppNavigation navigation={navigation} screenProps={{ user }} />
      }
    
    }
    

    然后,在需要自定义主题的导航器上的AppNavigation中,我会:

    DrawerNavigation = StackNavigator({
      DrawerStack: { screen: DrawerStack }
    }, {
        headerMode: 'float',
        navigationOptions: ({ navigation, screenProps }) => {
          let headerText = Colors.headerText;
          let brand = Colors.brand;
          let accent = Colors.accent;
          if (screenProps.user) {
            let theme = screenProps.user.club.theme;
            brand = theme.brand;
            headerText = theme.headerText;
            accent = theme.accent;
          }
          return ({
            headerStyle: { backgroundColor: brand },
            title: 'Welcome!',
            headerTintColor: headerText,
            gesturesEnabled: false,
            headerRight: drawerButton(navigation, headerText),
            headerLeft: <Image source={Images.clubLogo} style={logoStyle} />
          })
        }
      })
    
    推荐文章