敘述
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),玉龍企業(yè)網(wǎng)站建設(shè),玉龍品牌網(wǎng)站建設(shè),網(wǎng)站定制,玉龍網(wǎng)站建設(shè)報價,網(wǎng)絡營銷,網(wǎng)絡優(yōu)化,玉龍網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。滑動沖突可以說是日常開發(fā)中比較常見的一類問題,也是比較讓人頭疼的一類問題,尤其是在使用第三方框架的時候,兩個原本完美的控件,組合在一起之后,忽然發(fā)現(xiàn)整個世界都不好了。
關(guān)于滑動沖突
滑動沖突分類
滑動沖突,總的來說就是兩類。
1、同方向滑動沖突
比如ScrollView嵌套ListView,或者是ScrollView嵌套自己
2、不同方向滑動沖突
比如ScrollView嵌套ViewPager,或者是ViewPager嵌套ScrollView,這種情況其實很典型。現(xiàn)在大部分應用最外層都是ViewPager+Fragment 的底部切換(比如微信)結(jié)構(gòu),這種時候,就很容易出現(xiàn)滑動沖突。不過ViewPager里面無論是嵌套ListView還是ScrollView,滑動沖突是沒有的,畢竟是官方的東西,可能已經(jīng)考慮到了這些,所以比較完善。
復雜一點的滑動沖突,基本上就是這兩個沖突結(jié)合的結(jié)果。
滑動沖突解決思路
滑動沖突,就其本質(zhì)來說,兩個不同方向(或者是同方向)的View,其中有一個是占主導地位的,每次總是搶著去處理外界的滑動行為,這樣就導致一種很別扭的用戶體驗,明明只是橫向的滑動了一下,縱向的列表卻在垂直方向發(fā)生了動作。就是說,這個占主導地位的View,每一次都身不由己的攔截了這個滑動的動作,因此,要解決滑動沖突,就是得明確告訴這個占主導地位的View,什么時候你該攔截,什么時候你不應該攔截,應該由下一層的View去處理這個滑動動作。
這里不明白的同學,可以去了解一下Android Touch事件的分發(fā)機制,這也是解決滑動沖突的核心知識。
第二種滑動沖突,解決起來是比較簡單的。這里就結(jié)合例子說一下。
滑動沖突
這里,說一下背景情況。之前做下拉刷新、上拉加載更多時一直使用的是PullToRefreshView這個控件,因為很方便,不用導入三方工程。在其內(nèi)部可以放置ListView,GridView及ScrollView,非常方便,用起來可謂是屢試不爽。但是直到有一天,因項目需要,在ListView頂部加了一個輪播圖控件BannerView。結(jié)果發(fā)現(xiàn)輪播圖滑動的時候,和縱向的下拉刷新組件沖突了。
如之前所說,解決滑動沖突的關(guān)鍵,就是明確告知接收到Touch的View,是否需要攔截此次事件。
解決方法
解決方案1,從外部攔截機制考慮
這里,相當于是PullToRefreshView嵌套了ViewPager,那么每次優(yōu)先接收到Touch事件的必然是PullToRefreshView。因為正常情況下,父控件會優(yōu)先接收到touch事件。這樣就清楚了,看代碼:
在PullToRefreshView的onInterceptTouchEvent方法中:
@Override public boolean onInterceptTouchEvent(MotionEvent e) { int y = (int) e.getRawY(); int x = (int) e.getRawX(); boolean resume = false; switch (e.getAction()) { case MotionEvent.ACTION_DOWN: // 發(fā)生down事件時,記錄y坐標 mLastMotionY = y; mLastMotionX = x; resume = false; break; case MotionEvent.ACTION_MOVE: // deltaY > 0 是向下運動,< 0是向上運動 int deltaY = y - mLastMotionY; int deleaX = x - mLastMotionX; if (Math.abs(deleaX) > Math.abs(deltaY)) { resume = false; } else { //當前正處于滑動 if (isRefreshViewScroll(deltaY)) { resume = true; } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: break; } return resume; }