react-navigation(基础学习)(一)

一、react-navigation是干什么的?

react-navigation提供了类似于浏览器的导航窗口,可以实现跳转和回退等功能。它维护了一个堆栈,把浏览记录都放在堆栈当中,当点击返回时就会把堆栈当中的第一个去除掉,剩下的就是上一个页面。

二、react-navigation 的安装

在你的react-native项目中:

yarn add react-navigation
# or with npm
# npm install --save react-navigation

  

三、初步使用react-nativigation

react-navigation使用createStackNavigator创建一个堆栈浏览器,通过传入路径名和路径名对应的参数(如路径所对应的屏幕组件,屏幕标题栏的设置等功能。)

import React from 'react';
import { View, Text } from 'react-native';
import { createStackNavigator } from 'react-navigation';

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Home Screen</Text>
      </View>
    );
  }
}

export default createStackNavigator({
  Home: {
    screen: HomeScreen
  },
});

  createStackNavigator是创建了一个组件。

由于app.js是整个程序的入口,因此一般我们在app.js中使用export default class App,将创建的堆栈浏览器赋值给一个组件变量,并在App中返回该组件。这样我们可以更多的对堆栈浏览器进行设置。

修改上述代码如下:

const RootStack = createStackNavigator({
  Home: {
    screen: HomeScreen
  },
});

export default class App extends React.Component {
  render() {
    return <RootStack />;
  }
}

 如果路径后仅有screen一个参数,也可以简化写:

const RootStack = createStackNavigator({
  Home: HomeScreen
});

 添加第二条路径:

class DetailsScreen extends React.Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Details Screen</Text>
      </View>
    );
  }
}

const RootStack = createStackNavigator(
  {
    Home: HomeScreen,
    Details: DetailsScreen,
  },
  {
    initialRouteName: 'Home',
  }
);

  initialRouteName用于指定初始化的路径

四、在不同的页面进行转移

所有在createStackNavigation中创建的screen组件的props中都含有navigation这个对象,通过调用navigaition的navigate和push方法便可以跳转到指定的路径,并且可以在跳转的同时传递参数给指定的路径,被传递参数的路径可以通过getParam的方法获取上一个路径传递的参数。

示例:

import React from 'react';
import { Button, View, Text } from 'react-native';
import { createStackNavigator } from 'react-navigation';

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Home Screen</Text>
        <Button
          title="Go to Details"
          onPress={() => this.props.navigation.navigate('Details')}
        />
      </View>
    );
  }
}

  

<Button
  title="Go to Details... again"
  onPress={() => this.props.navigation.push('Details')}
/>
}

  navigate和push的区别是:navigate首先检查堆栈浏览器中是否已经存在该页面,如果存在就不会重复添加,而push不检查堆栈浏览器中是否存在,每次都用都添加一个新的路径到堆栈浏览器中。

每当调用navigate或push到一个页面时,navigation便自动会在页面标题处出现返回按钮,当然也可以手工调用函数goBack返回,示例

class DetailsScreen extends React.Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Details Screen</Text>
        <Button
          title="Go to Details... again"
          onPress={() => this.props.navigation.push('Details')}
        />
        <Button
          title="Go to Home"
          onPress={() => this.props.navigation.navigate('Home')}
        />
        <Button
          title="Go back"
          onPress={() => this.props.navigation.goBack()}
        />
      </View>
    );
  }
}

  返回指定路径,请使用navigate,返回最上层的页面使用 navigation.popToTop()

五、页面转移同时添加参数

传递参数使用:this.props.navigation.navigate('RouteName', { /* params go here */ })或者this.props.navigation.push('RouteName', { /* params go here */ })

被传递的路径接受参数使用this.props.navigation.getParam(paramName, defaultValue),如果没有接受到参数则使用默认参数defaultValue

