Android React Native uses Native UI Components

Source: Internet
Author: User

Android React Native uses Native UI Components

Android React Native has encapsulated several common Native components, such as ScrollView and TextInput. However, not all original components of the system are encapsulated, so sometimes we have to encapsulate it by ourselves, so that we can use Native components that React Native has not encapsulated for us, suchWebViewThe Android implementation is not officially provided, so we can encapsulate WebView now.

I have written an article about Android React Native using Native modules. The method of using Native UI components is similar to that of using Native modules.

First, I need to inheritSimpleViewManagerThis generic class, similar to the native module, needs to be rewrittenGetName ()Method, expose the UI component name to the javascript layer, and then rewrite it.CreateViewInstanceMethod, return the instance of the native UI component we need to use in it. Here isWebView. Then, some necessary attributes are exposed to the javascript layer. For the sake of simplicity, we only expose two attributes here.Url, One isHtmlOnce a url is set on the javascript layer, a webpage is loaded. Once html is set, this html is loaded, and the exposure of attributes uses annotations, set the Annotation on the corresponding set method, and then process the UI update in the set method. For example, once the url is set, the webpage will be loaded in the setUrl. In the end, our ViewManager is like this.

 {    public static final String REACT_CLASS = "RCTWebView";    @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");    }}" data-snippet-id="ext.329b12fe654599976cf9c9288406e94b" data-snippet-saved="false" data-csrftoken="YovcNaBu-lenjyfTe3r17RMPlzP81oURyVgs" data-codota-status="done">public class ReactWebViewManager extends SimpleViewManager
  
    {    public static final String REACT_CLASS = "RCTWebView";    @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");    }}
  

Like native modules, native UI components also need to be registered to implementReactPackageInterface to register WebView.

 createNativeModules(ReactApplicationContext reactContext) {        return Collections.emptyList();;    }    @Override    public List
 
  > createJSModules() {        return Collections.emptyList();    }    @Override    public List
  
    createViewManagers(ReactApplicationContext reactContext) {        return Arrays.
   
    asList(                new ReactWebViewManager());    }}" data-snippet-id="ext.b8393c10894123c26f8f90dc93c90cac" data-snippet-saved="false" data-csrftoken="pAWMZxSf-LITk3G4glq3DgVmMEiqiHgeAN6k" data-codota-status="done">
    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()); }}
        
       
      
     
   
  
 

Set thisReactPackageAddReactInstanceManagerGo to instance

  .addPackage(new AppReactPackage())

Create a WebView. js file on the javascript layer. Enter the following content

'use strict';var { requireNativeComponent,PropTypes  } = require('react-native');var iface = {  name: 'WebView',  propTypes: {    url: PropTypes.string,    html: PropTypes.string,  },};module.exports = requireNativeComponent('RCTWebView', iface);

We can see that we only specify the attribute type in it.

So far, you can use this WebView component.

var WebView=require('./WebView');render: function() {    return (    
          
      
      );  },   

Here, we simply load the Baidu homepage. Note that the width and height of the component must be set. Otherwise, you will not see the component. The final result is as follows.

This is just the most basic way to display the original UI component, but more common is the event. For example, we need to process the WebView rolling event on the javascript layer. What should we do at this time.

At this time, we need to inherit WebView, rewrite the corresponding event, and then pass the event to the javascript layer.

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

We have rewritten the callbackOnScrollChangedMethod to ConstructWritableMapObject, pass in ScrollX and ScrollY, and then callReactContext. getJSModule (RCTEventEmitter. class). receiveEvent (getId (), "topChange", event );Events occur to the javascript layer. Note thatTopChangeCorresponding to the javascript LayerOnChangeMethod.UIManagerModuleConstantsClass.

Then we need to modifyCreateViewInstanceMethod, in which we return the child class of our implementation, just like this

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

The javascript layer also needs to be transformed to a certain extent. The final code is as follows:

;  }}WebView.propTypes = {    url: PropTypes.string,    html: PropTypes.string,    onScrollChange: PropTypes.func,};var RCTWebView = requireNativeComponent('RCTWebView', WebView,{    nativeOnly: {onChange: true}});module.exports = WebView" data-snippet-id="ext.d77348022d402d3fbda2fc1aea163b84" data-snippet-saved="false" data-csrftoken="M7VXVSiz-JsluEvZfqm_oyONV-uHimEkfOvM" data-codota-status="done">'use strict';var React = require('react-native');var {  requireNativeComponent,  PropTypes} = 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 
  
   ;  }}WebView.propTypes = {    url: PropTypes.string,    html: PropTypes.string,    onScrollChange: PropTypes.func,};var RCTWebView = requireNativeComponent('RCTWebView', WebView,{    nativeOnly: {onChange: true}});module.exports = WebView
  

Do not ask me why this is the case, because this is what is written in the official documentation. You only need to copy the code and modify it. For details, see Native UI Components.

Note thatFunction. bind (this)I am not sure about the syntax. I have not learned javascript and React since I am interested in searching on the Internet. InOnChangeIn the function, we determine if the attributeOnScrollChangeIf no value is set, return directly. Otherwise, call the set onScrollChange attribute value (the value is a function type) and pass the two parameters passed in at the Java layer to the function,{ScrollX: event. nativeEvent. ScrollX, ScrollY: event. nativeEvent. ScrollY}

Then let's call

var WebView=require('./WebView');render: function() {return (
  
   
  );},onWebViewScroll:function(event){    console.log(event);},

Wait for the WebView loading and processing, and then slide up and down to see the console output, as shown below:

The whole process of the component shows that React Native has made a good encapsulation for us. We only need to write a small amount of code to use the Native UI component.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.