加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

React Native十五:原生UI组件

发布时间:2020-12-15 03:29:29 所属栏目:百科 来源:网络整理
导读:在如今的App中,已经有成千上万的原生UI组件了——其中的一些是平台的一部分,另一些可能来自于一些第三方库,而且可能你自己还收藏了很多。React Native已经封装了大部分最常见的组件,譬如ScrollView和TextInput,但不可能封装全部组件。而且,说不定你曾
在如今的App中,已经有成千上万的原生UI组件了——其中的一些是平台的一部分,另一些可能来自于一些第三方库,而且可能你自己还收藏了很多。React Native已经封装了大部分最常见的组件,譬如ScrollView和TextInput,但不可能封装全部组件。而且,说不定你曾经为自己以前的App还封装过一些组件,React Native肯定没法包含它们。幸运的是,在React Naitve应用程序中封装和植入已有的组件非常简单。
本向导会引导你如何构建一个原生UI组件,带领你了解React Native核心库中WebView组件的具体实现。
一、WebView样例
在这个例子里,我们来看看为了让JavaScript中可以使用WevView,我们以react-native init AwesomeProject创建示例项目进行演示,项目完成目录如下:

提供原生视图很简单,主要有如下几个步骤:
1.创建一个ViewManager的子类,实现createViewInstance方法,使用@ReactProp(或@ReactPropGroup)注解;
2.创建一个把ReactPackage的子类,把这个视图管理类注册到应用程序包的createViewManagers里;
3.在MainActivity中的getPackages方法中添加ReactPackage的子类;
4.实现JavaScript模块WebView.js,index.android.js;
1.创建一个ViewManager的子类,实现createViewInstance方法,使用@ReactProp(或@ReactPropGroup)注解。
ReactWebViewManager.java类:
public class ReactWebViewManager extends SimpleViewManager<WebView>{
    public static final String REACT_CLASS = "MyWebView";

    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Override
    protected WebView createViewInstance(ThemedReactContext reactContext) {
        WebView webView= new WebView(reactContext);
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view,String url) {
                view.loadUrl(url);
                return true;
            }
        });
        return webView;
    }


    @ReactProp(name = "url")
    public void setUrl(WebView view,@Nullable String url) {
        Log.e("TAG","setUrl");
        view.loadUrl(url);
    }
    @ReactProp(name = "html")
    public void setHtml(WebView view,@Nullable String html) {
        Log.e("TAG","setHtml");
        view.loadData(html,"text/html; charset=utf-8","UTF-8");
    }
}
2.创建一个把ReactPackage的子类,把这个视图管理类注册到应用程序包的createViewManagers里;
AppReactPackage.java类
public class AppReactPackage implements ReactPackage{
    ...... ......
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(
                new ReactWebViewManager(),new ReactRTCWebViewManager());
    }
}
3.在MainActivity中的getPackages方法中添加ReactPackage的子类;
MainActivity.java类
public class MainActivity extends ReactActivity {
    ...... ...... 
    @Override
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
            new MainReactPackage(),new AppReactPackage()
        );
    }
}
4.实现JavaScript模块WebView.js,index.android.js;
WebView.js文件
var { requireNativeComponent,PropTypes  } = require('react-native');

var iface = {
  name: 'WebView',propTypes: {
    url: PropTypes.string,html: PropTypes.string,},};

module.exports = requireNativeComponent('MyWebView',iface);
index.android.js文件
import React from 'react';
import {
  AppRegistry,StyleSheet,Text,View
} from 'react-native';

var WebView=require('./WebView');

class MyAwesomeApp extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello,World</Text>
        <WebView url="https://www.baidu.com" style={{width:200,height:400}}></WebView>
      </View>
    )
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,justifyContent: 'center',hello: {
    fontSize: 20,textAlign: 'center',margin: 10,});

AppRegistry.registerComponent('AwesomeProject',() => MyAwesomeApp);
5.运行效果如下:

提示1:如果在运行的过程中,报错如下

