ohos扩展包——触摸事件分发

jacksky
发布于 2021-9-27 17:52
浏览
0收藏

扩展事件分发机制 dispatchTouchEvent -> onInterceptTouchEvent -> onTouchEvent,并实现了requestDisallowInterceptTouchEvent方法。

注意

  1. 如果根布局或者中间的ComponentContainer实现的是View而非ViewGroup,那么事件将不会继续往下传递。
  2. 视图树中间可以出现断层,即出现未实现View或ViewGroup的控件,事件会跳过并往下传递。
  3. 未实现View或ViewGroup的控件,如果设置了setTouchEventListener,那么事件将在回调返回true后直接被消费,而导致不会被分发。
  4. 如果遇到super.onTouchEvent或者super.onInterceptTouchEvent,需要去父类查看逻辑并移植进来,如果是普通的布局或者控件一般是可以忽略,或者返回false的。
  5. 如果遇到super.dispatchTouchEvent则可以直接使用ViewGroupHelper/ViewHelper的dispatchTouchEvent来替代。
  6. 暂时只支持单点触摸的分发

使用

ComponentContainer

  1. ComponentContainer需要实现Component.TouchEventListener以及ViewGroup接口
    public class ViewParent extends DirectionalLayout implements Component.TouchEventListener, ViewGroup​
  2. 设置setTouchEventListener
    setTouchEventListener(this);​
  3. 在ohos的onTouchEvent内调用DispatchHelper的dispatch方法
    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        return DispatchHelper.dispatch(component, event);
    }​
  4. 转发ViewGroup接口内的dispatchTouchEvent、isConsumed、requestDisallowInterceptTouchEvent方法至ViewGroupHelper实现,并在onInterceptTouchEvent、onTouchEvent内实现具体分发逻辑
        ViewGroupHelper impl = new ViewGroupHelper();
    
        @Override
        public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
            impl.requestDisallowInterceptTouchEvent(disallowIntercept);
        }
    
        @Override
        public boolean onInterceptTouchEvent(TouchEvent ev) {
            return false;
        }
    
        @Override
        public boolean dispatchTouchEvent(TouchEvent event) {
            return impl.dispatchTouchEvent(event);
        }
    
        @Override
        public boolean onTouchEvent(TouchEvent event) {
            return false;
        }
    
        @Override
        public boolean isConsumed() {
            return impl.isConsumed();
        }​

Component

  1. Component需要实现Component.TouchEventListener以及View接口
public class ViewChild extends ScrollView implements Component.TouchEventListener, View
  1. 设置setTouchEventListener
    setTouchEventListener(this);​
  2. 在ohos的onTouchEvent内调用DispatchHelper的dispatch方法
@Override
public boolean onTouchEvent(Component component, TouchEvent event) {
    return DispatchHelper.dispatch(component, event);
}

4、转发ViewGroup接口内的dispatchTouchEvent、isConsumed方法至ViewHelper实现,并在onTouchEvent内实现具体分发逻辑

    ViewHelper impl = new ViewHelper();

    @Override
    public boolean dispatchTouchEvent(TouchEvent event) {
        return impl.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(TouchEvent event) {
        return true;
    }

    @Override
    public boolean isConsumed() {
        return impl.isConsumed();
    }

requestDisallowInterceptTouchEvent

Component需要父控件不拦截事件,可以调用DispatchHelper的requestDisallowInterceptTouchEvent方法

DispatchHelper.requestDisallowInterceptTouchEvent(this, false);

// postRequestDisallowInterceptTouchEvent会通过EventHandler将函数延迟执行
// 避免在构造函数中调用requestDisallowInterceptTouchEvent时,获取ComponentParent为空的情况
DispatchHelper.postRequestDisallowInterceptTouchEvent(this, false);

 

接着打印每个函数的日志,并且尝试修改父控件的onInterceptTouchEvent、onTouchEvent,以及子控件的onTouchEvent的值,并查看日志结果。

也可以再多尝试几层ViewGroup实现,来实现更复杂的效果。

实现

由于ohos的事件传递是冒泡形式,即事件会先到目标控件内,如果目标控件不消耗事件,则冒泡到父控件内。而安卓的事件则是先传递到父控件,再经过分发,传递到目标控件内。

因此DispatchHelper的主要作用就是查找视图树内所有实现了View或ViewGroup的控件,并调用顶层控件的dispatchTouchEvent函数向下分发事件。并过滤掉由于事件冒泡,而传递过来的重复事件。

ViewHelper、ViewGroupHelper则主要实现了安卓的View、ViewGroup中dispatchTouchEvent函数的逻辑。

已于2021-9-27 18:25:59修改
收藏
回复
举报
回复
    相关推荐