中文字幕av高清_国产视频一二区_男女羞羞羞视频午夜视频_成人精品一区_欧美色视_在线视频这里只有精品

千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機(jī)構(gòu)

手機(jī)站
千鋒教育

千鋒學(xué)習(xí)站 | 隨時(shí)隨地免費(fèi)學(xué)

千鋒教育

掃一掃進(jìn)入千鋒手機(jī)站

領(lǐng)取全套視頻
千鋒教育

關(guān)注千鋒學(xué)習(xí)站小程序
隨時(shí)隨地免費(fèi)學(xué)習(xí)課程

當(dāng)前位置:首頁  >  技術(shù)干貨  > ACTION_CANCEL到底何時(shí)觸發(fā),滑出子View范圍會(huì)發(fā)生什么?

ACTION_CANCEL到底何時(shí)觸發(fā),滑出子View范圍會(huì)發(fā)生什么?

來源:千鋒教育
發(fā)布人:xqq
時(shí)間: 2023-10-12 21:31:42 1697117502

一、ACTION_CANCEL在這些時(shí)候會(huì)觸發(fā)

1、父view攔截事件

首先要了解ViewGroup什么情況下會(huì)攔截事件,請(qǐng)看下面一段代碼:

@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) ...    boolean handled = false;    if (onFilterTouchEventForSecurity(ev))         final int action = ev.getAction();        final int actionMasked = action & MotionEvent.ACTION_MASK;...        // Check for interception.        final boolean intercepted;        // 判斷條件一        if (actionMasked == MotionEvent.ACTION_DOWN                || mFirstTouchTarget != null)             final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;            // 判斷條件二            if (!disallowIntercept)                 intercepted = onInterceptTouchEvent(ev);                ev.setAction(action); // restore action in case it was changed             else                 intercepted = false;                     else             // There are no touch targets and this action is not an initial down            // so this view group continues to intercept touches.            intercepted = true;                ...        ...

可以看出有兩個(gè)條件:

MotionEvent.ACTION_DOWN事件或者mFirstTouchTarget非空也就是有子view在處理事件子view沒有做攔截,也就是沒有調(diào)用ViewParent#requestDisallowInterceptTouchEvent(true)

如果滿足上面的兩個(gè)條件才會(huì)執(zhí)行onInterceptTouchEvent(ev)。如果ViewGroup攔截了事件,則intercepted變量為true,接著往下看:

@Overridepublic boolean dispatchTouchEvent(MotionEvent ev)         boolean handled = false;    if (onFilterTouchEventForSecurity(ev))         ...        // Check for interception.        final boolean intercepted;        if (actionMasked == MotionEvent.ACTION_DOWN                || mFirstTouchTarget != null)             final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;            if (!disallowIntercept)                 // 當(dāng)mFirstTouchTarget != null,也就是子view處理了事件                // 此時(shí)如果父ViewGroup攔截了事件,intercepted==true                intercepted = onInterceptTouchEvent(ev);                ev.setAction(action); // restore action in case it was changed             else                 intercepted = false;                     else             // There are no touch targets and this action is not an initial down            // so this view group continues to intercept touches.            intercepted = true;                ...        // Dispatch to touch targets.        if (mFirstTouchTarget == null)             ...         else             // Dispatch to touch targets, excluding the new touch target if we already            // dispatched to it.  Cancel touch targets if necessary.            TouchTarget predecessor = null;            TouchTarget target = mFirstTouchTarget;            while (target != null)                 final TouchTarget next = target.next;                if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget)                     ...                 else                     // 判斷一:此時(shí)cancelChild == true                    final boolean cancelChild = resetCancelNextUpFlag(target.child)                            || intercepted;// 判斷二:給child發(fā)送cancel事件                    if (dispatchTransformedTouchEvent(ev, cancelChild,                            target.child, target.pointerIdBits))                         handled = true;                                        ...                ...    return handled;

以上判斷一處cancelChild為true,然后進(jìn)入判斷二中一看究竟:

private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,            View child, int desiredPointerIdBits)     final boolean handled;    // Canceling motions is a special case.  We don't need to perform any transformations    // or filtering.  The important part is the action, not the contents.    final int oldAction = event.getAction();    if (cancel || oldAction == MotionEvent.ACTION_CANCEL)         // 將event設(shè)置成ACTION_CANCEL        event.setAction(MotionEvent.ACTION_CANCEL);        if (child == null)             ...         else             // 分發(fā)給child            handled = child.dispatchTouchEvent(event);                event.setAction(oldAction);        return handled;

當(dāng)參數(shù)cancel為ture時(shí)會(huì)將event設(shè)置為MotionEvent.ACTION_CANCEL,然后分發(fā)給child。

