React Native 中如何使用Android的第三方控件以Android的弹幕为例

来源:互联网 发布:什么软件看爱奇艺会员 编辑:程序博客网 时间:2024/05/21 10:11

Facebook的React Native 框架让我们移动端的民工眼前一亮啊,然而有个很蛋疼的问题就是目前react native提供的API目前有很多没办法满足我们,还好万能的react native为我们提供了自定义的方法,下面我们就一步一步的实现。

     比如我们使用react native做一个弹幕。

                         

      1 首先我们在原生的Android找到先关的弹幕框架加入RN项目的Android端的依赖,这里我用的是github上的

compile 'com.github.ctiao:DanmakuFlameMaster:0.5.3'

      2 然后我们就在Android中得到弹幕视图

        

package com.danmuView;import android.content.Context;import android.graphics.Color;import android.support.annotation.Nullable;import android.view.ContextThemeWrapper;import android.view.View;import com.facebook.react.bridge.ReactMethod;import com.facebook.react.uimanager.SimpleViewManager;import com.facebook.react.uimanager.ThemedReactContext;import com.facebook.react.uimanager.annotations.ReactProp;import java.util.Random;import master.flame.danmaku.controller.DrawHandler;import master.flame.danmaku.danmaku.model.BaseDanmaku;import master.flame.danmaku.danmaku.model.DanmakuTimer;import master.flame.danmaku.danmaku.model.IDanmakus;import master.flame.danmaku.danmaku.model.android.DanmakuContext;import master.flame.danmaku.danmaku.model.android.Danmakus;import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;import master.flame.danmaku.ui.widget.DanmakuView;/** * Created by cz on 2017/1/24. */public class DanmuView extends SimpleViewManager {    private String MOUDLENAME = "DanmuView";    public static boolean showDanmaku;    static  Context context;    //弹幕控制器    public static DanmakuContext   danmakuContext;    //弹幕view    public static DanmakuView danmakuView;    @Override    public String getName() {        return MOUDLENAME;    }    @Override    protected View createViewInstance(ThemedReactContext reactContext) {        context = reactContext;        danmakuView = new DanmakuView(reactContext);        //提升绘制效率        danmakuView.enableDanmakuDrawingCache(true);        //设置回调        danmakuView.setCallback(new DrawHandler.Callback() {            @Override            public void prepared() {                //准备完成开始显示                showDanmaku = false;                danmakuView.start();                generateSomeDanmaku();            }            @Override            public void updateTimer(DanmakuTimer timer) {            }            @Override            public void danmakuShown(BaseDanmaku danmaku) {            }            @Override            public void drawingFinished() {            }        });        //创建DanmakuContext实例。DanmakuContext可以用于对弹幕的各种全局配置进行设定,如设置字体、设置最大显示行数等,这里我们设置为默认        danmakuContext = DanmakuContext.create();        //弹幕解析器        BaseDanmakuParser parser = new BaseDanmakuParser() {            @Override            protected IDanmakus parse() {                return new Danmakus();            }        };        danmakuView.prepare(parser, danmakuContext);         return danmakuView;    }    /**     * sp转px的方法。     */    public static int sp2px(float spValue) {        final float fontScale =new ContextThemeWrapper(context,0).getResources().getDisplayMetrics().scaledDensity;        return (int) (spValue * fontScale + 0.5f);    }    /**     * 向弹幕View中添加一条弹幕     *     * @param content    弹幕的具体内容     * @param withBorder 弹幕是否有边框     */    public static  void addDanmaku(String content, boolean withBorder) {        BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);        danmaku.text = content;        danmaku.padding = 5;        danmaku.textSize = sp2px(20);        danmaku.textColor = Color.WHITE;        danmaku.setTime(danmakuView.getCurrentTime());        if (withBorder) {            danmaku.borderColor = Color.GREEN;        }        danmakuView.addDanmaku(danmaku);    }    /**     * 随机生成一些弹幕内容以供测试     */    public static void generateSomeDanmaku() {        new Thread(new Runnable() {            @Override            public void run() {                while (showDanmaku) {                    int time = new Random().nextInt(300);                    String content = "弹幕--nima" + time + time;                    addDanmaku(content, false);                    try {                        Thread.sleep(time);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }).start();    }    @ReactProp(name = "needShow")    public void setShowDanmu(DanmakuView  danmakuView, @Nullable String needShow ){             if("Y".equals(needShow)){                 danmakuView.show();             }else {                 danmakuView.hide();             }    }    @ReactMethod    public  void  showDanmu(){             if(showDanmaku ){                  showDanmaku =false;                 generateSomeDanmaku();             }else {                 showDanmaku=true;                 generateSomeDanmaku();             }    }    @ReactMethod    public void destoryDanmu(){        showDanmaku = false;        if (danmakuView != null) {            danmakuView.release();            danmakuView = null;        }    }}


    3 为js端提供module接口

package com.danmuView;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.Arrays;import java.util.Collections;import java.util.List;/** * Created by cz on 2017/1/24. */public class DanmuViewReactPackage 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 DanmuView());    }}

    4我们的弹幕接口已经封装完成,接下来我们需要对我们的弹幕进行控制,先把控制的方法封装完成


