您的位置:首页 > Web前端 > React

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

2017-09-15 14:49 621 查看
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);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

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


2、Java层自定义ViewManager

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

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

同时需要提供两个被注入的方法setStartColor和setEndColor,必须使用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);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53


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<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new ReactPackage() {

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

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

@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
}
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

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

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


4、JS层开发GradientColorView组件

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

前面说过,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;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

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

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

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

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

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

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


5、GradientColorView组件的使用

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

如何使用一共分两步:

1,导入声明
import GradientColorView from './GradientColorView.js';
1

2,作为标签使用
<GradientColorView style={{width:80,height:80}} startColor="yellow" endColor="red"/>
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: