react-navigation笔记

2018.02.07 1.0稳定版本已经发布

更新日志:https://github.com/react-navigation/react-navigation/releases

说下这个库的最新消息,几个月没动,终于发了一个roadmap,向1.0 stable进发了

https://reactnavigation.org/blog/2017/9/Renewed-v1

具体要完善的功能:

https://github.com/react-community/react-navigation/issues/2585

 已完善的点:

1.reset动画(目前reset的时候,动画是是分段完成的,而不是像普通back那种动画一次性)

相关issues:#1493

目前已经修复,具体查看#2520, 注意,这个request是在beta16中发布的,但是伴随着一个很严重的bug #2864,所以需要升级到beta17以上才能正常使用

2.跳转无动画

可能有需要某一个页面跳转或者返回的时候不需要动画,这个功能可以在beta28+版本(#3345)中实现

event-system

注意,需要搭配NavigationActions这种方式使用( 经过测试无效,暂时不知道怎么回事)

this.props.dispatch(
          NavigationActions.back({
            key: backFromScene.route.key,
            immediate: true,
          })
        );

 前面的版本NavigationActions,back()是不带参数的,navigation.goBack()是可以带参数的,最新的beta28+,NavigationActions,back()如同上面这种用法,也是可以带参数的了,不是都是route key,而不是routeName

基础参数:

1.navigationOptions

该值是从上一个页面传递过来或者自己在Screen中定义,自定义如下:

 static navigationOptions = {
        title:'登录',
        headerTintColor:'yellow',
        headerRight:
            <View style={{flexDirection:'row'}}>
                <Text style={{color:'red'}}>more</Text>
            </View>
    };

该对象支持的属性列表:

title

String that can be used as a fallback for headerTitle and tabBarLabel

header

React Element or a function that given HeaderProps returns a React Element, to display as a header. Setting to null hides header.

headerTitle

String or React Element used by the header. Defaults to scene title

headerBackTitle

Title string used by the back button on iOS or null to disable label. Defaults to scene title

headerTruncatedBackTitle

Title string used by the back button when headerBackTitle doesn't fit on the screen. "Back" by default.

headerRight

React Element to display on the right side of the header

headerLeft

React Element to display on the left side of the header

headerStyle

Style object for the header

headerTitleStyle

Style object for the title component

headerBackTitleStyle

Style object for the back title

headerTintColor

Tint color for the header

headerPressColorAndroid

Color for material ripple (Android >= 5.0 only)

gesturesEnabled

Whether you can use gestures to dismiss this screen. Defaults to true on iOS, false on Android.

2.params

传递参数

this.props.navigation.navigate('',{
      xxx:''
})

在目标组件中,可以通过下面的方式取值

this.props.navigation.state.params.xxx

如果是新的项目,这样修改无所谓,如果是老项目,并且使用官方的navigator,也就是说,以前这样this.props.xxx取值,现在就变成上面取值了,这将是一个巨大的工作量

此问题,在issues-935 可以看到,很多人都在讨论(抱怨)这个问题,也有人利用HOC给出的workground

https://github.com/vonovak/react-navigation-props-mapper (注意:0.2.0版本的使用方式和0.1.3的方式不一样,并且不兼容)

可以将params里面的对象直接映射到props一级

 场景支持:                                                                     

注意:该库的API变化比较快,一切以当前为准

1)修改header的背景色

  直接通过navigationOptions的headerStyle属性来设置,下面是全局配置,组件内设置static navigationOptions会覆盖该处的配置

  譬如设置全局的状态栏为蓝底,白字

  

const App = StackNavigator({
    Main:{screen:HomeScreen},
},{
    navigationOptions:{
        headerTintColor:gColors.bgColorF,
        headerStyle:{
            backgroundColor:gColors.themeColor
        },
        cardStack:{
            gesturesEnabled:false
        }
    }
});

 

2)动态修改右侧按钮的文字和响应

从上面的代码可以看出,在component中设置 navigationOptions,修饰符为static,所以这个时候使用this.xxx是无法响应的,必须是static方法才能响应,有一种间接的方式解决该方法

