其實(shí)RN中已存在部分控件到原生控件的映射矫限,在RN中可以直接使用苫耸,可是畢竟RN提供的組件有限乘客,我們平時(shí)原生開發(fā)中還進(jìn)行自定義控件/組件呢狡刘,所以這里就講到了RN如何去使用我們?cè)淖远x控件/組件俺祠。
下面以開發(fā)中碰到的事例簡(jiǎn)單介紹一下:
RN開發(fā)中同樣的代碼在Android與IOS上會(huì)有不同的現(xiàn)象绞惦,部分布局在iOS上顯示沒(méi)有問(wèn)題逼纸,但是在android環(huán)境下運(yùn)行會(huì)出現(xiàn)被剪裁的現(xiàn)象,現(xiàn)象如下左圖顯示济蝉,看到這我們Android開發(fā)應(yīng)該想到問(wèn)題的原因是因?yàn)樽硬季直桓覆季纸o剪裁了杰刽,那么又如何解決呢菠发?有問(wèn)題找開發(fā)者文檔啊,ViewGroup Android documentation (https://developer.android.com/reference/android/view/ViewGroup.html#setClipChildren(boolean))贺嫂,我們把這個(gè)屬性設(shè)置一下setClipChildren(false)發(fā)現(xiàn)可以解決問(wèn)題滓鸠,可是我們總不能每個(gè)View都這么設(shè)置吧,那我們就要自定義控件了第喳,在RN中使用我們的自定義控件了糜俗,主題來(lái)了哈,具體操作如下:
- 在Android項(xiàng)目中創(chuàng)建容器
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(); } } }
- 創(chuàng)建對(duì)應(yīng)的的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; } }
- 創(chuàng)建對(duì)應(yīng)的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通信的方法曲饱,下面會(huì)講述 return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { List<ViewManager> views = new ArrayList<>(); views.add(new ReactVGManager()); return views; } }
- 在Android項(xiàng)目中的application中設(shè)置對(duì)應(yīng)的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項(xiàng)目中創(chuàng)建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
- 創(chuàng)建AhsNativeModule供RN與Android通信使用
public class AhsNativeModule extends 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調(diào)用Native,并獲取返回值 * @param key * @param callback */ @ReactMethod public void rnGetNativeData(String key, Callback callback) { String result = "我可以根據(jù)你的key拿到你想要的數(shù)據(jù)"; callback.invoke(result); } /** * RN關(guān)閉當(dāng)前頁(yè)面 */ @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; }
通過(guò)這個(gè)事例也簡(jiǎn)單介紹了RN如何去調(diào)用原生的控件與自定義組件等操作,此處就不講述原生Android與RN如何通信了扩淀,之前已經(jīng)講述過(guò)楔敌,需要的請(qǐng)看 【RN系列:Android原生與RN如何交互通信】 。