React-Native系列Android——自定义View组件开发

React-Native是由ReactJS发展而来,继承了其JavaScript XML(简称JSX)和组件化等特性。JSX是一种XML语言,用于视图层级搭建。而组件化是一种设计思想,具有易于维护组合和便于扩展等优点,React-Native中无论是原生Java层,还是JS层,都遵循了这种思想。

Android原生Java端的组件分为两种类型:视图组件(View)和功能组件(Module),React-Native官方为开发者提供了大量的常用组件,位于com.facebook.react.views包和com.facebook.react.modules包下面,基本覆盖了所有类型的组件,包括文本,输入框,图片等。

本文GradientColorView(颜色渐变视图)为例,演示如何自定义一个原生View组件,并在JS中调用。


1、Java层自定义GradientColorView

package com.myproject;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.view.View;

public class GradientColorView extends View {

    private GradientDrawable mDrawable;

    private int mStartColor;
    private int mEndColor;

    public GradientColorView(Context context) {
        super(context);
        mDrawable = new GradientDrawable();
        mDrawable.setOrientation(Orientation.LEFT_RIGHT);
    }

    public void setStartColor(int startColor) {
        this.mStartColor = startColor;
    }

    public void setEndColor(int endColor) {
        this.mEndColor = endColor;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mDrawable.setBounds(0, 0, getWidth(), getHeight());
        mDrawable.setColors(new int[]{mStartColor, mEndColor});
        mDrawable.draw(canvas);
    }

}

代码非常简单,自定义一个普通View,并提供两个控制渐变颜色的方法setStartColorsetEndColor,然后再onDraw方法里面绘制在画布上。


2、Java层自定义ViewManager

编写UI管理器,如果没有特殊要求,直接继承SimpleViewManager,并使用上一步的GradientColorView作为泛型类型。

这里需要实现两个简单的方法getNamecreateViewInstance,前者用来映射JS中的组件(后面讲到),后者用来创建View实例。

同时需要提供两个被注入的方法setStartColorsetEndColor,必须使用ReactProp注解,name值与JS中属性名保持一致。

package com.myproject;

import javax.annotation.Nullable;

import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;

public class GradientColorViewManager extends SimpleViewManager<GradientColorView> {

    // React-Native官方大多数自定义View都是用RCT开头,这里保持规范性
    private static final String REACT_CLASS = "RCTGradientColorView";

    @Override
    public String getName() {
        // 此处name在后面JS组件开发时会用到,需要统一命名
        return REACT_CLASS;
    }

    @Override
    protected GradientColorView createViewInstance(ThemedReactContext reactContext) {
        // GradientColorView的实例化
        return new GradientColorView(reactContext);
    }

    /**
     * ReactProp注解方法,React-Native底层会自动反射调用,
     * name字符串值与JS中配置的属性名保持一致
     * customType字符串值表示颜色转换,不配置会转换异常
     * 
     * @param view GradientColorView实例
     * @param startColor 渐变起始值
     */
    @ReactProp(name = "startColor", customType = "Color")
    public void setStartColor(GradientColorView view, @Nullable Integer startColor) {
        view.setStartColor(startColor);
    }

    /**
     * ReactProp注解方法,React-Native底层会自动反射调用,
     * name字符串值与JS中配置的属性名保持一致
     * customType字符串值表示颜色转换,不配置会转换异常
     * 
     * @param view GradientColorView实例
     * @param endColor 渐变结束值
     */
    @ReactProp(name = "endColor", customType = "Color")
    public void setEndColor(GradientColorView view, @Nullable Integer endColor) {
        view.setEndColor(endColor);
    }

}

3、Java层注册ViewManager

上一步中编写的GradientColorViewManager需要手动注册,否则React-Native底层无法映射识别,具体注册是在Activity中,代码如下:

    /**
     * A list of packages used by the app. If the app uses additional views
     * or modules besides the default ones, add more packages here.
     */
    @Override
    protected List getPackages() {
        return Arrays.asList(
            new MainReactPackage(),
            new ReactPackage() {

                @Override
                public List createViewManagers(
                        ReactApplicationContext reactContext) {
                    return Arrays.asList(new GradientColorViewManager());
                }

                @Override
                public List createNativeModules(
                        ReactApplicationContext reactContext) {
                    return Collections.emptyList();
                }

                @Override
                public List> createJSModules() {
                    return Collections.emptyList();
                }
            }
        );
    }

