前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React Native调用原生UI组件

React Native调用原生UI组件

作者头像
xiangzhihong
发布2018-02-06 17:28:17
1.5K0
发布2018-02-06 17:28:17
举报
文章被收录于专栏:向治洪向治洪

在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'/>
        );
    }
}

不过调用貌似有点问题。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-07-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Android原生组件封装
    • 代码实现
      • React Native实现
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档