React Navigation - Gradient color for Header

2019-02-07 11:59发布

问题:

I am using React Navigation in React Native app and i want to change the backgroundColor for the header to be gradient and i found out there is a node module : react-native-linear-gradient to achieve gradient in react native

i have Root StackNavigator like that :

const Router = StackNavigator({

Login: {
    screen: Login,
    navigationOptions: ({navigation}) => ({
       headerTitle: <Text>SomeTitle</Text>
       headerLeft: <SearchAndAgent />,
       headerRight: <TouchableOpacity
        onPress={() => { null }
    </TouchableOpacity>,
    headerStyle: { backgroundColor: '#005D97' },
    }),
},
});

i can wrap Text or View to be gradient like that :

<LinearGradient colors={['#3076A7', '#19398A']}><Text style={styles.title}>{title}</Text></LinearGradient>,

how can i wrap the header background in the navigationOptions to use the the LinearGradient module?

i know that i can create a custom header component and use it but when i doing it all the native navigation animations from React Navigation not working like the Title Animation between two Routes so its not helping me.

thanks for helping !

回答1:

The solution of Mark P was right but now you need to define headerStyle and do the absolute positioning there:

navigationOptions: {
  header: props => <GradientHeader {...props} />,
  headerStyle: {
    backgroundColor: 'transparent',
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
  },
},

and the GradientHeader:

const GradientHeader = props => (
<View style={{ backgroundColor: '#eee' }}>
    <LinearGradient
      colors={['red', 'blue']}
      style={[StyleSheet.absoluteFill, { height: Header.HEIGHT }]}
    >
      <Header {...props} />
    </LinearGradient>
  </View>
)


回答2:

Just for your information, now with headerBackground props it's a way easier.

You can have a gradient header just doing this :

navigationOptions: {
  headerBackground: (
    <LinearGradient
      colors={['#a13388', '#10356c']}
      style={{ flex: 1 }}
      start={[0, 0]}
      end={[1, 0]}
    />
  ),
  headerTitleStyle: { color: '#fff' },
}

This solution works good even with SafeArea for IosX



回答3:

Similar to this issue: React Navigation; use image in header?

For a Linear Gradient you would simply do >

//imports

import { Image, StyleSheet, View } from 'react-native';
import { Header } from 'react-navigation' ;
import LinearGradient from 'react-native-linear-gradient';

//header

Create the Header component which is wrapped in the Linear Gradient. by making the header backgroundColor: 'transparent' you will then show the Linear Gradient wrapping it.

const GradientHeader = props => (
  <View style={{ backgroundColor: '#eee' }}>
    <LinearGradient
      colors={['#00a8c3', '#00373f']}
      style={[StyleSheet.absoluteFill, styles.linearGradient]}
    />
    <Header {...props} style={{ backgroundColor: 'transparent' }}/>
  </View>
);

Return the screen with the header being your GradientHeader component.

const SimpleStack = StackNavigator({
  Home: {
    screen: MyHomeScreen,
  },
}, {
  navigationOptions: {
    headerTitleStyle: { color: '#fff' },
    header: (props) => <GradientHeader {...props} />,
  }
});

Should look something like this with the above code.

Gradient Header



回答4:

You can use LinearGradient component from the expo. It is a useful component and you can't install another library like react-native-linear-gradient. https://docs.expo.io/versions/latest/sdk/linear-gradient/. By the way, you can change the back button. It is easy.

You can implement it on inside screen with navigationOptions like that

static navigationOptions = ({ navigation }: any) => {
  const onGoBack = () => navigation.goBack();
  return {
    header: (props: any) => <GradientHeader {...props} />,
    headerStyle: { height: 68, backgroundColor: "transparent", color: colors.white },
    headerTitle: "Sign Up",
    headerTitleStyle: { color: colors.white, fontSize: 18 },
    headerLeft: (
      <TouchableOpacity style={{ width: 32, height: 32, paddingLeft: 8 }} onPress={onGoBack}>
        <Image source={images.back} resizeMode="center" style={{ width: 32, height: 32 }} />
      </TouchableOpacity>
    ),
  };
};