示例:

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Home Screen</Text>
        <Button
          title="Go to Details"
          onPress={() => {
            /* 1. Navigate to the Details route with params */
            this.props.navigation.navigate('Details', {
              itemId: 86,
              otherParam: 'anything you want here',
            });
          }}
        />
      </View>
    );
  }
}

class DetailsScreen extends React.Component {
  render() {
    /* 2. Get the param, provide a fallback value if not available */
    const { navigation } = this.props;
    const itemId = navigation.getParam('itemId', 'NO-ID');
    const otherParam = navigation.getParam('otherParam', 'some default value');

    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Details Screen</Text>
        <Text>itemId: {JSON.stringify(itemId)}</Text>
        <Text>otherParam: {JSON.stringify(otherParam)}</Text>
        <Button
          title="Go to Details... again"
          onPress={() =>
            this.props.navigation.push('Details', {
              itemId: Math.floor(Math.random() * 100),
            })}
        />
        <Button
          title="Go to Home"
          onPress={() => this.props.navigation.navigate('Home')}
        />
        <Button
          title="Go back"
          onPress={() => this.props.navigation.goBack()}
        />
      </View>
    );
  }
}

  可以使用this.props.navigation.state.params接受参数,但如果上调路径没有传递参数过来,就会出现null值。

六、设置标题栏

到现在为止,标题栏的格式还是默认的白色,页面时灰色,现在看如何设置标题栏的标题、字体、背景、图片等信息

在screen组件中可以调用静态属性:navigationOptions来设置标题栏的属性,

设置标题,使用title属性

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

  /* render function, etc */
}

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

  /* render function, etc */
}

  我们还可以使用参数设置标题,static navigationOptions可以接受三个参数分别是navigation(相当于this.props.navigation),screenProps(屏幕的属性)和navigationOptions(使用已经定义好的navigationOption定义默认属性),这里可以使用navigation.getParm的方法接受参数并传递给title,示例

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

  同时可以使用navigation.setParams来设置参数:

<Button
    title="Update the title"
    onPress={() => this.props.navigation.setParams({otherParam: 'Updated!'})}
  />

 

调整标题栏的样式:可以通过设置:

headerStyle:头部标题栏样式

headerTintColor:头部标题和返回键的颜色

headerTitleStyle:标题字体的属性,大小,粗细,字体等,示例

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

  上述设置仅对一个HomeScreen生效,如果要对所有的screen生效,需要在包含screen的createStackNavigator创建的堆栈浏览器组件中进行统一的配置,当然如果不希望统一的配置,可以继续在单个screen中进行配置,这时单个screen的配置将覆盖在createStackNavigator中的配置。示例:

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
    /* No more header config here! */
  };

  /* render function, etc */
}

/* other code... */

const RootStack = createStackNavigator(
  {
    Home: HomeScreen,
    Details: DetailsScreen,
  },
  {
    initialRouteName: 'Home',
    /* The header config from HomeScreen is now here */
    navigationOptions: {
      headerStyle: {
        backgroundColor: '#f4511e',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
    },
  }
);

  覆盖createStackNavigator的设置示例:

class DetailsScreen extends React.Component {
  static navigationOptions = ({ navigation, navigationOptions }) => {
    const { params } = navigation.state;

    return {
      title: params ? params.otherParam : 'A Nested Details Screen',
      /* These values are used instead of the shared configuration! */
      headerStyle: {
        backgroundColor: navigationOptions.headerTintColor,
      },
      headerTintColor: navigationOptions.headerStyle.backgroundColor,
    };
  };

  /* render function, etc */
}

  当然,也可以使用自定义的组件代替标题,如使用一张图片

class LogoTitle extends React.Component {
  render() {
    return (
      <Image
        source={require('./spiro.png')}
        style={{ width: 30, height: 30 }}
      />
    );
  }
}

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

  /* render function, etc */
}

  这里使用的headerTitle,而不是title

 

 

 

 

 

posted @ 2018-07-28 09:22  tutu_python  阅读(349)  评论(0)    收藏  举报