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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM