跳到主要內容

React Native 應用程式的由右至左版面配置支援

·7 分鐘閱讀
Mengjue (Mandy) Wang
Facebook 軟體工程師實習生

在應用程式發布到應用程式商店後,國際化是進一步擴展受眾範圍的下一步。全球有超過 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 應用程式)現在提供阿拉伯語和希伯來語版本,並為 iOSAndroid 提供 RTL 版面配置。以下是在這些 RTL 語言中的外觀

RN 中用於 RTL 支援的變更概述

css-layout 已經具有 startend 的版面配置概念。在由左至右 (LTR) 版面配置中,start 表示 left,而 end 表示 right。但在 RTL 中,start 表示 right,而 end 表示 left。這表示我們可以讓 RN 依賴 startend 計算來計算正確的版面配置,其中包括 positionpaddingmargin

此外,css-layout 已經使每個組件的方向繼承自其父組件。這表示,我們只需要將根組件的方向設定為 RTL,整個應用程式就會翻轉。

下圖說明了高階變更

這些包括

透過此更新,當您允許應用程式使用 RTL 版面配置時

  • 每個組件版面配置都會水平翻轉
  • 如果您使用支援 RTL 的 OSS 組件,則某些手勢和動畫將自動具有 RTL 版面配置
  • 可能需要最少的額外工作才能使您的應用程式完全支援 RTL

讓應用程式支援 RTL

  1. 為了支援 RTL,您應該先將 RTL 語言套件新增至您的應用程式。

  2. 透過在原生程式碼的開頭呼叫 allowRTL() 函數,允許您的應用程式使用 RTL 版面配置。我們提供此公用程式僅在您的應用程式準備就緒時才套用至 RTL 版面配置。以下是一個範例

    iOS

    // in AppDelegate.m
    [[RCTI18nUtil sharedInstance] allowRTL:YES];

    Android

    // in MainActivity.java
    I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
    sharedI18nUtilInstance.allowRTL(context, true);
  3. 對於 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,例如 SwipeableRowNavigationExperimental。但是,其他具有手勢的組件將需要手動支援 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 支援能幫助您為國際受眾擴展您的應用程式!