React Native 應用程式的由右至左版面配置支援
在應用程式發布到應用程式商店後,國際化是進一步擴展受眾範圍的下一步。全球有超過 20 個國家和眾多人使用由右至左 (RTL) 語言。因此,讓您的應用程式支援他們的 RTL 是必要的。
我們很高興宣布 React Native 已獲得改進,以支援 RTL 版面配置。這項功能今天已在 react-native master 分支中提供,並將在下一個 RC 版本中提供:v0.33.0-rc
。
這牽涉到變更 css-layout(RN 使用的核心版面配置引擎)、RN 核心實作,以及特定的 OSS JS 組件以支援 RTL。
為了在生產環境中測試 RTL 支援,最新版本的 Facebook 廣告管理員應用程式(第一個跨平台 100% RN 應用程式)現在提供阿拉伯語和希伯來語版本,並為 iOS 和 Android 提供 RTL 版面配置。以下是在這些 RTL 語言中的外觀


RN 中用於 RTL 支援的變更概述
css-layout 已經具有 start
和 end
的版面配置概念。在由左至右 (LTR) 版面配置中,start
表示 left
,而 end
表示 right
。但在 RTL 中,start
表示 right
,而 end
表示 left
。這表示我們可以讓 RN 依賴 start
和 end
計算來計算正確的版面配置,其中包括 position
、padding
和 margin
。
此外,css-layout 已經使每個組件的方向繼承自其父組件。這表示,我們只需要將根組件的方向設定為 RTL,整個應用程式就會翻轉。
下圖說明了高階變更
這些包括
- css-layout RTL 支援絕對定位
- 在 RN 核心實作中將
left
和right
映射到陰影節點的start
和end
- 並公開一個 橋接公用程式模組,以協助控制 RTL 版面配置
透過此更新,當您允許應用程式使用 RTL 版面配置時
- 每個組件版面配置都會水平翻轉
- 如果您使用支援 RTL 的 OSS 組件,則某些手勢和動畫將自動具有 RTL 版面配置
- 可能需要最少的額外工作才能使您的應用程式完全支援 RTL
讓應用程式支援 RTL
-
為了支援 RTL,您應該先將 RTL 語言套件新增至您的應用程式。
-
透過在原生程式碼的開頭呼叫
allowRTL()
函數,允許您的應用程式使用 RTL 版面配置。我們提供此公用程式僅在您的應用程式準備就緒時才套用至 RTL 版面配置。以下是一個範例iOS
// in AppDelegate.m
[[RCTI18nUtil sharedInstance] allowRTL:YES];Android
// in MainActivity.java
I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
sharedI18nUtilInstance.allowRTL(context, true); -
對於 Android,您需要在
AndroidManifest.xml
檔案中的<application>
元素中新增android:supportsRtl="true"
。
現在,當您重新編譯應用程式並將裝置語言變更為 RTL 語言(例如阿拉伯語或希伯來語)時,您的應用程式版面配置應自動變更為 RTL。
編寫支援 RTL 的組件
一般而言,大多數組件都已支援 RTL,例如
- 由左至右版面配置

- 由右至左版面配置

但是,有幾種情況需要注意,您需要 I18nManager
。在 I18nManager
中,有一個常數 isRTL
可以判斷應用程式的版面配置是否為 RTL,以便您可以根據版面配置進行必要的變更。
具有方向性含義的圖示
如果您的組件具有圖示或圖像,它們在 LTR 和 RTL 版面配置中的顯示方式將相同,因為 RN 不會翻轉您的來源圖像。因此,您應根據版面配置樣式翻轉它們。
- 由左至右版面配置

- 由右至左版面配置

