RN调用原生UI组件的方法

简述

在RN开发中,难免会遇到有一些组件是实现不了的,这时就需要封装原生UI组件给RN使用。我这里是来拿跑马灯效果实现的

在原生Android中使用跑马灯效果实现如下:

定义一个FocusedTextView控件,来实现跑马灯的效果

public class FocusedTextView extends AppCompatTextView {
    public FocusedTextView(Context context) {
        super(context);
    }

    public FocusedTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public FocusedTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean isFocused() {
        //欺骗android系统,让其永远是有焦点的
        return true;
    }
}

在android布局中使用这个自定义的控件


这样就可以实现了一个跑马灯的效果。

下面我们来实现RN调用原生UI组件的方法

提供原生视图有如下几部:

  1. 创建一个 ViewManager 的子类并实现createViewInstance方法。
  2. 导出视图的属性设置器:使用@ReactProp(或@ReactPropGroup)注解。
  3. 把这个视图管理类注册到应用程序包的createViewManagers里。
  4. 实现 JavaScript 模块。
  5. 使用

1. 创建一个 ViewManager 的子类并实现createViewInstance方法。

public class FocusedTextViewManager extends SimpleViewManager {
    public static final String REACT_CLASS = "FocusedTextView";
    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Override
    protected FocusedTextView createViewInstance(ThemedReactContext reactContext) {
        FocusedTextView focusedTextView = new FocusedTextView(reactContext);
//        focusedTextView.setText("");
        focusedTextView.setTextColor(Color.BLUE);
        focusedTextView.setSingleLine(true);
        focusedTextView.setEllipsize(TextUtils.TruncateAt.MARQUEE);

        return focusedTextView;
    }
}

在这个例子里我们创建一个视图管理类FocusedTextViewManager,它继承自SimpleViewManager< FocusedTextView >。FocusedTextView是这个视图管理类所管理的对象类型,也就是我们自定义的原生视图。getName方法返回的名字会用于在 JavaScript 端引用。

2. 通过@ReactProp(或@ReactPropGroup)注解来导出属性的设置方法

要导出给 JavaScript 使用的属性,需要申明带有@ReactProp(或@ReactPropGroup)注解的设置方法。方法的第一个参数是要修改属性的视图实例,第二个参数是要设置的属性值。方法的返回值类型必须为void,而且访问控制必须被声明为public。JavaScript 所得知的属性类型会由该方法第二个参数的类型来自动决定。支持的类型有:boolean,int, float, double,String, Boolean, Integer, ReadableArray, ReadableMap

@ReactProp注解必须包含一个字符串类型的参数name。这个参数指定了对应属性在 JavaScript 端的名字。

除了name@ReactProp注解还接受这些可选的参数:defaultBoolean, defaultInt, defaultFloat。这些参数必须是对应的基础类型的值(也就是boolean, int, float),这些值会被传递给 setter 方法,以免 JavaScript 端某些情况下在组件中移除了对应的属性。注意这个"默认"值只对基本类型生效,对于其他的类型而言,当对应的属性删除时,null会作为默认值提供给方法。

重要!
在 ReactJS 里,修改一个属性会引发一次对设置方法的调用。有一种修改情况是,移除掉之前设置的属性。在这种情况下设置方法也一样会被调用,并且“默认”值会被作为参数提供(对于基础类型来说可以通过defaultBooleandefaultFloat@ReactProp的属性提供,而对于复杂类型来说参数则会设置为null

@ReactProp(name="text")
public void setText(FocusedTextView view,String text){
    view.setText(text);
}

@ReactProp(name="size")
public void setTextSize(FocusedTextView view,float size){
    view.setTextSize(size);
}

3.把这个视图管理类注册到应用程序包的createViewManagers里。

在 Java 中的最后一步就是把视图控制器注册到应用中.这和原生模块的注册方法类似,唯一的区别是我们把它放到createViewManagers方法的返回值里。

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

4.实现 JavaScript 模块。

整个过程的最后一步就是创建 JavaScript 模块并且定义 Java 和 JavaScript 之间的接口层。

import React, {Component} from 'react';
import {requireNativeComponent,View} from 'react-native';
import PropTypes from 'prop-types'

let iface = {
  name:'FocusedTextView',
  propTypes:{
      text:PropTypes.string,
      size:PropTypes.number,
      ...View.propTypes
  }
};
module.exports = requireNativeComponent("FocusedTextView",iface);

requireNativeComponent通常接受两个参数,第一个参数是原生视频的名称,而第二个参数是一个描述组件接口的对象。组件接口应当声明一个友好的name,用来在调试信息中显示;组件接口还必须声明propTypes字段,用来对应到原生视图上。这个propType还可以用来检查用户使用View的方式是否正确。

注意,如果还需要一个JavaScript组件来做一些除了指定那么和propTypes以外的事情,譬如时间处理,你可以把原生组件用一个普通React组件封装。在这种情况下,requireNativeComponent的第二个参数变为用于封装的组件。

5. 使用

import FocusedTextView from './FocusedTextView';

啦啦啦啦啦啦阿拉啦啦啦"}/>

最后的效果图:

RN调用原生UI组件的方法_第1张图片

源码连接

你可能感兴趣的:(RN调用原生UI组件的方法)