摘要:接下來查看方法的源碼里面的處理如下如果則返回,即該對觸摸事件不予處理。顯示了提示框的話則隱藏如果不可點擊,則移除長按事件的檢測,返回否則繼續向下走。當前是點擊事件,所以移除長按事件的檢測。關于源碼中的事件,可以參考文章源碼事件
在Android-27中查看源碼:
首先我們來查看單個View的觸摸事件的處理,在View的dispatchTouchEvent方法中看看源碼是如何處理的。
</>復制代碼
public boolean dispatchTouchEvent(MotionEvent event) {
// If the event should be handled by accessibility focus first.
if (event.isTargetAccessibilityFocus()) {
// We don"t have focus or no virtual descendant has it, do not handle the event.
if (!isAccessibilityFocusedViewOrHost()) {
return false;
}
// We have focus and got the event, then use normal event dispatch.
event.setTargetAccessibilityFocus(false);
}
boolean result = false;
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Defensive cleanup for new gesture
stopNestedScroll();
}
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
if (!result && mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
// Clean up after nested scrolls if this is the end of a gesture;
// also cancel it if we tried an ACTION_DOWN but we didn"t want the rest
// of the gesture.
if (actionMasked == MotionEvent.ACTION_UP ||
actionMasked == MotionEvent.ACTION_CANCEL ||
(actionMasked == MotionEvent.ACTION_DOWN && !result)) {
stopNestedScroll();
}
return result;
}
dispatchTouchEvent處理過程如下:
如果設置了OnTouchListener和enabled為true,并且onTouch返回為true,即該View在OnTouchListener的onTouch方法中處理了觸摸事件。
如果onTouchEvent返回為true,即該View在onTouchEvent中處理了觸摸事件。
如果觸摸事件在該View中得到處理則返回true,否則返回false(即該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();
final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
|| (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
|| (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
if ((viewFlags & ENABLED_MASK) == DISABLED) {
if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
setPressed(false);
}
mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
// A disabled view that is clickable still consumes the touch
// events, it just doesn"t respond to them.
return clickable;
}
if (mTouchDelegate != null) {
if (mTouchDelegate.onTouchEvent(event)) {
return true;
}
}
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
switch (action) {
case MotionEvent.ACTION_UP:
mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
if ((viewFlags & TOOLTIP) == TOOLTIP) {
handleTooltipUp();
}
if (!clickable) {
removeTapCallback();
removeLongPressCallback();
mInContextButtonPress = false;
mHasPerformedLongPress = false;
mIgnoreNextUpEvent = false;
break;
}
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)) {
performClick();
}
}
}
if (mUnsetPressedState == null) {
mUnsetPressedState = new UnsetPressedState();
}
if (prepressed) {
postDelayed(mUnsetPressedState,
ViewConfiguration.getPressedStateDuration());
} else if (!post(mUnsetPressedState)) {
// If the post failed, unpress right now
mUnsetPressedState.run();
}
removeTapCallback();
}
mIgnoreNextUpEvent = false;
break;
case MotionEvent.ACTION_DOWN:
if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
}
mHasPerformedLongPress = false;
if (!clickable) {
checkForLongClick(0, x, y);
break;
}
if (performButtonActionOnTouchDown(event)) {
break;
}
// Walk up the hierarchy to determine if we"re inside a scrolling container.
boolean isInScrollingContainer = isInScrollingContainer();
// For views inside a scrolling container, delay the pressed feedback for
// a short period in case this is a scroll.
if (isInScrollingContainer) {
mPrivateFlags |= PFLAG_PREPRESSED;
if (mPendingCheckForTap == null) {
mPendingCheckForTap = new CheckForTap();
}
mPendingCheckForTap.x = event.getX();
mPendingCheckForTap.y = event.getY();
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
} else {
// Not inside a scrolling container, so show the feedback right away
setPressed(true, x, y);
checkForLongClick(0, x, y);
}
break;
case MotionEvent.ACTION_CANCEL:
if (clickable) {
setPressed(false);
}
removeTapCallback();
removeLongPressCallback();
mInContextButtonPress = false;
mHasPerformedLongPress = false;
mIgnoreNextUpEvent = false;
mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
break;
case MotionEvent.ACTION_MOVE:
if (clickable) {
drawableHotspotChanged(x, y);
}
// Be lenient about moving outside of buttons
if (!pointInView(x, y, mTouchSlop)) {
// Outside button
// Remove any future long press/tap checks
removeTapCallback();
removeLongPressCallback();
if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
setPressed(false);
}
mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
}
break;
}
return true;
}
return false;
}
onTouchEvent里面的處理如下:
如果setEnabled(false),則返回false,即該View對觸摸事件不予處理。
如果設置了TouchDelegate,并且TouchDelegate的onTouchEvent返回true,則返回true,即由TouchDelegate中的onTouchEvent方法處理了觸摸事件。否則繼續向下。
如果該View不可點擊并且(viewFlags & TOOLTIP) != TOOLTIP(即當停留或長按在該view時不可顯示提示框),則返回false,即該View對觸摸事件不予處理。否則繼續向下。
根據觸摸事件的分類進行處理:
MotionEvent.ACTION_DOWN:
不可點擊或者不在可滑動的容器內:如果LONG_CLICKABLE為true則執行OnLongClickListener的onLongClick方法;或者設置了viewFlags為TOOLTIP,則執行showTooltip(顯示提示框)。然后返回true,即該View處理了觸摸事件,否則繼續向下走。
MotionEvent.ACTION_MOVE:在手指移動的過程中判斷是否仍在當前view的范圍。
MotionEvent.ACTION_UP:
顯示了提示框的話則隱藏;
如果不可點擊,則移除長按事件的檢測,返回true,否則繼續向下走。
當前是點擊事件,所以移除長按事件的檢測。然后執行performClick方法,返回true,即該View處理了觸摸事件。
關于ViewGroup源碼中的Touch事件,可以參考文章:ViewGroup源碼-Touch事件
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72174.html
摘要:在中查看源碼在看完源碼的觸摸事件源碼事件后,我們接著來看看容器類的觸摸事件。同樣的先來看源碼中的方法首先,會判斷是否不允許攔截,可以通過進行設置,默認允許攔截。 在Android-27中查看源碼: 在看完View源碼的觸摸事件(View源碼-Touch事件)后,我們接著來看看容器類View的觸摸事件。因為容器類的View都繼承自ViewGroup,所以我們在ViewGroup的源碼中來...
摘要:注意,事件分發是向下傳遞的,也就是父到子的順序。事件分發機制的本質是要解決,點擊事件由哪個對象發出,經過哪些對象,最終達到哪個對象并最終得到處理。表示以及分發給其中在內部完成被賦值。會自己處理事件。 目錄介紹 01.Android中事件分發順序 1.1 事件分發的對象是誰 1.2 事件分發的本質 1.3 事件在哪些對象間進行傳遞 1.4 事件分發過程涉及方法 1.5 Androi...
摘要:當不攔截事件的時候,事件會向下分發交由它的子或進行處理。表示以及分發給其中在內部完成被賦值。會自己處理事件。 目錄介紹 01.Android中事件分發順序 02.Activity的事件分發機制 2.1 源碼分析 2.2 點擊事件調用順序 2.3 得出結論 03.ViewGroup事件的分發機制 3.1 看一下這個案例 3.2 源碼分析 3.3 得出結論 04.Vie...
閱讀 1323·2021-11-15 11:37
閱讀 2580·2021-09-22 10:56
閱讀 3403·2021-09-06 15:11
閱讀 814·2021-08-31 09:45
閱讀 2914·2021-07-28 11:16
閱讀 1816·2019-08-30 15:44
閱讀 487·2019-08-30 13:22
閱讀 3354·2019-08-30 13:18