处理1:修改该部分代码如下,module.exports = requireNativeComponent('MyWebView',iface,{nativeOnly:{
'scaleX': true,
'scaleY': true,121);"> 'testID': true,121);"> 'decomposedMatrix': true,121);"> 'backgroundColor': true,121);"> 'accessibilityComponentType': true,121);"> 'renderToHardwareTextureAndroid': true,121);"> 'translateY': true,121);"> 'translateX': true,121);"> 'accessibilityLabel': true,121);"> 'accessibilityLiveRegion': true,121);"> 'importantForAccessibility': true,121);"> 'rotation': true,121);"> 'opacity': true,121);"> 'onLayout': true,121);"> }});
二、事件
现在我们已经知道了怎么导出一个原生视图组件,并且我们可以在JS里很方便的控制它了。不过我们怎么才能处理来自用户的事件,譬如缩放操作或者拖动?当一个原生事件发生的时候,它应该也能触发JavaScript端视图上的事件,这两个视图会依据getId()而关联在一起。
下面我们就以基于原始WebView组件,在JavaScript层处理它的滚动事件,实现如下:
1.创建RTCWebView继承WebView,重写对应的事件,然后将事件传递给javascript层了
public class RTCWebView extends WebView {

    public RTCWebView(Context context) {
        super(context);
    }

    public RTCWebView(Context context,AttributeSet attrs) {
        super(context,attrs);
    }

    public RTCWebView(Context context,AttributeSet attrs,int defStyleAttr) {
        super(context,attrs,defStyleAttr);
    }

    @Override
    protected void onScrollChanged(int l,int t,int oldl,int oldt) {
        super.onScrollChanged(l,t,oldl,oldt);
        Log.e("TAG","onScrollChanged");
        WritableMap event = Arguments.createMap();
        event.putInt("ScrollX",l);
        event.putInt("ScrollY",t);
        ReactContext reactContext = (ReactContext)getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                getId(),"topChange",event);
    }
}
2.创建 ReactRTCWebViewManager,在 createViewInstance 方法,在里面返回我们实现的子类 RTCWebView
public class ReactRTCWebViewManager extends SimpleViewManager<WebView>{
    public static final String REACT_CLASS = "MyRTCWebView";
    ...... ...... 

    @Override
    protected WebView createViewInstance(ThemedReactContext reactContext) {
        WebView webView= new RTCWebView(reactContext);
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view,String url) {
                view.loadUrl(url);
                return true;
            }
        });
        return webView;
    }
    ...... ...... 
}
3.仍然再AppAppReactPackage注册实现ReactRTCWebViewManager(该部分省略);
4.JavaScript层创建RTCWebView.js文件,改造index.android.js文件:
RTCWebView.js文件
'use strict';

var React = require('react');
var ReactNative = require('react-native');
var {
  requireNativeComponent,PropTypes
} = ReactNative;


class WebView extends React.Component {
  constructor() {
    super();
    this._onChange = this._onChange.bind(this);
  }
  _onChange(event: Event) {
    if (!this.props.onScrollChange) {
      return;
    }
    this.props.onScrollChange({ScrollX:event.nativeEvent.ScrollX,ScrollY:event.nativeEvent.ScrollY});
  }
  render() {
    return <RTCWebView {...this.props} onChange={this._onChange} />;
  }
}
WebView.propTypes = {
    url: React.PropTypes.string,html: React.PropTypes.string,onScrollChange: React.PropTypes.func,};

var RTCWebView = requireNativeComponent('MyRTCWebView',WebView,{nativeOnly:{
                                                                    'scaleX': true,'scaleY': true,'testID': true,'decomposedMatrix': true,'backgroundColor': true,'accessibilityComponentType': true,'renderToHardwareTextureAndroid': true,'translateY': true,'translateX': true,'accessibilityLabel': true,'accessibilityLiveRegion': true,'importantForAccessibility': true,'rotation': true,'opacity': true,'onLayout': true,'source': true,'javaScriptEnabled': true,'domStorageEnabled': true,'injectedJavaScript': true,'userAgent': true,'onChange': true,}});
module.exports = WebView
index.android.js文件
'use strict';

import React from 'react';
import {
  AppRegistry,View
} from 'react-native';

var WebView=require('./RTCWebView');

class MyAwesomeApp extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello,World</Text>
        <WebView onScrollChange={this.onWebViewScroll} url="https://www.baidu.com" style={{width:200,height:400}}></WebView>
      </View>
    )
  }

  onWebViewScroll(event) {
      console.log(event);
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,() => MyAwesomeApp);
5.Debug Js,运行后滑动Webview,在Chrome的Develop Tools中显示如下:

提示2:如果在Debug JS的过程中,出现如下报错,导致无法正常Debug
The method /launch-chrome-devtools is deprecated. You are probably using an application created with an older CLI with the packager of a newer CLI. Please upgrade your application: https://facebook.github.io/react-native/docs/upgrading.html
处理2:尝试安装新版的Chrome浏览器版本,和react-native的版本。该demo使用的react-native版本为0.27.1-rc2,具体如何升级请查看《版本升级》章节。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读