React Navigation 構建 Android 和 iOS 統一的 UI
React Navigation 是 React Native 專案常用的路由和導航庫,通過它我們可以很輕鬆的構建多個頁面並完成頁面的跳轉。不過,因為 iOS 和 Android 在設計風格上的差異,React Navigation 在不同平臺上的表現也不同。例如,切換 StackNavigator
頁面時,iOS 是從右側滑入,而 Android 是從底部滑入。 在 React Native 專案中,有時我們想要構建 iOS 和 Android 統一的 UI,這時我們就需要對 React Navigation 的預設配置進行一些修改。本文以 iOS 風格為主,介紹如何構建在 Android 上表現相同的 UI。
主要的差異
開始之前,先看一下 iOS 和 Android 之間有哪些差異,這樣我們才清楚自己要做什麼。
狀態列
iOS 中 App 是全屏模式,狀態列不佔據佈局空間。

Android 中狀態列預設是佔據佈局空間的。

Header
在 iOS 中,Header 的高度是 44,標題居中,底部有邊框,返回按鈕圖示是“<”。

在 Android 中,Header 的高度是 56,標題居左,底部有陰影,返回按鈕圖示是“←”。

同時在標題的字型上也存在差異。
頁面切換效果
iOS 是從右側滑入劃出,而 Android 是從底部的淡入淡出。

同時,我們還可以注意到在切換時,iOS 的 Header 是固定在頂部的,而 Android 是隨頁面一起切換的(Android 截圖不便,這裡就沒有貼出)。
統一 UI
在瞭解完差異以後,現在來看看怎麼抹平這些差異來實現統一的 UI(iOS 風格)。
狀態列
在 iOS 中頁面是全屏的,狀態列不佔空間,頁面內容會上移到狀態列下面(這是 iOS 中有 SafeAreaView
的原因之一),而Android 中預設狀態列是佔空間的。通常這沒有什麼問題,但是當我們需要設定全屏背景或者頁面頂部有背景圖片時,Android 上的體驗就較差了。
幸好,在 Android 4.4 以後,通過 FLAG_TRANSLUCENT_STATUS
屬性可以將狀態列設定成不佔據佈局空間的透明樣式。我們可以在 Android 程式碼中設定:
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 複製程式碼
也可以在 theme 中設定 windowTranslucentStatus
:
<!-- android/app/src/main/res/values/styles.xml --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">true</item></style> 複製程式碼
還可以通過 StatusBar 的 translucent
屬性進行設定。
<StatusBar translucent /> 複製程式碼
設定完以後效果如下圖。

從圖中可以看出,狀態列現在不佔據空間,內容上移導致狀態列和標題欄重疊了。為了讓標題欄回到原來的位置,我們需要增加 Header 的高度,並且新增一個上邊距,大小為狀態列的高度:
static navigationOptions = { title: 'PageB', headerStyle: Platform.OS === 'android' ? { paddingTop: StatusBar.currentHeight, height: StatusBar.currentHeight + 56, } : {} } 複製程式碼
Header 和過渡效果
Header 和過濾效果我們都可以通過 createStackNavigator
暴露出來的屬性來進行配置。
{ defaultNavigationOptions: { headerTitleStyle: { fontSize: 17, } }, headerMode: 'float', // 公用一個頂部 Header,頁面切換時顯示動畫 headerLayoutPreset: 'center' // 標題居中 } 複製程式碼