ReactNative开发——封装原生UI组件
来源:互联网 发布:.net程序员面试指南 编辑:程序博客网 时间:2024/06/03 14:26
ReactNative开发——封装原生UI组件
下文我们将制作一个可以用来显示图片的原生UI组件,这个UI组件可以随着手势放大缩小。(封装PhotoView)
PhotoView的开源地址:https://github.com/chrisbanes/PhotoView
一、引入开源库
可以PhotoView开源库作者的引用提示:
1、在 android项目根目录中的 build.gradle中加入:
allprojects {...maven { url "https://jitpack.io" }}
2、在android Moudle中的build.gralde 中加入
dependencies { .... compile 'com.github.chrisbanes:PhotoView:2.0.0' compile 'com.github.bumptech.glide:glide:4.0.0-RC0' annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC0'}
额,还要引用glide方便我们加载网络图片。
二、在Native端建立一个ViewManager。
1、我们可以直接创建一个类继承com.facebook.react.uimanager.SimpleViewManager
然后重新它的 getName
,createViewInstance
方法
public class PhotoViewManger extends SimpleViewManager<PhotoView> { private static final String TAG = "PhotoViewManger"; private static final String REACT_CLASS = "PhotoView"; private ThemedReactContext aContext; private PhotoView photoView; @Override public String getName() { return REACT_CLASS; } @Override protected PhotoView createViewInstance(ThemedReactContext reactContext) { this.aContext = reactContext; photoView = new PhotoView(reactContext); photoView.setImageResource(R.mipmap.ic_launcher); }); return photoView; }}
三、通过@ReactProp(或 @ReactPropGroup)注解来导出属性
例如:
@ReactProp(name = "imgSource")public void setSource(PhotoView photoView, String source) { Glide.with(aContext).load(source).into(photoView);}
这里声明了一个属性,属性名为imgSource
。注意:这个方法必须是public
的,其中第一个时我们createViewInstance
返回的那个View,第二个参数使我们接受的参数类型,可以为boolean
int
float
double
String
Boolean
Integer
com.facebook.react.bridge.ReadableArray
com.facebook.react.bridge.ReadableMap
。
注解中也可以设置默认值defaultInt
defaultDouble
等等。
四、创建一个ReactPackage的实现类
创建一类继承自ReactPackage,并在createViewManagers返回List中加入我们定义的ViewManager。
public class PhotoViewPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Arrays.<ViewManager>asList(new PhotoViewManger()); }}
五、在ReactNativeHost中加入我们定义的ReactPackage实现类
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 PhotoViewPackage() ); }};
六、在React Native端使用
import React from 'react';import {requireNativeComponent, View} from 'react-native';let iface = { name: 'PhotoView', propTypes: { imgSource: React.PropTypes.string, ...View.propTypes //支持View组件的所有属性 }}var RCTPhotoView = requireNativeComponent('PhotoView', iface);export default RCTPhotoView;
核心方法:requireNativeComponent('PhotoView', iface)
这个方法可以接收三个参数:
第一个参数:stirng 类型,对应我们Native中定义的那个ViewManager#getName的返回值。
第二个参数:{name?:string,displayName?:string,propTypes:Object}类型,或者ReactClass类型
第三个参数:{nativeOnly?:Object} 类型,用来解决 一些特殊的属性,想从原生组件中导出,但是又不希望它们成为对应React封装组件的属性
封装好之后,我们就可以想使用ReactNative组件那样使用了
class Main extends Component { render() { return ( <View style={{flex: 1}}> <PhotoView onChange={(obj) => { Alert.alert('scale',obj.nativeEvent.msg); }} style={{flex: 1, width: '100%'}} imgSource='https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1497959956050&di=d9ac82e7c9ba4fde2836510aeb2f2248&imgtype=0&src=http%3A%2F%2Fimg.tupianzj.com%2Fuploads%2Fallimg%2F160309%2F9-16030Z92137.jpg' /> </View> ); }}AppRegistry.registerComponent('HybridUsage', () => Main);
七、事件
下面我们将演示怎么将Native UI 组件的事件导出。
我以导出PhotoView
的OnScaleChangeListener
为例
1、给native发送事件
photoView.setOnScaleChangeListener(new OnScaleChangedListener() { @Override public void onScaleChange(float scaleFactor, float focusX, float focusY) { WritableMap map = Arguments.createMap(); map.putInt("target", photoView.getId()); map.putString("msg", "ScaleInfo: scaleFactor:" + scaleFactor + ",focusX" + focusX + ",focusY" + focusY); /** * {@link com.facebook.react.uimanager.UIManagerModuleConstants} */ aContext.getJSModule(RCTEventEmitter.class).receiveEvent( photoView.getId(), "topChange", map ); } });
核心方法:
aContext.getJSModule(RCTEventEmitter.class).receiveEvent( photoView.getId(), "topChange", map);
这里第一个参数NavieUi组件的getId,第二个参数为事件的名称 我们传入”topChange”实际对应的的ReactNative端的”onChange”函数
我们可以查看com.facebook.react.uimanager.UIManagerModuleConstants
查看对应关系。
2、ReactNative端
我们给属性多设置一个onChange
方法,用来接受Native UI组件的回调
let iface = { name: 'PhotoView', propTypes: { imgSource: React.PropTypes.string, //回调 onChange: React.PropTypes.func, ...View.propTypes //支持View组件的所有属性 }}var RCTPhotoView = requireNativeComponent('PhotoView', iface);export default RCTPhotoView;
3、使用
/** * Created by blueberry on 6/20/2017. */import React, {Component} from 'react';import {AppRegistry, StyleSheet, View, Text, requireNativeComponent, TextInput, Button, Alert} from 'react-native';import PhotoView from './PhotoView';class Main extends Component { render() { return ( <View style={{flex: 1}}> <PhotoView onChange={(obj) => { Alert.alert('scale',obj.nativeEvent.msg); }} style={{flex: 1, width: '100%'}} imgSource='https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1497959956050&di=d9ac82e7c9ba4fde2836510aeb2f2248&imgtype=0&src=http%3A%2F%2Fimg.tupianzj.com%2Fuploads%2Fallimg%2F160309%2F9-16030Z92137.jpg' /> </View> ); }}AppRegistry.registerComponent('HybridUsage', () => Main);
另外Native端还有一种方法,也可以导出事件
对应的java代码:
photoView.setOnScaleChangeListener(new OnScaleChangedListener() { @Override public void onScaleChange(float scaleFactor, float focusX, float focusY) { // 这里又2中方案 : 1. aContext.getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(new ReactScaleChangeEvent(photoView.getId(), "ScaleInfo: scaleFactor:" + scaleFactor + ",focusX" + focusX + ",focusY" + focusY));// // 2.// WritableMap map = Arguments.createMap();// map.putInt("target", photoView.getId());// map.putString("msg", "ScaleInfo: scaleFactor:" + scaleFactor// + ",focusX" + focusX + ",focusY" + focusY);//// /**// * {@link com.facebook.react.uimanager.UIManagerModuleConstants}// */// aContext.getJSModule(RCTEventEmitter.class).receiveEvent(// photoView.getId(), "topChange", map// ); } });/** * {@link com.facebook.react.uimanager.UIManagerModuleConstants} */class ReactScaleChangeEvent extends Event<ReactScaleChangeEvent> { public static final String EVENT_NAME = "topChange"; //会被映射为onChange 具体映射关系参见 UIManagerModuleConstants.java private String msg; ReactScaleChangeEvent(int viewId, String msg) { super(viewId); this.msg = msg; } @Override public String getEventName() { return EVENT_NAME; } @Override public void dispatch(RCTEventEmitter rctEventEmitter) { rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); } private WritableMap serializeEventData() { WritableMap map = Arguments.createMap(); map.putInt("target", getViewTag()); map.putString("msg", this.msg); return map; }}
示例代码地址:
https://github.com/blueberryCoder/RNDemo/blob/master/HybridUsage/android/app/src/main/java/com/hybridusage/PhotoViewManger.java
- ReactNative开发——封装原生UI组件
- React Native 封装原生UI组件(iOS)
- React Native封装原生UI组件
- ReactNative开发——自定义组件
- ReactNative开发——View组件
- ReactNative开发——Text组件
- ReactNative开发——组件的引用
- ReactNative开发——组件的生命周期
- ReactNative开发——滑动组件
- ReactNative 组件封装---Modal
- 基于原生HTML的UI组件开发
- ReactNative(五)——组件封装、样式定义、父子组件通过props传值
- React Native之原生UI组件封装---适配Android
- React Native之原生UI组件封装---适配Android
- ReactNative开发——可触摸组件类型
- 原生UI组件
- vue.js原生组件化开发——父子组件
- ReactNative——fetch封装新姿势
- linux 网络编程 Tcp文件服务器
- CSS Grid布局:图解网格布局中术语三
- Mysql模糊查询like效率,以及更高效的写法
- axios的post
- CSS 布局的未来:网格布局 · 张小伦爱学习
- ReactNative开发——封装原生UI组件
- 一小时搞定DIV+CSS布局-固定页面开度布局
- 【修真院“善良”系列之十】初级Java程序员的学习路线
- 【JZOJ5153】树形图求和 题解
- DIV CSS绝对定位布局案例 position布局实例
- 斯坦福大学Andrew Ng教授主讲的《机器学习》公开课观后感
- CSS布局十八般武艺都在这里了
- Java实现简单的RPC框架
- java jar 自启动 centos7 systemctl