「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战」
相关文章:
Android View的事件分发(一)-事件分发的过程
Android View的事件分发(二)-事件传递顺序
Android View的事件分发(三)-事件的分发(dispatchTouchEvent)
Android View的事件分发(四)-事件处理(onTouchEvent)
Android View的事件分发(五)-事件拦截(onInterceptTouchEvent)
上一篇文章,介绍了View事件的分发,也就是事件的传递过程,最重要的就是dispatchTouchEvent方法的调用以及对阻止父类拦截事件的方法,requestDisallowInterceptTouchEvent,最后通过源码分析,ViewGroup 的事件分发最终还是调用 View 的 dispatchTouchEvent 方法,那么View的分发上一篇也介绍到了,最后执行到onTouchEvent来处理事件,那么这篇文章,介绍onTouchEvent的事件处理。
onTouchEvent
View自己的onTouchEvent方法:
public boolean onTouchEvent(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
final int viewFlags = mViewFlags;
final int action = event.getAction();
//1.如果View是设置成不可用的(DISABLED)仍然会消费点击事件
if ((viewFlags & ENABLED_MASK) == DISABLED) {
if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
setPressed(false);
}
// A disabled view that is clickable still consumes the touch
// events, it just doesn't respond to them.
return (((viewFlags & CLICKABLE) == CLICKABLE
|| (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
|| (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
}
...
//2.CLICKABLE 和LONG_CLICKABLE只要有一个为true就消费这个事件
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
(viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
switch (action) {
case MotionEvent.ACTION_UP:
boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
// take focus if we don't have it already and we should in
// touch mode.
boolean focusTaken = false;
if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
focusTaken = requestFocus();
}
if (prepressed) {
// The button is being released before we actually
// showed it as pressed. Make it show the pressed
// state now (before scheduling the click) to ensure
// the user sees it.
setPressed(true, x, y);
}
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
// This is a tap, so remove the longpress check
removeLongPressCallback();
// Only perform take click actions if we were in the pressed state
if (!focusTaken) {
// Use a Runnable and post this rather than calling
// performClick directly. This lets other visual state
// of the view update before click actions start.
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
//3.在ACTION_UP方法发生时会触发performClick()方法
performClick();
}
}
}
...
break;
}
...
return true;
}
return false;
}
上面源码中重要部分,都加注释,可以看出DISABLED这个标识,是标识View的可用状态,源码中可以看出,即使View是disabled状态,事件还是会被消费,那么消费的前提是什么呢?就是CLICKABLE和LONG_CLICKABLE有一个为true,那么就会被消费,也就是onTouchEvenet的返回值为true,这个在开篇的文章中已经介绍了,View 的onTouchEvent 方法默认都会消费掉事件(返回true),除非它是不可点击的(clickable和longClickable同时为false),View的longClickable默认为false,clickable需要区分情况,如Button的clickable默认为true,而TextView的clickable默认为false。另外在看下,在ACTION_UP中的方法performClick:
/**
* Call this view's OnClickListener, if it is defined. Performs all normal
* actions associated with clicking: reporting accessibility event, playing
* a sound, etc.
*
* @return True there was an assigned OnClickListener that was called, false
* otherwise is returned.
*/
public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
result = true;
} else {
result = false;
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
return result;
}
可以看出,如果View设置点击事件,也就是onClick事件,那么会回调onClick方法。
View的 clickable属性对不同的View的默认值是不一样的,默认情况下,Button的clickable是true,而TextView默认是false,但是如果TextView,设置了setOnClickListener那么,就默认将clickable设置成了true,setOnLongClickListener,也是同理。
public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
public void setOnLongClickListener(@Nullable OnLongClickListener l) {
if (!isLongClickable()) {
setLongClickable(true);
}
getListenerInfo().mOnLongClickListener = l;
}
onTouchEvent事件的处理就介绍到这里,篇幅比较短,内容也不是很多,但是也是开发中遇到问题比较多的点。
今天更文,刚好是元宵,祝大家元宵节快乐,阖家欢乐。