ReactNative如何在JS中引用原生自定义控件(rn变化太快,网上很多教程有坑,这个我研究后可用,特意分享)
Posted lee0oo0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReactNative如何在JS中引用原生自定义控件(rn变化太快,网上很多教程有坑,这个我研究后可用,特意分享)相关的知识,希望对你有一定的参考价值。
直接写一个Demo例子,有相关功底的肯定明白,会对特别的地方进行提醒,本文基于https://blog.csdn.net/lintcgirl/article/details/53489490,但是按此链接文章不可用。
首先是JAVA部分:
1 import com.facebook.react.ReactActivity; 2 3 public class MainActivity extends ReactActivity { 4 5 /** 6 * Returns the name of the main component registered from javascript. 7 * This is used to schedule rendering of the component. 8 */ 9 @Override 10 protected String getMainComponentName() { 11 return "RNMyTest"; 12 } 13 }
1 import android.app.Application; 2 3 import com.facebook.react.ReactApplication; 4 import com.facebook.react.ReactNativeHost; 5 import com.facebook.react.ReactPackage; 6 import com.facebook.react.shell.MainReactPackage; 7 import com.facebook.soloader.SoLoader; 8 import com.rnmytest.view.AppReactPackage; 9 10 import java.util.Arrays; 11 import java.util.List; 12 13 public class MainApplication extends Application implements ReactApplication { 14 15 private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 16 @Override 17 public boolean getUseDeveloperSupport() { 18 return BuildConfig.DEBUG; 19 } 20 21 @Override 22 protected List<ReactPackage> getPackages() { 23 return Arrays.<ReactPackage>asList( 24 new MainReactPackage(), 25 new AppReactPackage() 26 ); 27 } 28 29 @Override 30 protected String getJSMainModuleName() { 31 return "index"; 32 } 33 }; 34 35 @Override 36 public ReactNativeHost getReactNativeHost() { 37 return mReactNativeHost; 38 } 39 40 @Override 41 public void onCreate() { 42 super.onCreate(); 43 SoLoader.init(this, /* native exopackage */ false); 44 } 45 }
第一坑,之前的项目可能创建时间太久,ReactApplication完全无法引用,后面我是重新新建一个demo测试后能成功导入,各种百度google无法解决这个方案,如有能解决的朋友请告诉我。
下面是自定义的view
1 import com.facebook.react.ReactPackage; 2 import com.facebook.react.bridge.NativeModule; 3 import com.facebook.react.bridge.ReactApplicationContext; 4 import com.facebook.react.uimanager.ViewManager; 5 import java.util.Arrays; 6 import java.util.Collections; 7 import java.util.List; 8 9 /** 10 * Created by bingmingli on 2018/6/8. 11 */ 12 13 public class AppReactPackage implements ReactPackage { 14 15 @Override 16 public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { 17 return Collections.emptyList(); 18 } 19 20 // @Override 21 // public List<Class<? extends JavaScriptModule>> createJSModules() { 22 // return Collections.emptyList(); 23 // } 24 25 @Override 26 public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { 27 return Arrays.<ViewManager>asList( 28 new CircleManager() 29 ); 30 } 31 }
第二坑:注释部分的方法在新版本已经去除了
1 import android.content.Context; 2 import android.graphics.Canvas; 3 import android.graphics.Paint; 4 import android.util.Log; 5 import android.view.View; 6 7 import com.facebook.react.uimanager.PixelUtil; 8 9 public class CircleView extends View { 10 private final String TAG = "CircleView"; 11 private Paint mPaint; // 画笔 12 private float mRadius; // 圆的半径 13 14 public CircleView(Context context) { 15 super(context); 16 mPaint = new Paint(); 17 mPaint.setColor(0xAA000000); 18 } 19 20 /** 21 * 设置圆的半径 22 * @param radius 23 */ 24 public void setRadius(Integer radius) { 25 /** 26 * 由于JS传过的数字是dip单位,需要转换为实际像素 27 * 使用com.facebook.react.uimanager包中的PixelUtil,进行转换 28 */ 29 mRadius = PixelUtil.toPixelFromDIP(radius); 30 invalidate(); 31 } 32 33 @Override 34 protected void onDraw(Canvas canvas) { 35 super.onDraw(canvas); 36 canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); // 画一个半径为100px的圆 37 Log.d(TAG, "绘图"); 38 } 39 }
1 import com.facebook.react.uimanager.SimpleViewManager; 2 import com.facebook.react.uimanager.ThemedReactContext; 3 import com.facebook.react.uimanager.annotations.ReactProp; 4 5 /** 6 * Created by bingmingli on 2018/6/8. 7 */ 8 9 public class CircleManager extends SimpleViewManager<CircleView> { 10 11 /** 12 * 设置js引用名 13 */ 14 @Override 15 public String getName() { 16 return "MCircle"; 17 } 18 19 /** 20 * 创建UI组件实例 21 */ 22 @Override 23 protected CircleView createViewInstance(ThemedReactContext reactContext) { 24 return new CircleView(reactContext); 25 } 26 27 /** 28 * 传输半径参数 29 */ 30 @ReactProp(name = "radius") 31 public void setRadius(CircleView view, Integer radius) { 32 view.setRadius(radius); 33 } 34 }
下面是JS部分:
circle.js
1 import React, { Component } from ‘react‘; 2 import { 3 View, 4 requireNativeComponent 5 } from ‘react-native‘; 6 7 import PropTypes from ‘prop-types‘ 8 // const RCTCircle = requireNativeComponent(‘MCircle‘, { 9 // propTypes: { 10 // radius: PropTypes.number, 11 // ...View.propTypes // 包含默认的View的属性 12 // }, 13 // }); 14 // module.exports=RCTCircle; 15 16 var iface = { 17 name: ‘MCircle‘, 18 propTypes: { 19 radius: PropTypes.number, 20 ...View.propTypes 21 }, 22 }; 23 24 module.exports = requireNativeComponent(‘MCircle‘, iface);
第三坑:PropTypes的导入方式为import PropTypes from ‘prop-types‘
第四坑:...View.propTypes这个必须有,不然自己的属性不能识别
第五坑:iface里面的name 与 requireNativeComponent的第一个参数需要一致,很多教程这里不一致,导致找不到这个原生view
App.js
1 import React, { Component } from ‘react‘; 2 import { 3 Platform, 4 StyleSheet, 5 Text, 6 View 7 } from ‘react-native‘; 8 9 import MCircle from ‘./circle‘; 10 11 const instructions = Platform.select({ 12 ios: ‘Press Cmd+R to reload,\n‘ + 13 ‘Cmd+D or shake for dev menu‘, 14 android: ‘Double tap R on your keyboard to reload,\n‘ + 15 ‘Shake or press menu button for dev menu‘, 16 }); 17 18 export default class App extends Component<Props> { 19 render() { 20 return ( 21 <View> 22 <MCircle 23 style={{width: 100, height: 100}} 24 radius={50} 25 /> 26 </View> 27 ); 28 } 29 } 30 31 const styles = StyleSheet.create({ 32 container: { 33 flex: 1, 34 justifyContent: ‘center‘, 35 alignItems: ‘center‘, 36 backgroundColor: ‘#F5FCFF‘, 37 }, 38 welcome: { 39 fontSize: 20, 40 textAlign: ‘center‘, 41 margin: 10, 42 }, 43 instructions: { 44 textAlign: ‘center‘, 45 color: ‘#333333‘, 46 marginBottom: 5, 47 }, 48 });
提醒:导入的view必须名字也一致,这不用多说了
以上是关于ReactNative如何在JS中引用原生自定义控件(rn变化太快,网上很多教程有坑,这个我研究后可用,特意分享)的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Jest 测试导入自定义原生模块的 React Native 组件?
使用 Swift 反应原生自定义 UI 组件:如何在事件中访问 reactTag