從 Android 到 React Native 開發(3、自定義原生控件支持)

 恍惚間3個月過去了,做爲揭棺而起的失蹤人口,遲來的第三篇,也是react native原生相關的最後的一篇,是時候給收個尾了。此次就不廢話了,直接上主題( ̄^ ̄)ゞ。javascript

 react native的高效,在於其中大部分組件,都是基於原生封裝的,js中對組件的配置與操做,最終都會轉化爲native控件行爲。以上的這段廢話,總結起來就是:react native經過統一的接口封裝,把原生控件轉爲js組件使用。java

 既然有官方封裝,那確定少不了自定義控件。react native自定義組件仍是很方便的,關鍵就在於ViewManager/ViewGroupManager。從類名上,很明顯是對應原生中的View和ViewGroup。node

(PS :react native 中的View組件,封裝的實際上是ViewGroupManager,因此View組件才能夠包裹子組件,組件中的ZIndex屬性,其實就是子組件在add到ViewGroup中前後,以下圖) react

 其餘的內部細節就不深究咯,愉悅的奔向主題吧(˶‾᷄ ⁻̫ ‾᷅˵)。注意,下方代碼分析大部分來自如下路徑:git

//js組件
node_modules/react-native/Libraries/Components/View
node_modules/react-native/Libraries/Components/WebView

//原生java
react-native-0.xx.x/com.facebook/react/views/view
react-native-0.xx.x/com.facebook/react/views/webview複製代碼

一、繼承ViewGroupManager

 首先咱們須要實現一個XXXGroupManager,繼承於ViewGroupManager。其中最主要的即是重載實現getName和creatViewInstance兩個方法。github

  • getName 指定了XXXGroupManager在js組件中獲取的名稱。web

  • creatViewInstance 建立了自定義控件在Manager中使用,這裏只要將你在原生端的自定義控件,生成便可。react-native

 js組件中,使用requireNativeComponent,能夠經過上面中getName指定的名稱,獲取到對應的控件,以下圖,經過獲取到的控件,就能夠配置對應的接口啦ε-(´∀`; )。ui

關於requireNativeComponent的使用說明參考下圖 this

二、設置自定義控件屬性

 react native 提供 @ReactProp@ReactPropGroup 註解,爲js組件提供接口,配置原生控件的屬性。以下圖1,name = "borderStyle" 表示,js組件能夠經過borderStyle設置控件的borderStyle,如圖2。若是須要默認值,能夠增長default屬性。

圖1

圖2

 這裏須要注意,@ReactPropGroup是一組相近的屬性設置註解,如設置UI的上下左右的不一樣寬度,原生中經過index判斷,而它們在js端組件的設置,能夠統一到原生中的一個接口。

圖3

三、原生控件操做JS組件

 react native提供原生控件對js組件的交互支持,和上一篇文章相似,也是經過事件機制發送,發送消息到js組件中,js組件經過監聽事件的callback處理消息。

 首先,在 UIManagerModuleConstants.java 中,如圖4,react native默認映射了一些組件的消息事件名,如topChange在js組件中經過onChange監聽,這樣在原始中經過topChange發送的消息,就能夠在組件中的onChange接收到消息。

 消息中的參數,能夠經過WritableMap傳遞數據,利用rctEventEmitter發送消息。

圖4

圖5

 有時候,你可能還須要自定義本身的消息名,那麼你須要重寫
getExportedCustomDirectEventTypeConstants ,只有註冊了你的映射消息關係,才能夠在js組件中,正常接收到你自定的消息名的消息。

圖6

圖7

四、js組件操做原生控件

 既然原生控件能夠操做組件,那麼js組件也有控制原生控件的需求。這時候咱們能夠重載 getCommandsMap ,用來註冊js組件支持的操做行爲,經過 receiveCommand 處理操做,如在js組件中調用reload,就會觸發原生XXXGroupManager中receiveCommand的root.reload,從而與原生控件交互。

圖9中,經過UIManager,發送命令到原生。

圖8

圖9

 這類使用方式,相似的使用場景有,例如

//textInput組件中主動獲取焦點
UIManager.dispatchViewManagerCommand(
                    ReactNative.findNodeHandle(this.textInput),
                    UIManager.AndroidTextInput.Commands.focusTextInput,
                    null);複製代碼

五、js端組件實現

 最終在原生端配置結束後,js端配置完對應邏輯,經過 module.exports = WebView 導出組件使用。

結言

 拖了這麼久,react native和andorid原生相關的文章終於收尾啦(◐‿◑),也算是對react native的一個里程碑吧。在實際開發中,react native的代碼的複用率仍是挺高的,做爲跨平臺開發的一種,仍是蠻推薦你們嘗試下。

 接下來有時間會把github的demo完善下,畢竟demo落下的有點多了,歡迎你們關注喲ε-(´∀`; )。

我的github入口:github.com/CarGuo

還記得我嗎?
相關文章
相關標籤/搜索