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方法,在里面返回我们实现的子类RTCWebViewpublic 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
- React Native十五:原生UI组件
- Android React Native使用原生UI组件
- React Native使用指南-原生UI组件
- React Native 封装原生UI组件(iOS)
- React Native封装原生UI组件
- React Native使用原生UI组件
- React Native 使用原生 UI 组件
- React Native调用原生UI组件
- react native 调用原生UI组件
- React Native之原生UI组件封装---适配Android
- React-Native系列Android自定义原生UI组件
- React Native之原生UI组件封装---适配Android
- React Native 原生UI组件的基本使用
- React-native 调用原生组件
- React Native使用原生组件
- React Native调用原生组件
- React Native 原生平台调用React Native组件
- 【稀饭】react native 实战系列教程之自定义原生UI组件
- react的初始化阶段
- 不是技术牛人,如何拿到国内IT巨头的Offer
- 堆栈程序理解
- BZOJ 2427: [HAOI2010]软件安装
- Android 的内存泄漏
- React Native十五:原生UI组件
- 欢迎使用CSDN-markdown编辑器
- 动态获取时间
- Qt Creator设置代码自动补全
- 贪心算法——Prim最小生成树
- ubuntu中kvm桥接模式设置
- 使用Docker安装HUE
- LInux 子进程创建函数fork简介
- IEC61850客户端软件IEDScout使用说明