2、ACTION_DOWN初始化操作

首先請(qǐng)看一段代碼:

public boolean dispatchTouchEvent(MotionEvent ev)     boolean handled = false;    if (onFilterTouchEventForSecurity(ev))         final int action = ev.getAction();        final int actionMasked = action & MotionEvent.ACTION_MASK;        // Handle an initial down.        if (actionMasked == MotionEvent.ACTION_DOWN)             // Throw away all previous state when starting a new touch gesture.            // The framework may have dropped the up or cancel event for the previous gesture            // due to an app switch, ANR, or some other state change.            // 取消并清除所有的Touch目標(biāo)            cancelAndClearTouchTargets(ev);            resetTouchState();        ...        ...

系統(tǒng)可能會(huì)由于App切換、ANR等原因丟失了up,cancel事件。因此需要在ACTION_DOWN時(shí)丟棄掉所有前面的狀態(tài),具體代碼如下:

private void cancelAndClearTouchTargets(MotionEvent event)     if (mFirstTouchTarget != null)         boolean syntheticEvent = false;        if (event == null)             final long now = SystemClock.uptimeMillis();            event = MotionEvent.obtain(now, now,                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);            syntheticEvent = true;                for (TouchTarget target = mFirstTouchTarget; target != null; target = target.next)             resetCancelNextUpFlag(target.child);            // 分發(fā)事件同情況一            dispatchTransformedTouchEvent(event, true, target.child, target.pointerIdBits);                ...

PS:在dispatchDetachedFromWindow()中也會(huì)調(diào)用cancelAndClearTouchTargets()

3、在子View處理事件的過程中被從父View中移除時(shí)

請(qǐng)看下面這段代碼:

public void removeView(View view)     if (removeViewInternal(view))         requestLayout();        invalidate(true);    private boolean removeViewInternal(View view)     final int index = indexOfChild(view);    if (index >= 0)         removeViewInternal(index, view);        return true;        return false;private void removeViewInternal(int index, View view)     ...    cancelTouchTarget(view);...private void cancelTouchTarget(View view)     TouchTarget predecessor = null;    TouchTarget target = mFirstTouchTarget;    while (target != null)         final TouchTarget next = target.next;        if (target.child == view)             ...            // 創(chuàng)建ACTION_CANCEL事件            MotionEvent event = MotionEvent.obtain(now, now,                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);            分發(fā)給目標(biāo)view            view.dispatchTouchEvent(event);            event.recycle();            return;                predecessor = target;        target = next;

4、子View被設(shè)置了PFLAG_CANCEL_NEXT_UP_EVENT標(biāo)記時(shí)

請(qǐng)看下面這段代碼,在情況一種的兩個(gè)判斷處:

// 判斷一:此時(shí)cancelChild == truefinal boolean cancelChild = resetCancelNextUpFlag(target.child)|| intercepted;// 判斷二:給child發(fā)送cancel事件if (dispatchTransformedTouchEvent(ev, cancelChild,    target.child, target.pointerIdBits))     handled = true;

當(dāng)?resetCancelNextUpFlag(target.child)?為true時(shí)同樣也會(huì)導(dǎo)致cancel,查看代碼:

/** * Indicates whether the view is temporarily detached. * * @hide */static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;private static boolean resetCancelNextUpFlag(View view)     if ((view.mPrivateFlags & PFLAG_CANCEL_NEXT_UP_EVENT) != 0)         view.mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;        return true;        return false;

二、滑出子View范圍會(huì)發(fā)生什么

通常來說,滑出子View范圍什么也不會(huì)發(fā)生。如果手指移出了子View之外,從而導(dǎo)致事件序列被取消,那么通常不會(huì)有太多事情發(fā)生。您的應(yīng)用程序?qū)?huì)收到一個(gè)ACTION_CANCEL事件,但是由于事件已經(jīng)被取消,您無法執(zhí)行任何進(jìn)一步的操作。如果您希望避免這種情況發(fā)生,您可以嘗試使用requestDisallowInterceptTouchEvent()方法來防止觸摸事件序列被攔截,或者重新設(shè)計(jì)您的UI以確保用戶不會(huì)意外地移動(dòng)手指到View的范圍外。

延伸閱讀1:ACTION_CANCEL作用

我們知道如果某一個(gè)子View處理了Down事件,那么隨之而來的Move和Up事件也會(huì)交給它處理。但是交給它處理之前,父View還是可以攔截事件的,如果攔截了事件,那么子View就會(huì)收到一個(gè)Cancel事件,并且不會(huì)收到后續(xù)的Move和Up事件。

聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
10年以上業(yè)內(nèi)強(qiáng)師集結(jié),手把手帶你蛻變精英
請(qǐng)您保持通訊暢通,專屬學(xué)習(xí)老師24小時(shí)內(nèi)將與您1V1溝通
免費(fèi)領(lǐng)取
今日已有369人領(lǐng)取成功
劉同學(xué) 138****2860 剛剛成功領(lǐng)取
王同學(xué) 131****2015 剛剛成功領(lǐng)取
張同學(xué) 133****4652 剛剛成功領(lǐng)取
李同學(xué) 135****8607 剛剛成功領(lǐng)取
楊同學(xué) 132****5667 剛剛成功領(lǐng)取
岳同學(xué) 134****6652 剛剛成功領(lǐng)取
梁同學(xué) 157****2950 剛剛成功領(lǐng)取
劉同學(xué) 189****1015 剛剛成功領(lǐng)取
張同學(xué) 155****4678 剛剛成功領(lǐng)取
鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
董同學(xué) 138****2867 剛剛成功領(lǐng)取
周同學(xué) 136****3602 剛剛成功領(lǐng)取
相關(guān)推薦HOT
linux有什么優(yōu)點(diǎn)?

1、開源Linux的主要優(yōu)點(diǎn)之一是它是一個(gè)開放源代碼的操作系統(tǒng),即每個(gè)人都可以輕松獲得其源代碼。任何有編程能力的人都可以出于任何目的貢獻(xiàn),修...詳情>>

2023-10-12 23:08:52
Python特點(diǎn)及應(yīng)用?

一、Python的特點(diǎn)Python是一種高級(jí)編程語言,由Guido van Rossum于上世紀(jì)90年代初開發(fā),它具有以下特點(diǎn):1、語法簡(jiǎn)潔易讀Python使用縮進(jìn)來表示...詳情>>

2023-10-12 23:00:52
為什么Oracle收購(gòu)MySQL后仍保證其開源免費(fèi)?

一、為什么Oracle收購(gòu)MySQL后仍保證其開源免費(fèi)MySQL在收購(gòu)前一直使用GPL許可分發(fā),而GPL許可是不可撤銷的,這意味著至少被收購(gòu)之前的最后一個(gè)Re...詳情>>

2023-10-12 22:52:49
為什么MySQL對(duì)SQL標(biāo)準(zhǔn)中很多基本用法都不支持?

一、為什么MySQL對(duì)SQL標(biāo)準(zhǔn)中很多基本用法都不支持因?yàn)楫?dāng)年,在微軟.net技術(shù)棧下開發(fā)應(yīng)用,用的就是sql server數(shù)據(jù)庫(kù)。在特性方面,不僅緊跟sql...詳情>>

2023-10-12 22:49:20
數(shù)據(jù)庫(kù)與Microsoft Excel有什么區(qū)別?

一、數(shù)據(jù)庫(kù)與Microsoft Excel的區(qū)別1、結(jié)構(gòu)不同excel即是電子數(shù)據(jù)表,顯示由一系列行與列構(gòu)成的網(wǎng)格。。其中的單元格可以用于存放數(shù)值、計(jì)算式...詳情>>

2023-10-12 22:47:09
主站蜘蛛池模板: 国产乱码精品1区2区3区 | 日韩福利在线 | 91欧美激情一区二区三区成人 | 免费在线观看一级毛片 | 色综合久久久 | 欧美日韩亚洲国产综合 | 国产999精品久久久久久 | 激情欧美一区二区三区中文字幕 | 国产二区精品 | 欧美三级免费观看 | 免费一区二区三区 | 成年入口无限观看网站 | 在线成人 | 欧美日本免费 | 成人18视频在线观看 | 欧美一区永久视频免费观看 | 亚洲国产精品成人综合色在线婷婷 | 国产一区免费在线观看 | 污视频网站入口 | 国产精品中文字幕在线观看 | 屁屁影院一区二区三区 | 日韩精品视频在线观看网站 | 成人午夜精品一区二区三区 | 五月婷婷综合久久 | 亚洲日韩中文字幕天堂不卡 | 亚洲一区综合 | 91高清免费 | 久久亚洲精品国产一区 | 日韩在线精品 | 一级黄色录象片 | 有码在线播放 | 欧美日韩精品一区二区在线观看 | 亚洲福利 | 理论黄色片| 午夜精品福利一区二区三区蜜桃 | 久久久久国产一区二区三区小说 | 久久精品| 欧美一区三区三区高中清蜜桃 | 久久精品在线观看视频 | 久草久草久| 亚洲最新视频在线观看 |