Android專案整合RN系列:RN使用Android原生控制元件或自定義元件
其實RN中已存在部分控制元件到原生控制元件的對映,在RN中可以直接使用,可是畢竟RN提供的元件有限,我們平時原生開發中還進行自定義控制元件/元件呢,所以這裡就講到了RN如何去使用我們原生的自定義控制元件/元件。
下面以開發中碰到的事例簡單介紹一下:
RN開發中同樣的程式碼在Android與IOS上會有不同的現象,部分佈局在iOS上顯示沒有問題,但是在android環境下執行會出現被剪裁的現象,現象如下左圖顯示,看到這我們Android開發應該想到問題的原因是因為子佈局被父佈局給剪裁了,那麼又如何解決呢?有問題找開發者文件啊,ViewGroup Android documentation ( ofollow,noindex">https://developer.android.com/reference/android/view/ViewGroup.html#setClipChildren(boolean) ),我們把這個屬性設定一下setClipChildren(false)發現可以解決問題,可是我們總不能每個View都這麼設定吧,那我們就要自定義控制元件了,在RN中使用我們的自定義控制元件了,主題來了哈,具體操作如下:

image.png
- 在Android專案中建立容器
RNViewGroupLayout
public class RNViewGroupLayout extends ReactViewGroup { public RNViewGroupLayout(Context context) { super(context); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); try { ((ViewGroup) getParent()).setClipChildren(false); } catch (Exception e){ e.printStackTrace(); } } }
- 建立對應的的ReactVGManager
public class ReactVGManager extends ViewGroupManager<ReactViewGroup> { private static final String OVERFLOW_MANAGER_NAME = "NativeViewGroup"; @Override public String getName() { return OVERFLOW_MANAGER_NAME; } @Override protected ReactViewGroup createViewInstance(ThemedReactContext reactContext) { ReactViewGroup reactViewGroup = new RNViewGroupLayout(reactContext); return reactViewGroup; } }
- 建立對應的NativeReactPackage
public class NativeReactPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules=new ArrayList<>(); modules.add(new AhsNativeModule(reactContext)); //此處放置供RN與Android通訊的方法,下面會講述 return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { List<ViewManager> views = new ArrayList<>(); views.add(new ReactVGManager()); return views; } }
- 在Android專案中的application中設定對應的ReactNativeHost
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new NativeReactPackage() ); } };
- 在RN專案中建立NativeViewGroup.js
import React from 'react'; import PropTypes from 'prop-types' import { requireNativeComponent, View, } from 'react-native'; class NativeViewGroup1 extends React.Component { render() { return <AhsVG{...this.props}/> } } NativeViewGroup1.propTypes = { ...View.propTypes, }; const AhsVG = requireNativeComponent('NativeViewGroup', NativeViewGroup1) export default NativeViewGroup1
- 建立AhsNativeModule供RN與Android通訊使用
public class AhsNativeModuleextends ReactContextBaseJavaModule { public static final String REACT_NATIVE_CLASSNAME = "AhsNativeModule"; private ReactApplicationContext mContext; public static final String TAG = "TAG"; public AhsNativeModule(ReactApplicationContext reactContext) { super(reactContext); mContext = reactContext; } @Override public String getName() { return REACT_NATIVE_CLASSNAME; } /** * rn呼叫Native,並獲取返回值 * @param key * @param callback */ @ReactMethod public void rnGetNativeData(String key, Callback callback) { String result = "我可以根據你的key拿到你想要的資料"; callback.invoke(result); } /** * RN關閉當前頁面 */ @ReactMethod public void finishThisPage(){ if (getCurrentActivity() != null){ getCurrentActivity().finish(); } } /** * 向RN傳遞常量 */ @Nullable @Override public Map<String, Object> getConstants() { Map<String,Object> params = new HashMap<>(); params.put("Constant","我是常量,傳遞給RN"); return params; }
通過這個事例也簡單介紹了RN如何去呼叫原生的控制元件與自定義元件等操作,此處就不講述原生Android與RN如何通訊了,之前已經講述過,需要的請看 【Android專案整合RN系列:修改埠號 / 離線包 / 訊息通訊】 。