RN 封装 Android原生组件
背景
当在React Native暂时未提供部分原生功能或者模块,我们需要复用部分原生代码时,比如复用一个原生方法,此时就需要将原生方法进行封装,暴露出一个接口来让React-Native调用。
步骤
官网样例
以封装一个自适应字体大小的文本框为例,实现了设置文本、字体大小、可缩小到的最小字体大小、字体颜色、是否中划线、是否下划线、是否加粗、文字对齐方式、文本超出限制时省略号的位置、文本最大行数。
创建一个RN工程
命令行:react-native init 项目名
打开RN工程里的Android项目
创建ViewManager
实现getName方法
getName方法返回的名字在js端引用我们的控件时使用
实现createViewInstance方法
视图是在createViewInstance方法中创建的,视图应该在其默认状态下初始化,任何属性都将通过后续调用来设置updateView
导出给RN使用的属性
要导出给JavaScript使用的属性,需要申明带有@ReactProp(或@ReactPropGroup)注解的设置方法。 方法的第一个参数 view是要修改属性的视图实例,第二个参数 text是要设置的属性值。 方法的返回值类型必须为void,而且访问控制必须被声明为public。 @ReactProp注解必须包含一个字符串类型的参数name。这个参数指定了对应属性在RN端的名字。
class ReactAutoResizeTextViewManager : SimpleViewManager<AutoResizeTextView>() {
companion object {
const val REACT_CLASS = "REACTAutoResizeTextView"
}
override fun getName(): String {
return REACT_CLASS
}
override fun createViewInstance(reactContext: ThemedReactContext): AutoResizeTextView {
return AutoResizeTextView(reactContext)
}
@ReactProp(name = "text")
fun setText(autoResizeTextView: AutoResizeTextView, text: String) {
autoResizeTextView.setText(text)
}
@ReactProp(name = "textSize")
fun setTextSize(autoResizeTextView: AutoResizeTextView, textSize: Float) {
autoResizeTextView.setTextSize(textSize)
}
@ReactProp(name = "gravity")
fun setTextGravity(autoResizeTextView: AutoResizeTextView, gravity: String) {
autoResizeTextView.setTextGravity(gravity)
}
@ReactProp(name = "textColor")
fun setTextColor(autoResizeTextView: AutoResizeTextView, textColor: String) {
autoResizeTextView.setTextColor(textColor)
}
@ReactProp(name = "maxLines")
fun setMaxLines(autoResizeTextView: AutoResizeTextView, maxLines: Int) {
autoResizeTextView.setMaxLine(maxLines)
}
@ReactProp(name = "minTextSize")
fun setMinTextSize(autoResizeTextView: AutoResizeTextView, minTextSize: Float) {
autoResizeTextView.setMinTextSize(minTextSize)
}
@ReactProp(name = "underLine")
fun setUnderLine(autoResizeTextView: AutoResizeTextView, underLine: Boolean) {
autoResizeTextView.setUnderLine(underLine)
}
@ReactProp(name = "middleLine")
fun setMiddleLine(autoResizeTextView: AutoResizeTextView, middleLine: Boolean) {
autoResizeTextView.setMiddleLine(middleLine)
}
@ReactProp(name = "ellipsize")
fun setEllipsize(autoResizeTextView: AutoResizeTextView, ellipsize: String) {
autoResizeTextView.setEllipsize(ellipsize)
}
@ReactProp(name = "bold")
fun setBold(autoResizeTextView: AutoResizeTextView, bold: Boolean) {
autoResizeTextView.setTextStyle(bold)
}
}
注册ViewManager
新建ReactViewPackage类,实现ReactPackage的两个方法:createNativeModules,createViewManagers。
createNativeModules是用来添加原生模块的,比如:Toast等。createViewManagers是用来添加原生的UI组件的。 将我们创建的ReactAutoResizeTextViewManager添加到createViewManagers中,如果没有引入原生模块,可以将createNativeModules方返回空数组
class AutoResizeTextViewPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule> {
return Collections.emptyList()
}
override fun createViewManagers(reactContext: ReactApplicationContext): MutableList<ViewManager<*, *>> {
return mutableListOf(ReactAutoResizeTextViewManager())
}
}
注册Package
在项目的MainApplication.java文件的getPackages方法中添加我们封装的原生模块
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new AutoResizeTextViewPackage());
return packages;
}
在js端导出所封装的原生组件
requireNativeComponent通常接受两个参数,第一个参数是原生视图的名字,而第二个参数是一个描述组件接口的对象。组件接口应当声明一个友好的name,用来在调试信息中显示;组件接口还必须声明propTypes字段,用来对应到原生视图上。这个propTypes还可以用来检查用户使用View的方式是否正确。
import {requireNativeComponent,View} from 'react-native'
import {PropTypes} from 'prop-types'
const mReactAutoResizeTextView = {
name: "REACTAutoResizeTextView",
propTypes:{
"text":PropTypes.string,
"maxLines":PropTypes.number,
...View.propTypes
}
}
export default requireNativeComponent('REACTAutoResizeTextView',mReactAutoResizeTextView)
使用封装好的组件
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
DeviceEventEmitter
} from 'react-native';
import ReactAutoResizeTextView from './ReactAutoResizeTextView';
class mView extends Component {
render() {
return (
<View style={styles.container}>
<ReactAutoResizeTextView
style={styles.mAutoResizeTextView}
text="曾经沧海难为水,除却巫山不是云。取次花丛懒回顾,半缘修道半缘君。"
textSize={15}
middleLine={true}
underLine={false}
gravity="center"
ellipsize="middle"
minTextSize={6}
bold={true}
textColor="#FF0000"
maxLines={1}
/>
</View>
)
}
};
const styles = StyleSheet.create({
container:{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
mAutoResizeTextView:{
width:300,
height:300,
},
mTitle:{
width:300,
height:50,
marginBottom:30,
textAlign:'center',
color:'black'
}
});
AppRegistry.registerComponent('MyNativePackage', () => mView);
运行项目
命令行:react-native run-android
|