RN如何使用原生的AndroidUI组件

我们做RN开发的时候,如果RN的组件不能满足要求,或者一个功能写好的android组件,直接在RN上使用,想嗲用RN的组件一样使用,这个时候就需要今天讲的知识了------自定义rn原生的android UI组件

比如我们想实现个视频播放器,但是这个播放器是android里面特定开发的,想把这个播放器给RN中以组件Component的形式调用,来我们就来看这个例子,这个例子只实现了简单的播放和暂停

一、android端代码

RNPlayer

public class RNPlayer extends FrameLayout {private PlayerView playerView;public RNPlayer(Context context) {super(context);//addTextView();post(new Runnable() {@Overridepublic void run() {playerView=new PlayerView(getContext());FrameLayout.LayoutParams lp=new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);playerView.setLayoutParams(lp);addView(playerView);}});}public void startPlayer(String url){if (playerView!=null){playerView.startPlayer(url);}}public void destory(){if (playerView!=null){playerView.destory();}}public void stopPlayer(){if (playerView!=null){playerView.stopPlayer();}}
}

PlayerView

public class PlayerView extends FrameLayout {private QySurfaceView streamView;private CustomView customView;private int playerId;private  boolean isPlaying = false;public PlayerView(@NonNull Context context) {super(context);addPlayerView();}public PlayerView(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);addPlayerView();}public CustomView getCustomView() {return customView;}public void addPlayerView(){streamView = new QySurfaceView(getContext());FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);streamView.setLayoutParams(lp);addView(streamView);customView = new CustomView(getContext());customView.setLayoutParams(lp);addView(customView);setBackgroundColor(Color.BLACK);}public void startPlayer(String url){if (TextUtils.isEmpty(url))return;playerId = NativeApi.getInstance().createPlayer(url,"");if (playerId <= 0 || isPlaying){return;}streamView.setVisibility(VISIBLE);customView.setVisibility(VISIBLE);isPlaying = true;streamView.start(playerId);}public void stopPlayer(){if (isPlaying){NativeApi.getInstance().stopPlay(playerId);isPlaying = false;streamView.setVisibility(INVISIBLE);customView.setVisibility(INVISIBLE);}}public void destory(){if (isPlaying){streamView.destory();isPlaying = false;streamView.setVisibility(INVISIBLE);customView.setVisibility(INVISIBLE);}}
}

QySurfaceView

public class QySurfaceView extends SurfaceView {public static final String TAG="QySurfaceView";private SurfaceHolder holder;private int  playerId ;public QySurfaceView(Context context) {super(context);init();}public QySurfaceView(Context context, AttributeSet attrs) {super(context, attrs);init();}public QySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init(){holder = getHolder();holder.addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(SurfaceHolder surfaceHolder) {Log.d(TAG,"surfaceCreated");holder = surfaceHolder;}@Overridepublic void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {Log.d(TAG,"i:"+i+ " i1:"+i1 + " i2:"+i2);}@Overridepublic void surfaceDestroyed(SurfaceHolder surfaceHolder) {destory();}});}public void start(int id){this.playerId = id;Log.d(TAG,"start() playerId="+playerId);if (holder==null)throw new RuntimeException("holder is null");NativeApi.getInstance().startPlay(playerId,holder.getSurface());}public void destory(){Log.d(TAG,"destory");NativeApi.getInstance().stopPlay(playerId);NativeApi.getInstance().closePlayer(playerId);}}

最后NativeApi 是c++的native 方法,视频的拉去,编解码 都在这里做的,就不看了

上面的代码很简单,做过Android的同学都可以看懂,就是定义了一个android播放器视图

接下来我们来看Android和RN部分的代码

为了你module中可以引用到RN的库先导入:

implementation "com.facebook.react:react-native:+"

RNVGManager

