iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 10
1

本篇目的

首先我們必須認知到我們雖應該盡量的共用程式碼,但不應該完全被綁死,由於 iOS、Android 功能實作上的限制、UI 的慣例都還是有其差異,Facebook 內部在使用 React Native 時共用程度大約是 87 % 左右,所以我們也必須了解這些差異以及實作的方式。

平台設計的差異

Building the F8 2016 App: Part 2 - Designing an App for Multiple Platforms 這篇文有詳細的描述 Facebook F8 App 的跨平台設計過程,很值得一讀。

裡面有提到幾個很明顯的差異,如下圖:

header

  • iOS 上 Title 通常置中,而 Android 上置左
  • iOS Tab 使用框線加圓角,Android 使用下底線

在設計 Menu 時,iOS 比較常放在下方:

menu

其他比較明顯的差異有:

  • Android 有回上頁的實體按鈕,而 iOS 只有 Home 鍵,所以通常左上角會放回上一頁的按鈕。
  • iOS 上方只能左右各放一個按鈕,而 Android 可以放兩個以上的按鈕。
  • 確認、取消的按鈕位置的不同

更多設計的差異,建議直接參閱平台官方的 Guideline:

React Native 的機制

平台副檔名

React Native Packager 有內建的機制來處理不同平台的副檔名 (File Extension),例如我們一建立專案時所會看到的 index.ios.jsindex.android.js,就相當於 iOS、Android 上面各自的 index.js,這會在打包時處理妥當。

而其他的地方也可以類推:

const filename = require('./filename');

如果沒有 ./filename.js./filename.json 這些檔案,在 iOS 上會去找 ./filename.ios.js、在 Android 上則會去找 ./filename.android.js

我們也一樣能使用副檔名來載入不同圖片,例如:my-icon.ios.png and my-icon.android.png

另外,最新推出的 React VR,它的進入點則是 index.vr.js,可以看出類似的模式。

Platform 模組

React Native 的 Platform 模組,上面有一些關於平台的 Property 或是 Method 能夠取用。

其中這邊最有用的是 Platform.OS,可以藉由判斷它的值是 ios 還是 android 來做不一樣的樣式或是邏輯:

import { Platform, StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  height: (Platform.OS === 'ios') ? 200 : 100,
});

實際的案例,可以看看 f8app 裡面的 F8SegmentedControl 中間的用法。

Platform StyleSheet

F8App 的介紹文 中有提到一個 F8StyleSheet.create 的用法,可以簡單地去指定平台相關的樣式:

/* from js/common/F8SegmentedControl.js */
var styles = F8StyleSheet.create({
  container: {
    flexDirection: 'row',
    backgroundColor: 'transparent',
    ios: {
      paddingBottom: 6,
      justifyContent: 'center',
      alignItems: 'center',
    },
    android: {
      paddingLeft: 60,
    },
  },
  // ..
};

它的原始碼其實相當簡單,只是使用前面介紹過的 Platform.OS 來做屬性的覆寫:

export function create(styles: Object): {[name: string]: number} {
  const platformStyles = {};
  Object.keys(styles).forEach((name) => {
    let {ios, android, ...style} = {...styles[name]};
    if (ios && Platform.OS === 'ios') {
      style = {...style, ...ios};
    }
    if (android && Platform.OS === 'android') {
      style = {...style, ...android};
    }
    platformStyles[name] = style;
  });
  return StyleSheet.create(platformStyles);
}

有人把它抽出成獨立的 npm 套件 react-native-platform-stylesheet,讓我們可以直接安裝使用。

Native Modules

React Native 有提供橋接原生模組的方式,包括 Objective-C、Swift 的 iOS ModuleJava 的 Android Module,如果有既有適合的原生程式模組,也是可以考慮直接利用這個方式來使用。

結語

做出好的體驗是我們所共同追求的目標,除了未來 React Native 可能會幫我們處理妥善的部份以外,還需要盡己所能的去了解各平台的樣貌,以求能提供細緻的平台體驗。


上一篇
Day 09:常見的 React Native Component - Part II
下一篇
Day 11:IDE (Integrated Development Environment) for React Native
系列文
使用 Modern Web 技術來打造 Native App30

尚未有邦友留言

立即登入留言