package com.danmuView;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;import static com.danmuView.DanmuView.addDanmaku;import static com.danmuView.DanmuView.danmakuView;import static com.danmuView.DanmuView.generateSomeDanmaku;import static com.danmuView.DanmuView.showDanmaku;/** * Created by cz  on 2017/1/25. */public class DanmuControl extends ReactContextBaseJavaModule {    private  String MOUDLENAME = "DanmuControl";    public DanmuControl(ReactApplicationContext reactContext) {        super(reactContext);    }    @Override    public String getName() {        return MOUDLENAME;    }    @ReactMethod    public  void  showDanmu(){        if(showDanmaku ){            showDanmaku =false;            generateSomeDanmaku();        }else {            showDanmaku=true;            generateSomeDanmaku();        }    }   @ReactMethod   public void addDanmu(String content, boolean withBorder){       System.out.println("chenzhu--->添加一条弹幕");       addDanmaku(content,withBorder);   }    @ReactMethod    public void destoryDanmu(){        System.out.println("chenzhu--->销毁弹幕");        showDanmaku = false;        if (danmakuView != null) {            danmakuView.release();            danmakuView = null;        }    }}


    5将我们的控制方法暴露给我们的js端

package com.danmuView;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 com.startactivitydemo.MyIntentModule;import java.util.Arrays;import java.util.Collections;import java.util.List;/** * Created by cz  on 2017/1/25. */public class DanmuControlReactPackage implements ReactPackage {    @Override    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {        return Arrays.<NativeModule>asList(                new DanmuControl(reactContext));    }    @Override    public List<Class<? extends JavaScriptModule>> createJSModules() {        return Collections.emptyList();    }    @Override    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {        return Collections.emptyList();    }}


    6将我们自己封装的module注册到APPlocation中:

new DanmuViewReactPackage(),

new DanmuControlReactPackage(),

  7我们在js端先建一个对应的view类

/** * Created by cz on 2017/1/24. */'use strict';import { PropTypes } from 'react';import { requireNativeComponent, View } from 'react-native';var iface = {    name: 'DanmuView',    propTypes: {        needShow:  PropTypes.string ,        ...View.propTypes // 包含默认的View的属性    },};export  default module.exports = requireNativeComponent('DanmuView', iface);

然后就可以在你想是用的地方导入使用了,就和普通的控件类似的使用方法。


 8 刚才我们还Android本地封装了控制弹幕的方法使用也是非常的方便:

   

onPress={()=>{ NativeModules.DanmuControl.addDanmu("添加一条弹幕测试--------",true);}}>

直接在你需要响应的事件下面通过NativeModules点上类名在点上方法名即可。



       注意在封装modulepackg的时候返回的name要与你在js端自己定义的类名相同才能找到。

       所以理论上Android能实现的功能react native都能实现,但是却丢失了react native的最初的意图,

       不能完全的热更新了。所以大家在不到万不得已的情况下还是慎用
















1 0