ReactNative 调用Android(安卓)原生(二)——原生组件
ReactNative 调用Android 原生(一)——原生模块(一):https://blog.csdn.net/danfengw/article/details/83862623
ReactNative 调用Android 原生(一)——原生模块(二):
https://blog.csdn.net/danfengw/article/details/83901889
这是demo链接:https://github.com/danfengfirst/VisitAndroid
先说下我遇到的坑:
原本学完React Native调用原生模块我觉得挺顺利的,也挺容易理解的,觉得调用Android原生组件也是不成问题,应该挺快的,结果React Native 调原生组件一直不显示,在网上找了好多文章对比看,觉得自己代码、步骤都没有问题,调用控件不显示的原因文章末尾跟代码的注释里面我都将说明,免得有跟我一样入坑的!
步骤
1、继承SimpleViewManager
2、实现ReactPackage
3、向MainApplication添加ReactPackage
4、RN中导出View
5、使用导出的View
使用
如果你看过ReactNative 调用Android 原生(一)——原生模块(一)、(二)就很熟悉这个流程了,下面这个Demo是个倒计时的效果
1、继承SimpleViewManager,
(1)getName()返回的名字在RN中将被用到
(2) @ReactProp(name = “start”) 中@ReactProp注解用于定义方法,name = "start"中的start就是RN中导出的View可以使用的属性名
public class TestUI extends SimpleViewManager { @Override public String getName() { return "TimerView"; } @Override protected TimerView createViewInstance(ThemedReactContext reactContext) { return new TimerView(reactContext); } @ReactProp(name = "start") public void startTimer(TimerView timerView, Integer totalCount) { timerView.startTimer(totalCount); }}
补充:
public class TimerView extends LinearLayout { private Timer mTimer; private TimerTask mTimerTask; private TextView mTimerTv; private Context mContext; private int mCount; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); mTimerTv.setText(mCount + ""); int w = MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY); int h = MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY); measure( w, h); layout(getLeft(), getTop(), getRight(), getBottom()); } }; public TimerView(Context context) { this(context,null); } public TimerView(Context context, @Nullable AttributeSet attrs) { super(context); init(context); } private void init(Context context) { mContext = context; //布局的话随便加载 View view = LayoutInflater.from(context).inflate(R.layout.timer_view, this); view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); mTimerTv = view.findViewById(R.id.timer_tv); mTimerTv.setText(10 + ""); }//调用该方法,开始倒计时 public void startTimer(int totalcount) { mCount = totalcount; mTimerTv.setText(totalcount + ""); mTimer = new Timer(); mTimerTask = new TimerTask() { @Override public void run() { if (mCount >= 0) { --mCount; mHandler.sendEmptyMessage(0); } else { if (mTimer != null) { mTimer.cancel(); mTimer = null; } } } }; mTimer.schedule(mTimerTask, 0, 1000); } }
2、实现ReactPackage
public class TestPackages implements ReactPackage { @Override public List createNativeModules(ReactApplicationContext reactContext) { List nativeModules = new ArrayList<>(); nativeModules.add(new TestModules(reactContext)); return nativeModules; } @Override public List createViewManagers(ReactApplicationContext reactContext) { return Arrays.asList( new TestUI() ); }}
3、向MainApplication添加ReactPackage
public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), new TestPackages() ); } @Override protected String getJSMainModuleName() { return "index"; } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); }}
4、RN中导出View
这里就是坑了,必须写style并设置宽高,否则不显示
属性名:start对应上面的
import React, {Component} from 'react';import PropTypes from 'prop-types';import { requireNativeComponent, View} from 'react-native';//Android 原生View 映射成AndroidTimerView,导出为NativeTimerViewconst AndroidTimerView = requireNativeComponent('TimerView', NativeTimerView);export default class NativeTimerView extends Component { static propTypes = { stimer: PropTypes.number, }; render() { return }}
5、使用导出的View
如果你在第4步中没有设置style 在这里对NativeTimerView设置style的宽高,运行后仍然会什么都不显示,因此必须在第4步中设置宽高
export default class App extends Component { constructor() { super(); this.state = { name: 'To get started, edit App.js', sendEvent: 'Send Event' } } toast = () => { let obj = { id: 1, name: "xiaohong" }; NativeModules.TestModules.Toasts(obj); }; toastFinishCallback = () => { NativeModules.TestModules.ToastFinished("调用了原生并带有回调", (result) => { this.setState({ name: result.name }); }); }; sendEvent = () => { NativeModules.TestModules.sendEvent(); }; componentWillMount() { DeviceEventEmitter.addListener('sendEvent', (e: Event) => { this.setState({ sendEvent: e.name }); }) }; startActivity = () => { NativeModules.TestModules.startActivity(); }; render() { return ( Welcome to React Native! {this.state.name} {this.state.sendEvent} 点击开启activity ); }}const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, },});
总结
我的之前显示不出来就是因为我在第5步设置的宽高,而没有在第4步设置宽高,结果就一直显示不出来,希望不要有人再犯我这样的错误了。
更多相关文章
- Android】获取Mac地址
- android ndk环境配置
- [摘]android:windowSoftInputMode属性使用
- android webService
- Android(安卓)Studio加速
- android的四大组件及其生命周期
- Android沉浸式状态栏和手机虚拟按钮不兼容冲突的
- Android(安卓)slidingmenu详解 优化侧滑
- android语音搜索结果显示页实现