除了必要的MainReactPackage之外,注册了一个匿名内部类ReactPackage,包含了GradientColorViewManager。这样GradientColorViewManager的注册就完成了。

接下来需要开发JS层对应的组件了。


4、JS层开发GradientColorView组件

前三步中,Android原生组件开发完成了,但是如果要在设备中显示出来,还需要通过由Javascript层进行组件映射,如何映射是由Bridge(连接JavaJavascriptJNI库)完成的,这里不细讲。我们接下来编写桥梁另一端的代码。

前面说过,Javascript层也遵循了组件化设计思想,我们在React-Native项目根目录定义一个GradientColorView.js的文件,代码如下:

/**
 * @providesModule RCTGradientColorView
*/

'use strict';

var PropTypes = require('ReactPropTypes');
var React = require('React');
var View = require('View');
var requireNativeComponent = require('requireNativeComponent');

var GradientColorView = React.createClass({

    // 定义两个控制颜色的属性,与Java层GradientColorView中@ReactProp注解的方法参数保持一致
    propTypes: {
    ...View.propTypes,
        startColor: PropTypes.string,
        endColor: PropTypes.string,

},
    render: function() {
    return (
      <NativeGradientColorView 
style={this.props.style}
 startColor={this.props.startColor}
 endColor={this.props.endColor}/>
);}

});

    var NativeGradientColorView = requireNativeComponent('RCTGradientColorView', GradientColorView);

    module.exports = GradientColorView;

分析以上代码,主要是由5部分组成。

1、注解部分。@providesModule注解表示当前JS组件是需要与原生组件相互映射的,其值RCTGradientColorView与前面第3步中GradientColorViewManager类中的getName()值保持一致性,这样才能完成映射关系。这里不得不提一点,ViewManager这个类设计得并不是特别合理,如果getName()的值也通过Java类注解来完成,保持和JS层的呼应关系,将更容易让人理解。

2、初始化对象。PropTypesReactViewrequireNativeComponent等对象在后面会使用到,所以需要先实例化。这一点是ReactJS的语法,有兴趣自行研究。

3、定义组件属性。最基本的View.propTypes属性,还有两个自定义的的startColorendColor。这样使用组件的地方就可以使用如startColor=‘red’进行开发了。

4、组件渲染。这一步使用了JSXJavaScript XML)语法,自定义了NativeGradientColorView标签,实际上是对GradientColorView做了一层包装。

5、组件导出。最后一行代码 module.exports = GradientColorView 声明了GradientColorView标签可以在其他JS文件中调用。


5、GradientColorView组件的使用

到这里,自定义组件GradientColorView已经开发完成了,接下来提供给开发者进行使用。

如何使用一共分两步:

1,导入声明

import GradientColorView from './GradientColorView.js';

2,作为标签使用

<GradientColorView style={{width:80,height:80}} startColor="yellow" endColor="red"/>

使用效果如下:
React-Native系列Android——自定义View组件开发_第1张图片


6、总结

开发React-Native组件,涉及到Java(或Objective-C)和Javascript至少两种编程语言,流程比较繁琐,技术栈要求较高,除非迫不得已,一般不会这么做。

这里简要梳理一下步骤:
1、自定义View开发
2、编写相应ViewManager,实例化View,定义映射Name,注解API属性方法
3、Activity中注册ViewManager
4、编写Javascript组件,添加注解映射,定义标签对象、属性,提供给外部。
5、import组件,使用。

从以上步骤,大致可以了解React-Native组件的工作流程:

JSX标签解析 ——Javascript组件调用——Bridge——ViewManager反射——创建并配置View


本博客不定期持续更新,欢迎关注和交流:

http://blog.csdn.net/megatronkings

你可能感兴趣的:(React-Native)