//泛型里面是之前那个RNPlayer的类
public class RNVGManager extends ViewGroupManager<RNPlayer> {private static final String MANAGER_NAME = "PlayerView";@Nonnull@Overridepublic String getName() {//这个是RN代码那边获取组件时候需要的名字,要一致,自己随便写,我们先记住这个PlayerViewreturn MANAGER_NAME;}@Nonnull@Overrideprotected RNPlayer createViewInstance(@Nonnull ThemedReactContext themedReactContext) {//返回RNPlayerRNPlayer reactViewGroup = new RNPlayer(themedReactContext);return reactViewGroup;}//这个关键了//这个是RN那边的组将 需要的props,到时候组件可以引用这个url的props了@ReactProp(name = "url")//第一个参数一定是RNPlayer,就是这个播放器的对象,第二个是propspublic void setUrl(RNPlayer player,String url){//下面就是自己对应的实现if (!TextUtils.isEmpty(url)){if (url.equals("-1")){//-1 就停止player.stopPlayer();}else{//播放player.startPlayer(url);}}}}

PlayerPackage

//android要把自己的东西 给RN调用,必须通过ReactPackage 来实现,
//最后在Application中添加这个
public class PlayerPackage implements ReactPackage {@Nonnull@Overridepublic List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {List<NativeModule> moduleList=new ArrayList<>();moduleList.add(new PlayerModule(reactContext));return moduleList;}@Nonnull@Overridepublic List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactApplicationContext) {//这个就把上面那个RNVGManager 返回去了List<ViewManager> viewManagers=new ArrayList<>();viewManagers.add(new RNVGManager());return viewManagers;}
}

MainApplication

public class MainApplication extends NgnApplication implements ReactApplication {private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {@Overridepublic boolean getUseDeveloperSupport() {return BuildConfig.DEBUG;}@Overrideprotected List<ReactPackage> getPackages() {return Arrays.<ReactPackage>asList(new MainReactPackage(),new AVPackage()//添加刚刚那个包,new PlayerPackage());}@Overrideprotected String getJSMainModuleName() {return "index";}};@Overridepublic ReactNativeHost getReactNativeHost() {return mReactNativeHost;}@Overridepublic void onCreate() {super.onCreate();SoLoader.init(this, /* native exopackage */ false);}
}

这样Android这的代码就完成了

我们继续看下RN的代码如何写

RN:

Player.js

我们首先定义一个Player组件

import React, {Component} from 'react';
import {requireNativeComponent, View, ViewPropTypes} from 'react-native';
import PropTypes from 'prop-types'export default  class Player extends Component
{constructor(props) {super(props);}_assignRoot = (component) => {this._root = component;};setNativeProps(nativeProps) {//调用这个组件的setNativeProps方法,设置android原生定义个propsthis._root.setNativeProps(nativeProps);};startPlayer = (urlvalue) =>{//调用了android控件那边定义的url  propsthis.setNativeProps({url:urlvalue});}stop = () =>{//停止就传-1,都是前面定义好的this.setNativeProps({url:"-1"});}render (){const nativeProps = Object.assign({}, this.props);Object.assign(nativeProps, {});return (<PlayerViewref={this._assignRoot}{...nativeProps}/>);}}
Player.PropTypes = {//这个是props 是一个属性url:PropTypes.string,startPlayer:PropTypes.func,//方法类型stopPlayer:PropTypes.func,//方法类型//让这个组件继承View组件的propsscaleX: PropTypes.number,scaleY: PropTypes.number,translateX: PropTypes.number,translateY: PropTypes.number,rotation: PropTypes.number,...ViewPropTypes,}//从android 或者ios那边 获取PlayerView这个控件,这个名字就是之前android 那边播放器 定义的名字
//把这个PlayerView 添加到Player
//Player 里面的render里渲染就是返回的PlayerView
const PlayerView = requireNativeComponent('PlayerView', Player)

好了我们可以跟其他的组件一样开始愉快的使用了,使用的组件是

App.js

下面这个是一个项目的Demo,里面就有Player导入,其他的不用管就看Player那里

import Player from ‘./Player.js’,以及使用

/*** Sample React Native App* https://github.com/facebook/react-native** @format* @flow*/import React, {Component} from 'react';
import {props,Button, NativeModules, Platform, StyleSheet, Text, View,Alert,TextInput} from 'react-native';
import { DeviceEventEmitter } from 'react-native';
import Player from './Player.js'//导入avsdk 调用android代码
const avsdk =  NativeModules.avmodule;
const playersdk =  NativeModules.avplayer;
var username1 = "023100003"
var password1 = "023100002"var username2 = "023100001"
var password2 = "112233"var domain = "119.91.140.155"
var host = "119.91.140.155"
var port = 5060const buttonClick1 = () => {//String domain,String serverHost,int port,String userid,String password//很多的方法可以同步返回值var result=avsdk.register(domain,host,port,username1,password1)if(result == 1){avsdk.toast("注册成功");}};
const buttonClick2 = () => {var result=avsdk.register(domain,host,port,username2,password2)if(result == 1){avsdk.toast("注册成功");}};
const buttonClick_room1 = () => {var result=avsdk.makeCall("023200001");avsdk.toast(result?"进入成功":"进入失败");};
const buttonClick_room2 = () => {var result=avsdk.makeCall("023200002");avsdk.toast(result?"进入成功":"进入失败");};class App extends Component{/*public static final String SESSION_EVENT="session_event";public static final String REGISTER_EVENT="register_event";public static final String ERROR="error";*/componentDidMount(){//监听事件名为onevent的事件this.eventProxy=DeviceEventEmitter.addListener('session_event',this.onEventResult);//监听事件名为onerror的事件this.registerProxy=DeviceEventEmitter.addListener('register_event',this.onRegisterResult);//监听事件是error的事件this.errorProxy=DeviceEventEmitter.addListener('error',this.onErrorResult);}onEventResult = (e)=> {//avsdk.toast('event:'+e)}onRegisterResult = (e)=> {//avsdk.toast('register:'+e)}onErrorResult = (e)=> {//avsdk.toast('error:'+e)}componentWillUnmount(){this.eventProxy.remove();this.registerProxy.remove();this.errorProxy.remove();}render() {return (<View style={styles.container}><Text style={styles.text}>domain:{domain}  host:{host}  port:{port}</Text><Text style={styles.text}>用户一:{username1}  {password1}</Text><Text style={styles.text}>用户二:{username2}  {password2}</Text><Button title={"用户一注册"} onPress={buttonClick1}/><Button title={"用户二注册"}  onPress={buttonClick2}/><Button title={"进入会议室023200001"}  onPress={buttonClick_room1}/><Button title={"进入会议室023200002"}  onPress={buttonClick_room2}/><Button title={"挂断"}  onPress={() =>{var result=avsdk.hangUpCall();avsdk.toast(result==1?"挂断成功":"关断失败");}}/><Button title={"扬声器和听筒的切换"}  onPress={() =>{avsdk.toggleSpeakerphone();}}/><Button title={"是否已经注册"}  onPress={() => {avsdk.isRegister()//avsdk.toast(avsdk.isRegister()+"") ;}}/><Button title={"销毁"}  onPress={() => {avsdk.destory()avsdk.toast("已经销毁");}}/><Button title={"跳转视频"}  onPress={() => {playersdk.startPlayer("http://119.91.140.155:18080/live/0AF00011/0000/0001.flv");}}/>
//播放<Button title={"播放RN组件Player"}  onPress={() => {var url = "http://119.91.140.155:18080/live/0AF00011/0000/0001.flv"var uu="/storage/emulated/0/DCIM/Camera/t.mp4"//alert(this.myPlayer.props);// this.myPlayer.props.url(url);this.myPlayer.startPlayer(url);}}/>
//停止<Button title={"停止播放"}  onPress={() => {this.myPlayer.stop();}}/><Player ref={(view) => this.myPlayer = view} style={styles.playerStyle//url="http://119.91.140.155:18080/live/0AF00011/0000/0001.flv"  }></Player></View>);}
}const styles = StyleSheet.create({playerStyle:{width:200,height:100,},buttomStyle:{backgroundColor:'blue',width:100,height:500,marginTop:20,},text: {flexDirection:'column',backgroundColor: '#F5FCFF',height:50,fontSize:19},container: {flex: 1,flexDirection:'column',backgroundColor: '#F5FCFF',marginVertical:10},welcome: {fontSize: 20,textAlign: 'center',margin: 10,},instructions: {textAlign: 'center',color: '#333333',marginBottom: 5,},
});
export default App

好了,RN中使用android的UI组件的使用过程就介绍完了,如果你觉得还不错,能够帮助到你,就点个赞吧~~~

RN如何使用原生的AndroidUI组件相关推荐

  1. RN 封装 Android原生组件

    RN 封装 Android原生组件 背景 当在React Native暂时未提供部分原生功能或者模块,我们需要复用部分原生代码时,比如复用一个原生方法,此时就需要将原生方法进行封装,暴露出一个接口来让 ...

  2. RN 原生模块及组件入门

    前段时间,由于业务的需求,开始接触到了 RN 原生模块和组件的开发,最近刚好有一位同事也是有这方面的需求要开发就过来问我,我一时间竟然有点说不清楚,回想一下,挺多一些点已经有些模糊了,趁着现在刚过完年 ...

  3. java去掉rn,React Native删除第三方开源组件的依赖包

    最近项目即将上线,但是遇到了一个问题,安装之后第一次打开时,在有的Android手机上崩溃,之后再次运行就好了,好多Android机型都遇到这种情况,定位问题,发现是之前加载的第三方开源控件:reac ...

  4. [html] 举例说明原生的html组件有哪些?

    [html] 举例说明原生的html组件有哪些? <dialog><progress>-- 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷.欢迎 ...

  5. 原生的html组件,如何创建HTML5与原生UI组件混合的移动应用程序

    本文将介绍如何使用Trigger.io创建原生的顶部栏.标签栏.以及HTML/CSS/JavaScript的混合型移动应用程序. 以后我们将添加更多的原生UI组件到Trigger.io,但现在你只需要 ...

  6. RN与Android原生交互

    前言:最开始做RN开发的时候,没有和原生打交道,结果居然把项目做出来,后来有人问我,RN页面可以跳转到Activity页面吗?我蒙了,我想了一下为什么还要调到原生页面呢?那样就不兼容andoid和io ...

  7. vue 手动挂载组件 手动销毁组件_javascript原生手动分页组件

    上班第二天,好心烦,因为昨天情人节没情人吧~~~ 朋友圈都在虐狗,不刷了,老娘玩知乎去. 我不是天使:javascript原生自定义轮播图组件​zhuanlan.zhihu.com 我不是天使:jav ...

  8. vue 在线编辑excel表格(原生和使用组件的两种方式)

    vue 在线编辑excel表格(原生和使用组件的两种方式) top表头和left表头格式的表格 <template><div><!-- 用组件写的编辑表格 -->& ...

  9. FreeUI,一款微信原生开发UI组件库

    Free UI 轻量简洁的微信原生开发UI组件库 简介 Free UI,是一款微信原生开发的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 如果你喜欢,请给个star呗~ 个人说明 如有问题 ...

  10. RN 与android原生交互

    缘由 有时候App需要访问平台api,但在RN中没有相应的模块,或者需要你复用一些原生代码,这就需要进一步开发RN原生模块.一般用React Native开发App时会用到一些原生模块,比如:在做社会 ...

最新文章

  1. 分享一个android debug模式,出现 waiting for debugger把界面卡住,取巧的解决办法
  2. sdcard不可执行.
  3. Analog使用中的一些技巧和总结
  4. 在一个字符串寻找另一个字符串,并且输出短字符串头字母在长字符串的下标...
  5. 1.6 Dropout 正则化-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  6. 计划策略-52-没有最终装配和没有MTO的计划
  7. spring boot 中json数据处理
  8. ansible---基础
  9. spring webflow getting start
  10. 视觉SLAM笔记(17) 李代数求导与扰动模型
  11. 局域网访问提示无法访问检查拼写_关于海康视频监控异地访问设置一些细节的说明...
  12. git 解决fatal: Not a git repository
  13. 安全应急响应工作中易犯的5大错误
  14. 一套完整的 Java 线上故障排查技巧,建议收藏!
  15. JavaWeb:Tomcat、Servlet
  16. 三星:大小屏QLED和OLED两手都要抓,都要硬
  17. Kindle4rss中文rss资源推荐~
  18. 苹果计算机音频无法使用,苹果电脑没声音了怎么回事
  19. Win10安装了Office右键没有新建Word,excel,PPT等选项解决方法
  20. 成功时间管理软件推荐-DesktopCal和GTD

热门文章

  1. 内核热补丁,真的安全么?| 龙蜥技术
  2. 【LM】windows7 内部版本7601,此windows副本不是正版——已解决
  3. 关于OSPF区域划分
  4. Channel 用法
  5. ps裁剪和裁切的区别_PS图片的裁剪和裁切的含义和应用
  6. 评价页面,随手写的评价简陋模板
  7. C语言printf按二进制输出整数
  8. 2011 IT娱乐界回顾
  9. sdk 今日头条_今日头条商业SDK(激励视频)的坑
  10. 【Flutter小记10】apk 提交各大应用市场,出现armeabi与arm64 版本标识/版本号不一致无法上传审核的解决方案