React Native调用原生UI组件
在React Native 中,其已经将几个常用的原生组件进行了封装,但是并不是所有系统的原始组件都被封装了,因此有时候我们不得不自己动手封装一下,从而能够使用那些React Native没有为我们封装的原生组件。为了方便讲解,我们选择第一个第三方库kenburnsview来讲解,kenburnsview是一个可以让图片在在页面移动或者放大缩小的库。
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'/>
);
}
}
不过调用貌似有点问题。
- Unity3D学习笔记第一课
- Extjs4处理后台json数据中日期和时间的方法
- 机器学习:Python测试线性可分性的方法
- Java 机器学习库Smile实战(一)SVM
- 交易Transaction【区块链生存训练】
- 马尔可夫链文本生成的简单应用:不足20行的Python代码生成鸡汤文
- 最长递增子序列
- dedecms批量删除文档关键词可以吗
- 【学术】在C ++中使用TensorFlow训练深度神经网络
- 一个canonical标签解决site不在首页的问题
- 由一道面试题来了解进程间的通信
- 【教程】简单教程:用Python解决简单的水果分类问题
- 通过html<map>标签给图片加链接
- Windows下安装Scikit-Learn
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法