felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

React Navigation 配置 header #142

Open felix-cao opened 5 years ago

felix-cao commented 5 years ago

每一个 screen component 都有一个静态属性 navigationOptions, 可以将一个返回值为对象的函数赋值给 navigationOptions,也可以直接将这个对象赋值给 navigationOptions

通过本文的学习,需要掌握:

一、title 属性

1.1、设置 title

titlenavigationOptions 最常用的一个属性,用于设置 header 显示的名称。将 《React Navigation 参数传递》 中的代码更改如下

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
  };

  /* render function, etc */
}

class DetailsScreen extends React.Component {
  static navigationOptions = {
    title: 'Details',
  };

  /* render function, etc */
}

snack 中跑一把

1.2、读取参数的 title

把一个匿名函数赋值给 navigationOptions, 匿名函数返回一个对象,对象中的 title 接收了匿名函数中的参数。

class DetailsScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    return {
      title: navigation.getParam('otherParam', 'A Nested Details Screen'),
    };
  };

  /* render function, etc */
}

实际上这个匿名函数的参数对象有三个属性:

另外两个不常用,我们一般情况下了解 navigation 这个就可以了

1.3、更改 title 属性

// in DetailsScreen component
// ... Other Code
<Button
  title="Go back"
  onPress={() => this.props.navigation.goBack()}
/>
<Button
  title="Update the title"
  onPress={() =>
    this.props.navigation.setParams({ otherParam: 'Updated!' })}
/>
// ... Other Code

二、调整 header 样式

React Navigation 为我们提供了可以自定义的 header ,用于调整(Adjusting)样式,从而适配我们的需求。主要有三个属性:

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
    headerStyle: {
      backgroundColor: '#f4511e',
    },
    headerTintColor: '#fff',
    headerTitleStyle: {
      fontWeight: 'bold',
    },
  };

  /* render function, etc */
}

snack 中跑一把看看

三、跨 Screen 共享 navigationOptions

在上面的例子中,我们只设置了 HomeScreenheader 样式,现在我们在 DetailsScreen 中也设置同样的 header 样式,我们可以像HomeScreen一样,去 DetailsScreen 中写同样的 code, 只是,这种硬编码方式是很多人难以接受的,幸运的是 React Navigation 给我们提供了一个方案:在 Stack Navigation 的路由配置的第二个参数中设置 defaultNavigationOptions 属性

我们从本文 1.1 的代码开始

const AppNavigator = createStackNavigator(
 {
  Home: HomeScreen,
  Details: DetailsScreen
 },
 {
   initialRouteName: 'Home',
   defaultNavigationOptions: {
      headerStyle: {
        backgroundColor: '#f4511e',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
    },
 }
);

需要注意的是:

四、用自定义组件代替 header

还从本文1.1的代码开始

class MyTitle extends React.Component {
  render() {
    return (
      <View style={{ backgroudColor: '#d1d1d1', height: 30 }}><Text style={{color: '#ff0000'}}>Hello MyTitle</Text></View>
    );
  }
}

class HomeScreen extends React.Component {
  static navigationOptions = {
    // headerTitle instead of title
    headerTitle: <MyTitle />,
  };

  /* render function, etc */
}

snack 中跑一把

五、Header buttons

header title 的左边或右边加按钮用于交互是非常常见的需求,接上面的代码

// ... other code
class HomeScreen extends React.Component {
  static navigationOptions = {
    headerTitle: <MyTitle />,
    headerRight: (
      <Button
        onPress={() => alert('This is a button!')}
        title="Info"
        color="#222"
      />
    )
  };
}

// ... other code

snack 中跑一把

六、Header 与 Screen Component 的交互。

// In HomeScreen
// ... other code
static navigationOptions = ({ navigation }) => {
    return {
      headerTitle: <MyTitle />,
      headerRight: (
        <Button
          onPress={navigation.getParam('increaseCount', function(){})}
          title="+1"
          color="#222"
        />
      ),
    };
  };

  componentDidMount() {
    this.props.navigation.setParams({ increaseCount: this._increaseCount });
  }

  state = {
    count: 0,
  };

  _increaseCount = () => {
    this.setState({ count: this.state.count + 1 });
  };
// ... other code

Reference