React Native十五:原生UI组件

来源:互联网 发布:淘宝众筹怎么做 编辑:程序博客网 时间:2024/05/16 15:45
在如今的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;
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,
                                                             '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,
                                                           }});
二、事件
现在我们已经知道了怎么导出一个原生视图组件,并且我们可以在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,  StyleSheet,  Text,  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,    justifyContent: 'center',  },  hello: {    fontSize: 20,    textAlign: 'center',    margin: 10,  },});AppRegistry.registerComponent('AwesomeProject', () => 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,具体如何升级请查看《版本升级》章节。
1 0
原创粉丝点击