在如今的App中,已经有成千上万的原生UI部件了——其中的一些是平台的一部分,另一些可能来自于一些第三方库,而且可能你自己还收藏了很多。React Native已经封装了大部分最常见的组件,譬如ScrollView和TextInput,但不可能封装全部组件。而且,说不定你曾经为自己以前的App还封装过一些组件,React Native肯定没法包含它们。幸运的是,在React Naitve应用程序中封装和植入已有的组件非常简单。
和原生模块向导一样,本向导也是一个相对高级的向导,我们假设你已经对Android编程颇有经验。本向导会引导你如何构建一个原生UI组件,带领你了解React Native核心库中ImageView组件的具体实现。
创建一个ViewManager的子类。
实现createViewInstance方法。
导出视图的属性设置器:使用@ReactProp(或@ReactPropGroup)注解。
把这个视图管理类注册到应用程序包的createViewManagers里。
实现JavaScript模块。
public class ReactWebViewManager extends SimpleViewManager {
public static final String REACT_CLASS = "MGWebView";
@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");
}
}
说明:
1.需要使用原生组件,不管是第三方组件还是系统原生组件,需要定义以上视图管理类(类名随便起),它继承自SimpleViewManager。WebView是这个视图管理类所管理的对象类型,这就是原生的UI组件视图。getName方法返回的名字会用于在JavaScript端引用这个原生视图类型,和JavaScript注册的名字相同。
2.通过@ReactProp(或@ReactPropGroup)注解来导出属性的设置方法,用于js中的属性传入参数,可以定义默认值。具体可以参考官网。
public class AppReactPackage implements ReactPackage {
@Override
public List createNativeModules(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List> createJSModules() {
return Collections.emptyList();
}
@Override
public List createViewManagers(ReactApplicationContext reactContext) {
return Arrays.asList(
new ReactWebViewManager());
}
}
说明:
1.自定义以上类AppReactPackage(类名随便起),利用createViewManagers方法注册上面定义的视图管理器ReactWebViewManager
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new AppReactPackage())
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "reactandroid", null);
setContentView(mReactRootView);
说明:
1.首先会原生Android嵌入React Native
2.添加.addPackage(new AppReactPackage())
'use strict';
import { PropTypes } from 'react';
import { requireNativeComponent, View } from 'react-native';
var iface = {
name: 'MGWebView',
propTypes: {
url: PropTypes.string,
html: PropTypes.string,
...View.propTypes,
},
};
module.exports = requireNativeComponent('MGWebView', iface);
5.##js中调用MGWebView
'use strict';
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
var MGWebView=require('./js/MGWebView');
class HelloWorld extends React.Component {
render() {
return (
"https://www.baidu.com" style={{fix:1}}>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
AppRegistry.registerComponent('reactandroid', () => HelloWorld);
下面都是固定格式
public class MGWebView extends WebView{
public MGWebView(Context context) {
super(context);
}
public MGWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int 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);
}
}
'use strict';
import { PropTypes } from 'react';
import { requireNativeComponent, View } from 'react-native';
import React from 'react';
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 this.props} onChange={this._onChange} />;
}
}
WebView.propTypes = {
url: PropTypes.string,
html: PropTypes.string,
onScrollChange: PropTypes.func,
...View.propTypes,
};
var MGWebView = requireNativeComponent('MGWebView', WebView,{
nativeOnly: {onChange: true}
});
module.exports = WebView
import MGWebView from './js/WebView';
class HelloWorld extends React.Component {
render() {
return (
"https://www.baidu.com" style={{width:400,height:400}}>
)
}
}
E/TAG: onScrollChanged
E/TAG: onScrollChanged
E/TAG: onScrollChanged
E/TAG: onScrollChanged
E/TAG: onScrollChanged
E/TAG: onScrollChanged
E/TAG: onScrollChanged
E/TAG: onScrollChanged
E/TAG: onScrollChanged
E/TAG: onScrollChanged