滑動(dòng)沖突1

1.先來看看原始需求,自定義一個(gè)seekbar

關(guān)鍵代碼如下益兄,

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                lastX = event.rawX.toInt()
                if (isStartAnimator) {
                    return false
                }
                // check finger is touch above slide
                if (event.x > slideLeft && event.x < slideBitmap.width + slideLeft) {
                    slideIsMoving = true
                    return true
                }
            }
            MotionEvent.ACTION_MOVE -> {
                val dx = event.rawX.toInt() - lastX
                slideLeft += dx
                if (slideLeft < 0) {
                    slideLeft = 0
                }
                if (slideLeft > slideBgWidth + margin * 2 - slideBitmap.width) {
                    slideLeft = slideBgWidth + margin * 2 - slideBitmap.width
                }
                if (slideIsMoving) {
                    invalidate()
                    lastX = event.rawX.toInt()
                }
            }
            MotionEvent.ACTION_UP -> if (slideIsMoving) {
                backZero()
                slideIsMoving = false
            }
            else -> {
            }
        }
        return super.onTouchEvent(event)
    }

主要流程就是監(jiān)聽用戶觸摸事件节视,當(dāng)用戶點(diǎn)擊在滑塊上面時(shí)彻况,開始處理用戶滑動(dòng)事件(ACTION_DOWN 返回true)背伴,然后計(jì)算用戶滑動(dòng)距離树姨,修改slideLeft 值蹈集,并且調(diào)用invalidate() 刷新界面经宏。在onDraw中根據(jù)slideLeft值犀暑,修改滑塊位置。

2.新的需求是在viewpager中烛恤,此時(shí)我的滑動(dòng)就出現(xiàn)了問題

jumkq-xh0uv.gif

查看日志如下:

2021-10-15 15:21:56.324 17940-17940/com.example.myapplication I/CustomSeekBar: ACTION_DOWN
2021-10-15 15:21:56.433 17940-17940/com.example.myapplication I/CustomSeekBar: ACTION_MOVE
2021-10-15 15:21:56.450 17940-17940/com.example.myapplication I/CustomSeekBar: ACTION_MOVE
2021-10-15 15:21:56.466 17940-17940/com.example.myapplication I/CustomSeekBar: ACTION_CANCEL

正常情況下應(yīng)該是down- move-up
此時(shí)出現(xiàn)了down-move-cancel
為什么會(huì)這樣呢母怜?

3.咱們帶著問題來分析一下Android的事件分發(fā)處理流程

咱們從activity接收到事件開始,底層的不用在意缚柏。

先來看看activity布局層級(jí)

基于Android SDK 30普通布局


image.png

activity布局如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/xml_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.viewpager.widget.CustomViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

圖中可以看到activity苹熏,和window其實(shí)都不是view,DecorView才是咱們布局的頂層view币喧,然后到咱們自己的布局上一共已經(jīng)有5層view轨域。從第6層起,剛好就是咱們自己布局文件的根view杀餐。

seekBar onTouchEvent調(diào)用棧
再來看看activity事件分化流程
簡易事件分發(fā).png

以下是一次完整的事件分化處理過程:

請(qǐng)注意干发,viewPager onTouchEvent 默認(rèn)返回true,以下log是我修改代碼后的
2021-10-19 16:48:21.917 4857-4857/com.example.myapplication I/GUOHENG: SeekBarActivity dispatchTouchEvent
2021-10-19 16:48:21.925 4857-4857/com.example.myapplication I/GUOHENG: CustomViewPager dispatchTouchEvent
2021-10-19 16:48:21.926 4857-4857/com.example.myapplication I/GUOHENG: CustomViewPager onInterceptTouchEvent
2021-10-19 16:48:21.931 4857-4857/com.example.myapplication I/GUOHENG: CustomSeekBar dispatchTouchEvent
2021-10-19 16:48:21.931 4857-4857/com.example.myapplication I/GUOHENG: CustomSeekBar onTouchEvent
2021-10-19 16:48:25.761 4857-4857/com.example.myapplication I/GUOHENG: CustomViewPager onTouchEvent
2021-10-19 16:48:28.814 4857-4857/com.example.myapplication I/GUOHENG: SeekBarActivity onTouchEvent

