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 that cannot be autolinked yet can be added manually here, for example:
    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

在这里插入图片描述

Logo

智屏生态联盟致力于大屏生态发展,利用大屏快应用技术降低开发者开发、发布大屏应用门槛

更多推荐