以下是根據方向翻轉圖示的兩種方式
-
將
transform
樣式新增至圖像組件<Image
source={...}
style={{transform: [{scaleX: I18nManager.isRTL ? -1 : 1}]}}
/> -
或者,根據方向變更圖像來源
let imageSource = require('./back.png');
if (I18nManager.isRTL) {
imageSource = require('./forward.png');
}
return <Image source={imageSource} />;
手勢和動畫
在 Android 和 iOS 開發中,當您變更為 RTL 版面配置時,手勢和動畫與 LTR 版面配置相反。目前,在 RN 中,手勢和動畫在 RN 核心程式碼層級上不受支援,但在組件層級上受支援。好消息是,其中一些組件今天已經支援 RTL,例如 SwipeableRow
和 NavigationExperimental
。但是,其他具有手勢的組件將需要手動支援 RTL。
說明手勢 RTL 支援的一個很好的範例是 SwipeableRow
。
手勢範例
// SwipeableRow.js
_isSwipingExcessivelyRightFromClosedPosition(gestureState: Object): boolean {
// ...
const gestureStateDx = IS_RTL ? -gestureState.dx : gestureState.dx;
return (
this._isSwipingRightFromClosed(gestureState) &&
gestureStateDx > RIGHT_SWIPE_THRESHOLD
);
},
動畫範例
// SwipeableRow.js
_animateBounceBack(duration: number): void {
// ...
const swipeBounceBackDistance = IS_RTL ?
-RIGHT_SWIPE_BOUNCE_BACK_DISTANCE :
RIGHT_SWIPE_BOUNCE_BACK_DISTANCE;
this._animateTo(
-swipeBounceBackDistance,
duration,
this._animateToClosedPositionDuringBounce,
);
},
維護支援 RTL 的應用程式
即使在首次發布 RTL 相容的應用程式後,您可能仍需要迭代新功能。為了提高開發效率,I18nManager
提供了 forceRTL()
函數,用於更快速地進行 RTL 測試,而無需變更測試裝置語言。您可能想在您的應用程式中為此提供一個簡單的開關。以下是 RNTester 中 RTL 範例的範例
<RNTesterBlock title={'Quickly Test RTL Layout'}>
<View style={styles.flexDirectionRow}>
<Text style={styles.switchRowTextView}>forceRTL</Text>
<View style={styles.switchRowSwitchView}>
<Switch
onValueChange={this._onDirectionChange}
style={styles.rightAlignStyle}
value={this.state.isRTL}
/>
</View>
</View>
</RNTesterBlock>;
_onDirectionChange = () => {
I18nManager.forceRTL(!this.state.isRTL);
this.setState({isRTL: !this.state.isRTL});
Alert.alert(
'Reload this page',
'Please reload this page to change the UI direction! ' +
'All examples in this app will be affected. ' +
'Check them out to see what they look like in RTL layout.',
);
};
在開發新功能時,您可以輕鬆切換此按鈕並重新載入應用程式以查看 RTL 版面配置。好處是您無需變更語言設定即可進行測試,但是某些文字對齊方式不會變更,如下一節所述。因此,在發布之前,最好始終在 RTL 語言中測試您的應用程式。
限制和未來計畫
RTL 支援應涵蓋您應用程式中的大多數 UX;但是,目前有一些限制
- 文字對齊行為在 Android 和 iOS 中有所不同
- 在 iOS 中,預設文字對齊方式取決於活動語言套件,它們在同一側保持一致。在 Android 中,預設文字對齊方式取決於文字內容的語言,即英文將靠左對齊,而阿拉伯文將靠右對齊。
- 理論上,這應該在跨平台之間保持一致,但有些人可能在使用應用程式時更喜歡一種行為而不是另一種行為。可能需要更多使用者體驗研究來找出文字對齊的最佳實務。
-
沒有「真正的」左/右
如前所述,我們將 JS 端的
left
/right
樣式映射到start
/end
,RTL 版面配置的所有程式碼中的left
在螢幕上都會變成「右」,而程式碼中的right
會變成螢幕上的「左」。這很方便,因為您不需要對您的產品程式碼進行太多變更,但這表示無法在程式碼中指定「真正的左」或「真正的右」。未來,允許組件控制其方向而與語言無關可能是必要的。 -
使手勢和動畫的 RTL 支援對開發人員更友善
目前,仍然需要一些程式設計工作才能使手勢和動畫與 RTL 相容。未來,最好找到一種方法,使手勢和動畫的 RTL 支援對開發人員更友善。
試用看看!
查看 RNTester
中的 RTLExample
,以更深入瞭解 RTL 支援,並告訴我們它對您來說效果如何!
最後,感謝您的閱讀!我們希望 React Native 的 RTL 支援能幫助您為國際受眾擴展您的應用程式!