回复
ohos扩展包——触摸事件分发
jacksky
发布于 2021-9-27 17:52
浏览
0收藏
扩展事件分发机制 dispatchTouchEvent -> onInterceptTouchEvent -> onTouchEvent,并实现了requestDisallowInterceptTouchEvent方法。
注意
- 如果根布局或者中间的ComponentContainer实现的是View而非ViewGroup,那么事件将不会继续往下传递。
- 视图树中间可以出现断层,即出现未实现View或ViewGroup的控件,事件会跳过并往下传递。
- 未实现View或ViewGroup的控件,如果设置了setTouchEventListener,那么事件将在回调返回true后直接被消费,而导致不会被分发。
- 如果遇到super.onTouchEvent或者super.onInterceptTouchEvent,需要去父类查看逻辑并移植进来,如果是普通的布局或者控件一般是可以忽略,或者返回false的。
- 如果遇到super.dispatchTouchEvent则可以直接使用ViewGroupHelper/ViewHelper的dispatchTouchEvent来替代。
- 暂时只支持单点触摸的分发
使用
ComponentContainer
- ComponentContainer需要实现Component.TouchEventListener以及ViewGroup接口
public class ViewParent extends DirectionalLayout implements Component.TouchEventListener, ViewGroup
- 设置setTouchEventListener
setTouchEventListener(this);
- 在ohos的onTouchEvent内调用DispatchHelper的dispatch方法
@Override public boolean onTouchEvent(Component component, TouchEvent event) { return DispatchHelper.dispatch(component, event); }
- 转发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
- Component需要实现Component.TouchEventListener以及View接口
public class ViewChild extends ScrollView implements Component.TouchEventListener, View
- 设置setTouchEventListener
setTouchEventListener(this);
- 在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修改
赞
收藏
回复
相关推荐