React Native调用原生UI组件
2017-07-03 11:33
309 查看
在React Native 中,其已经将几个常用的原生组件进行了封装,但是并不是所有系统的原始组件都被封装了,因此有时候我们不得不自己动手封装一下,从而能够使用那些React Native没有为我们封装的原生组件。为了方便讲解,我们选择第一个第三方库kenburnsview来讲解,kenburnsview是一个可以让图片在在页面移动或者放大缩小的库。
首先,需要继承 SimpleViewManager 这个泛型类,和原生模块类似,需要重写 getName() 方法,将UI组件名称暴露给javascript层,接着需要重写 createViewInstance 方法,在里面返回需要使用的原生UI组件的实例。
2,暴露接口给javascript层调用
然后,就是暴露一些必要属性给javascript层,为了简单起见,我们这里只暴露两个属性,一个是 url ,一个是 html ,一旦javascript层设置了url,就会加载一个网页,而一旦设置了html,则会去加载这段html,而属性的暴露是使用注解。
为了方便,提供对应的set方法,之后在set方法中处理UI的更新操作。
首先新建一个RN项目,使用Anroid Studio开的Android项目,在build.gradle中添加kenburnsview库。
编写原生KenBurnsViewManager类,主要封装KenBurnsView的相关逻辑。代码如下:
实现ReactPackage接口,在createNativeModules函数中添加我们自定义的模块。该类的基本作用就是把继承的类的方法注册到JS里。相关代码如下:
熟悉原生模块的开发人员都知道,新建一个组件需要向系统注册。添加AppReactPackage 到ReactInstanceManager的实例中去,这里需要向MainActivity注册我们新建的组件(这是老版本的写法,新版本在Application注册)。MainActivity代码如下:
不过需要注意的是0.41版本之后,注册组件的方法改到了Application。在Application中找到getPackages方法,然后加如下代码。
然后在Android中调用:
不过调用貌似有点问题。
Android原生组件封装
1,继承SimpleViewManager,返回UI组件实例首先,需要继承 SimpleViewManager 这个泛型类,和原生模块类似,需要重写 getName() 方法,将UI组件名称暴露给javascript层,接着需要重写 createViewInstance 方法,在里面返回需要使用的原生UI组件的实例。
2,暴露接口给javascript层调用
然后,就是暴露一些必要属性给javascript层,为了简单起见,我们这里只暴露两个属性,一个是 url ,一个是 html ,一旦javascript层设置了url,就会加载一个网页,而一旦设置了html,则会去加载这段html,而属性的暴露是使用注解。
为了方便,提供对应的set方法,之后在set方法中处理UI的更新操作。
代码实现
首先看一下效果:首先新建一个RN项目,使用Anroid Studio开的Android项目,在build.gradle中添加kenburnsview库。
compile 'com.flaviofaria:kenburnsview:1.0.7'
编写原生KenBurnsViewManager类,主要封装KenBurnsView的相关逻辑。代码如下:
package com.rndemos; import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import android.util.Log; import android.webkit.WebView; import android.webkit.WebViewClient; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.annotations.ReactProp; import com.flaviofaria.kenburnsview.KenBurnsView; import java.io.InputStream; /** * Created by xiangzhihong on 2017/7/2. * React Native调用原生的Webiew组件 */ public class KenBurnsViewManager extends SimpleViewManager<KenBurnsView> { public static final String REACT_CLASS = "KenBurnsView"; private ThemedReactContext mContext=null; @Override public String getName() { return REACT_CLASS; } @Override protected KenBurnsView createViewInstance(ThemedReactContext reactContext) { mContext=reactContext; KenBurnsView kView= new KenBurnsView(reactContext); try { InputStream in=mContext.getAssets().open("shanghai.png"); Drawable drawable=Drawable.createFromStream(in,null); kView.setImageDrawable(drawable); }catch (Exception e){ e.printStackTrace(); } return kView; } @ReactProp(name = "imageSource") public void setSource(KenBurnsView view,@Nullable String imagePath) { try { InputStream in=mContext.getAssets().open(imagePath); Drawable drawable=Drawable.createFromStream(in,null); view.setImageDrawable(drawable); }catch (Exception e){ e.printStackTrace(); } } }
实现ReactPackage接口,在createNativeModules函数中添加我们自定义的模块。该类的基本作用就是把继承的类的方法注册到JS里。相关代码如下:
package com.rndemos; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Created by xiangzhihong on 2017/7/2. * 原生UI管理类 */ public class KenBurnsViewPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new KenBurnsViewManager()); return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } }
熟悉原生模块的开发人员都知道,新建一个组件需要向系统注册。添加AppReactPackage 到ReactInstanceManager的实例中去,这里需要向MainActivity注册我们新建的组件(这是老版本的写法,新版本在Application注册)。MainActivity代码如下:
package com.rndemos; import android.app.Application; import com.facebook.react.ReactApplication; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.ReactRootView; import com.facebook.react.common.LifecycleState; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; import java.util.Arrays; import java.util.List; import static com.facebook.react.common.ApplicationHolder.getApplication; public class MainApplication extends Application implements ReactApplication { private ReactRootView mReactRootView; private ReactInstanceManager mReactInstanceManager; 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() ); } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); initReactInstance(); } //添加的代码 //添加AppReactPackage 到ReactInstanceManager的实例中去 public void initReactInstance(){ mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModuleName("index.android") .addPackage(new MainReactPackage()) .addPackage(new AppReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); } }
不过需要注意的是0.41版本之后,注册组件的方法改到了Application。在Application中找到getPackages方法,然后加如下代码。
protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new AppReactPackage() ); }
React Native实现
接下来,我们需要在javascript层新建一个js文件(ReactWebView,区分系统的WebView)。注意,在与index.android.js相同的目录下创建。KenBurnsView类相关代码如下:import React, { Component,PropTypes } from 'react'; import { requireNativeComponent, NativeModules, View } from 'react-native'; var iface = { name: 'KenBurnsView', propTypes: { imageSource: React.PropTypes.string, ...View.propTypes }, }; module.exports = requireNativeComponent('KenBurnsView', iface);
然后在Android中调用:
var KenBurnView=require('./KenBurnsView'); let {width, height} = Dimensions.get("window"); export default class RNDemos extends Component { render() { return ( <KenBurnView style={styles.imageStyle} imageSource='http://ohe65w0xx.bkt.clouddn.com/shanghai.png'/> ); } }
不过调用貌似有点问题。
相关文章推荐
- react native学习笔记25——Android原生模块的封装与调用
- React Native 原生UI组件的基本使用
- 【react-native-0.31-iOS】封装原生组件并调用(02)
- react-native调用Android的原生方法
- React-Native调用iOS原生方法
- 在Android原生中嵌入React Native,进而React Native调用原生
- ReactNative调用OC原生
- ReactNative调用Android原生模块
- React Native之原生UI组件封装---适配Android
- react-native 调用原生模块详解
- react native js调用android原生activity
- React Native 原生平台调用React Native组件
- (八)React Native实现调用android原生java方法并实现广播的发送和接受
- React Native 原生与JS之间事件绑定注册 作用在于原生可以直接调用JS的方法
- react native结合Android原生实现调用相机或图库选择图片设置头像
- React-native 调用原生组件
- React-Native之Android:原生界面与React界面的相互调用
- react-native调用Android原生模块
- react-native 与高德地图(amap)原生互相调用