android 使用原生UI组件

在如今的App中,已经有成千上万的原生UI部件了——其中的一些是平台的一部分,另一些可能来自于一些第三方库,而且可能你自己还收藏了很多。React Native已经封装了大部分最常见的组件,譬如ScrollView和TextInput,但不可能封装全部组件。而且,说不定你曾经为自己以前的App还封装过一些组件,React Native肯定没法包含它们。幸运的是,在React Naitve应用程序中封装和植入已有的组件非常简单。

和原生模块向导一样,本向导也是一个相对高级的向导,我们假设你已经对Android编程颇有经验。本向导会引导你如何构建一个原生UI组件,带领你了解React Native核心库中ImageView组件的具体实现。

WebView样例

创建一个ViewManager的子类。
实现createViewInstance方法。
导出视图的属性设置器:使用@ReactProp(或@ReactPropGroup)注解。
把这个视图管理类注册到应用程序包的createViewManagers里。
实现JavaScript模块。

1.创建视图管理器

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中的属性传入参数,可以定义默认值。具体可以参考官网。

2.注册视图管理器

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

3.将这个AppReactPackage添加到ReactInstanceManager实例中去

 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())

4.实现对应的JavaScript模块

'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);

添加事件

下面都是固定格式

1. 继承webview 进行重写

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);
    }
}

2.webview.js

'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

3.调用

import MGWebView from './js/WebView';
class HelloWorld extends React.Component {
  render() {
    return (
   
          "https://www.baidu.com" style={{width:400,height:400}}>
     
    )
  }
}

4.结果

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

你可能感兴趣的:(react,android)