點(diǎn)擊seekbar時(shí)的事件分化及處理

點(diǎn)擊時(shí)
2021-10-19 17:00:41.669 5464-5464/com.example.myapplication I/GUOHENG: SeekBarActivity dispatchTouchEvent
2021-10-19 17:00:41.669 5464-5464/com.example.myapplication I/GUOHENG: CustomViewPager dispatchTouchEvent
2021-10-19 17:00:41.669 5464-5464/com.example.myapplication I/GUOHENG: CustomViewPager onInterceptTouchEvent
2021-10-19 17:00:41.670 5464-5464/com.example.myapplication I/GUOHENG: CustomSeekBar dispatchTouchEvent
2021-10-19 17:00:41.670 5464-5464/com.example.myapplication I/GUOHENG: CustomSeekBar onTouchEventACTION_DOWN
2021-10-19 17:00:41.670 5464-5464/com.example.myapplication I/GUOHENG: CustomViewPager onTouchEvent
2021-10-19 17:00:41.780 5464-5464/com.example.myapplication I/GUOHENG: SeekBarActivity dispatchTouchEvent
2021-10-19 17:00:41.780 5464-5464/com.example.myapplication I/GUOHENG: CustomViewPager dispatchTouchEvent
2021-10-19 17:00:41.780 5464-5464/com.example.myapplication I/GUOHENG: CustomViewPager onTouchEvent

滑動(dòng)seekbar時(shí)的事件分化及處理

滑動(dòng)時(shí)
2021-10-19 17:02:19.707 5577-5577/com.example.myapplication I/GUOHENG: SeekBarActivity dispatchTouchEvent
2021-10-19 17:02:19.707 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager dispatchTouchEvent
2021-10-19 17:02:19.708 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager onInterceptTouchEvent
2021-10-19 17:02:19.708 5577-5577/com.example.myapplication I/GUOHENG: CustomSeekBar dispatchTouchEvent
2021-10-19 17:02:19.708 5577-5577/com.example.myapplication I/GUOHENG: CustomSeekBar onTouchEventACTION_DOWN
2021-10-19 17:02:19.778 5577-5577/com.example.myapplication I/GUOHENG: SeekBarActivity dispatchTouchEvent
2021-10-19 17:02:19.778 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager dispatchTouchEvent
2021-10-19 17:02:19.778 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager onInterceptTouchEvent
2021-10-19 17:02:19.779 5577-5577/com.example.myapplication I/GUOHENG: CustomSeekBar dispatchTouchEvent
2021-10-19 17:02:19.779 5577-5577/com.example.myapplication I/GUOHENG: CustomSeekBar onTouchEventACTION_MOVE
2021-10-19 17:02:19.779 5577-5577/com.example.myapplication I/GUOHENG: SeekBarActivity onTouchEvent
2021-10-19 17:02:19.794 5577-5577/com.example.myapplication I/GUOHENG: SeekBarActivity dispatchTouchEvent
2021-10-19 17:02:19.794 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager dispatchTouchEvent
2021-10-19 17:02:19.794 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager onInterceptTouchEvent
2021-10-19 17:02:19.795 5577-5577/com.example.myapplication I/GUOHENG: CustomSeekBar dispatchTouchEvent
2021-10-19 17:02:19.795 5577-5577/com.example.myapplication I/GUOHENG: CustomSeekBar onTouchEventACTION_MOVE
2021-10-19 17:02:19.795 5577-5577/com.example.myapplication I/GUOHENG: SeekBarActivity onTouchEvent
2021-10-19 17:02:19.812 5577-5577/com.example.myapplication I/GUOHENG: SeekBarActivity dispatchTouchEvent
2021-10-19 17:02:19.813 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager dispatchTouchEvent
2021-10-19 17:02:19.813 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager onInterceptTouchEvent
2021-10-19 17:02:19.814 5577-5577/com.example.myapplication I/GUOHENG: CustomSeekBar dispatchTouchEvent
2021-10-19 17:02:19.814 5577-5577/com.example.myapplication I/GUOHENG: CustomSeekBar onTouchEventACTION_CANCEL
2021-10-19 17:02:19.816 5577-5577/com.example.myapplication I/GUOHENG: SeekBarActivity onTouchEvent
2021-10-19 17:02:19.828 5577-5577/com.example.myapplication I/GUOHENG: SeekBarActivity dispatchTouchEvent
2021-10-19 17:02:19.828 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager dispatchTouchEvent
2021-10-19 17:02:19.828 5577-5577/com.example.myapplication I/GUOHENG: CustomViewPager onTouchEvent

