reactnative 使用自定义原生控件

致敬 facebook 。reactnative 是factbook推出的移动端跨平台框架,给跨平台开发带来了新的实现。
它封装了大量常用的基础控件,但是在开发的过程中并不能满足个性的开发。有幸的是 rn团队为开发者接入自定义控件提供了解决方案。本章主要记录Android平台上如何使用自定义控件。


1.Android端原生实现

1.1 继承ViewManager进行自定义控件开发

1
2
3
4
5
6
7
8
9
10
11
12
public class GameViewManager extends SimpleViewManager<ImageView> {
@Override
public String getName() {
return "rnimageview";
}

@Override
protected ImageView createViewInstance(ThemedReactContext reactContext) {
return new ImageView():
}
}

getName 方法返回的值 就是我们在 rn的javascript文件里面使用的view标签名字

通过createViewInstance方法返回要使用控件的实例

1.2 支持自定义属性和方法

我们需要添加一些动态的值通过属性的方式让我们的原生控件接收,rn提供了一套通信方式,我们在ViewManager的实现类中添加如下方法:

1
2
3
4
5
6
7
@ReactMethod
@ReactProp(name = "gameURL")
public void setUrl(JdGameSurface view, @Nullable String sources) {
Toast.makeText(view.getContext(),"seturl",Toast.LENGTH_SHORT).show();
view.loadJsFromAssets("fish-android.js");
view.start();
}

添加 ReactMethod 注解的方法可以在javascript文件中访问, 这样我们可以在javascript中动态设值。

@ReactProp(name = “gameURL”) 此注解标识我们为本view添加了一个gameURL的属性 。 通过这样我们就完成了对应属性的添加

1.3 注册我们的自定义控件

首先我们 新建ReactPackage的实现类,然后将我们的自定义ViewManager 在createViewManagers方法中添加到集合返回,如下代码所示 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class GameReactPackage implements ReactPackage {


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

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
ArrayList<ViewManager> viewManagers = new ArrayList<>();
viewManagers.add(new GameViewManager());//重要
return viewManagers;
}
}

其次,在application中将我们新建的ReactPackage类,添加到rn中注册

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
public class MainApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}

@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new GameReactPackage()//重要
);
}

@Override
protected String getJSMainModuleName() {
return "index";
}
};

@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}

@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}

主要是在 getPackages 方法中将此 ReactPackage 添加到集合中返回 。

到此为止,我么就将Android中原生开发进行完毕,下面开始讲解怎么在 javascript文件中使用此自定义控件

2. 在RN中使用自定义控件

为方便使用,我们实现一个 rn模块对view进行统一的管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { requireNativeComponent } from 'react-native';

class JDGameView extends React.Component{
render() {
return <RNJDGame {...this.props} />;
}
}

JDGameView.propTypes = {
gameURL:PropTypes.string,
...View.propTypes
};

var RNJDGame = requireNativeComponent('RNJDGame',JDGameView);

export default JDGameView;

在我们需要使用此view的地方进行引入即可

1
2
3
4
5
render() {
return (
<JDGameView gameURL="xxxxxxx"></JDGameView>
);
}

至此,我们通过代码和讲解,实现了rn中进行自定义控件的完整流程。