在navigationOptions中可以获取state.params,所以可以通过该值将component里面的方法和navigationOptions关联起来,具体代码如下

export default class Test extends Component
{
    componentDidMount()
    {
        this.props.navigation.setParams({
            onBack: () => this.onBack(),
        });
    }

    static navigationOptions = ({navigation})=>({
        title:`${navigation.state.params?navigation.state.params.title:'电影'}`,
        header:Test.renderHeader(navigation)
    });

    static renderHeader=(navigation)=>{
        return(
            <View style={{height:50,flexDirection:'row'}}>
                <TouchableOpacity
                    activeOpacity={activeOpacity}
                    style={{alignSelf:'stretch',justifyContent:'center'}}
                    onPress={()=>navigation.state.params.onBack()}
                >
                    <View style={{paddingLeft:15,paddingRight:8}}>
                        <Icon name="angle-left" size={30} color={gColors.bgColorF}/>
                    </View>
                </TouchableOpacity>
            </View>
        );
    }
    
    ...
}

 renderHeader方法除了使用静态函数,也可以直接使用无状态组件

const renderHeader=({navigation})=>{
        return(
            <View style={{height:50,flexDirection:'row'}}>
                <TouchableOpacity
                    activeOpacity={activeOpacity}
                    style={{alignSelf:'stretch',justifyContent:'center'}}
                    onPress={()=>navigation.state.params.onBack()}
                >
                    <View style={{paddingLeft:15,paddingRight:8}}>
                        <Icon name="angle-left" size={30} color={gColors.bgColorF}/>
                    </View>
                </TouchableOpacity>
            </View>
        );
    }

3)屏蔽iOS下左侧返回的文字

  iOS默认情况下,左侧的文字是上一个场景的title,可以通过headerBackTitle属性设置,设为null,则不显示(但是返回按钮的点击范围相当于右边还是有两个文字的空间)

    android默认情况下,左侧是没有返回文字的(靠着返回按钮的那是标题)

4)屏蔽左侧返回按钮及默认的返回响应事件

5)更改返回按钮的图标

目前iOS和Android的返回按钮风格不一样,改request已经被人完善,等待合并

具体关注:https://github.com/react-community/react-navigation/pull/1999 

6)动态的显示和隐藏状态栏

7)将Android的标题居中

android中,默认情况下,title是靠左,紧靠返回按钮的,可以通过下面的代码来居中:

navigationOptions:{
        headerTitleStyle:{
            alignSelf:'center',
        },
        headerRight:<View />  //那种有返回按钮的页面中,会导致title整体向右偏移,所有在右侧设置一个View,来让title居中
    }

目前全局的配置还未知怎么使用参数来判定是否有返回按钮,所以,如果需要首页(由于是栈底,没有左侧的返回按钮),需要对改页面设置,否者title会左侧偏移(因为右侧有一个<View />)

 static navigationOptions = ({navigation})=>({
        headerLeft:<View />
    });

 具体情况可以关注:https://github.com/react-community/react-navigation/issues/544

8)拦截安卓返回键的事件

 componentDidMount()
    {
        this.listener = BackHandler.addEventListener('hardwareBackPress',()=>{
            console.log('hardwareBackPress');
            return true;  //返回true的时候,不会向下传递事件,为false的时候,则是默认的事件,返回到上一页面
        });
    }

componentWillUnmount()
    {
        this.listener&&this.listener.remove();
    }

9)统一iOS和android的默认动画

ios默认的效果是左右卡片式,但是android的默认效果不一致,可以使用下面的方式将android的也改为左右卡片式

import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';

export default StackNavigator({
  Home: {
    screen: HomeScreen,
  },
}, {
  transitionConfig: () => ({
    screenInterpolator: CardStackStyleInterpolator.forHorizontal,
  }),
  navigationOptions: ({ navigation }) => ({
    //...
  }),
})

相关问题: #1400  #3086

原文地址:https://www.cnblogs.com/yz1311/p/7057421.html