出現(xiàn)滑動(dòng)沖突原因就是父view將事件搶過去處理了史翘,給我們發(fā)了cancel事件枉长。導(dǎo)致后續(xù)move事件被父view處理,seekbar接收不到后續(xù)事件琼讽。
通過視頻也能看到滑動(dòng)一段距離后必峰,viewpager出現(xiàn)了滑動(dòng)不了的提示。關(guān)鍵代碼如下:


viewpager.java   onInterceptTouchEvent()
            case MotionEvent.ACTION_MOVE: {
               ......
                if (xDiff > mTouchSlop && xDiff * 0.5f > yDiff) {
                     Log.v(TAG, "Starting drag!" + mTouchSlop);
                    mIsBeingDragged = true;
                    requestParentDisallowInterceptTouchEvent(true);
                    setScrollState(SCROLL_STATE_DRAGGING);
                    mLastMotionX = dx > 0
                            ? mInitialMotionX + mTouchSlop : mInitialMotionX - mTouchSlop;
                    mLastMotionY = y;
                    setScrollingCacheEnabled(true);
                } 

viewGroup.java
        if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {
            event.setAction(MotionEvent.ACTION_CANCEL);
            if (child == null) {
                handled = super.dispatchTouchEvent(event);
            } else {
                handled = child.dispatchTouchEvent(event);
            }
            event.setAction(oldAction);
            return handled;
        }

解決沖突:在viewgroup中判斷是否攔截當(dāng)前事件前钻蹬,會(huì)有一個(gè)是否允許攔截的判斷吼蚁,我們可以在滑塊滑動(dòng)時(shí)不讓父親(viewpager)攔截

       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;
                }
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_MOVE -> {
                Log.i("GUOHENG", "CustomSeekBar onTouchEvent"+ "ACTION_MOVE")
......
......
               parent.requestDisallowInterceptTouchEvent(true)
            }

此刻就能正常滑動(dòng)了问欠。


0t5lo-x76hp.gif

文章參考 # [Android事件分發(fā)機(jī)制詳解:史上最全面肝匆、最易懂]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市顺献,隨后出現(xiàn)的幾起案子旗国,更是在濱河造成了極大的恐慌,老刑警劉巖注整,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粗仓,死亡現(xiàn)場離奇詭異嫁怀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)借浊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門塘淑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚂斤,你說我怎么就攤上這事存捺。” “怎么了曙蒸?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵捌治,是天一觀的道長。 經(jīng)常有香客問我纽窟,道長肖油,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任臂港,我火速辦了婚禮森枪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘审孽。我一直安慰自己县袱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布佑力。 她就那樣靜靜地躺著式散,像睡著了一般。 火紅的嫁衣襯著肌膚如雪打颤。 梳的紋絲不亂的頭發(fā)上暴拄,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音编饺,去河邊找鬼乖篷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛反肋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播踏施,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼石蔗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了畅形?” 一聲冷哼從身側(cè)響起养距,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎日熬,沒想到半個(gè)月后棍厌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年耘纱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敬肚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡束析,死狀恐怖艳馒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情员寇,我是刑警寧澤弄慰,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站蝶锋,受9級(jí)特大地震影響陆爽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扳缕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一慌闭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧第献,春花似錦贡必、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至飒赃,卻和暖如春利花,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背载佳。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工炒事, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蔫慧。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓挠乳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親姑躲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子睡扬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容