前面系列文章分析了react-native js代码和java jni代码的交互通道。
react-native第二个重要的部分自然是它对view的处理,如何使用js代码绘制出"native"控件是我们接下来系列文章的主要内容。
在第一篇文章的时候我们看到过一个ReactRootView 一个负责touch分发的根view。因此,这篇文章先看下这个view的实现。
ReactRootView.java
public class ReactRootView extends SizeMonitoringFrameLayout implementsRootView
/*****
RootView.java
public interfaceRootView {
/**
* Called when a child starts a native gesture (e.g. a scroll in a ScrollView). Should be called
* from the child's onTouchIntercepted implementation.
*/
void onChildStartedNativeGesture(MotionEvent androidEvent);
}
******///
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
handleTouchEvent(ev);
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
handleTouchEvent(ev);
super.onTouchEvent(ev);
// In case when there is no children interested in handling touch event, we return true from
// the root view in order to receive subsequent events related to that gesture
return true;
}
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
// No-op - override in order to still receive events to onInterceptTouchEvent
// even when some other view disallow that
//不调用super.requ..ent 是为了确保调用到onInterceptTouchEvent函数
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// No-op sinceUIManagerModule handles actually laying out children. //后面文章有分析这个manager
}
/**
* Main catalyst view is responsible for collecting and sending touch events to JS. This method
*reacts for an incoming android native touch events ({
@link MotionEvent}) andcalls into
* {
@link com.facebook.react.uimanager.events.EventDispatcher} when appropriate.
* It uses {
@link com.facebook.react.uimanager.TouchTargetManagerHelper#findTouchTargetView}
* helper method forfiguring out a react view ID in the case of ACTION_DOWN
* event (when the gesture starts).
*/
private void handleTouchEvent(MotionEvent ev) { //touch处理
//介绍一下rn view的思路。观察一下rn官方的例子,你会发现在xml文件中一般只有reactRootView这一个viewgroup
//因此rn在处理touch的时候要先找到target 然后使用dispather组件将touch转发给js封装好的控件
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
mReactInstanceManager.getCurrentReactContext() == null) {
return;
}
int action = ev.getAction() & MotionEvent.ACTION_MASK;
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class)
.getEventDispatcher(); //下面有分析具体实现
if (action == MotionEvent.ACTION_DOWN) {
mChildIsHandlingNativeGesture = false;
mTargetTag = TouchTargetHelper.findTargetTagForTouch(ev.getRawY(), ev.getRawX(), this);
//找到touch的目标(拿到一个view的id)(及其
对应的js实现的控件
eventDispatcher.dispatchEvent(new TouchEvent(mTargetTag, TouchEventType.START, ev));
//注意touchEvent封装了view的id ReactTouch的type 及touch实体(后面有分析-->用来传输给js控件
} else if (mChildIsHandlingNativeGesture) {