最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android滑動事件沖突的解決方法

 更新時(shí)間:2017年03月03日 14:31:09   作者:lylodlig  
這篇文章主要為大家詳細(xì)介紹了Android滑動事件沖突的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

滑動是Android中不可缺少的一部分,多個(gè)滑動必然會產(chǎn)生沖突,比如我們最常見的是ScrollView中嵌套了ListView,一般做法是計(jì)算出ListView的總高度,這樣就不用去滑動ListView了。又比如一個(gè)ViewPager嵌套Fragment,F(xiàn)ragment里面又有ListView,這原本是有滑動沖突的,但是ViewPager內(nèi)部去幫我們解決了這種沖突。那如果我們要自己解決沖突又該怎么辦呢。

下面有兩種方式來解決:

外部攔截法
外部攔截法是指在有點(diǎn)擊事件時(shí)都要經(jīng)過父容器,那么在父容器時(shí)如果需要攔截就攔截自己處理,不需要?jiǎng)t傳遞給下一層進(jìn)行處理,下面看個(gè)例子:

首先定義一個(gè)水平滑動的HorizontalScrollViewEx,看主要代碼

主要的攔截是需要重寫onInterceptTouchEvent

@Override 
 public boolean onInterceptTouchEvent(MotionEvent ev) { 
 boolean intercepted = false; 
 int x = (int) ev.getX(); 
 int y = (int) ev.getY(); 
 switch (ev.getAction()) { 
 case MotionEvent.ACTION_DOWN: 
 //down事件不攔截,否則無法傳給子元素 
 intercepted = false; 
 if (!mScroller.isFinished()) { 
  mScroller.abortAnimation(); 
  intercepted = true; 
 } 
 break; 
 case MotionEvent.ACTION_MOVE: 
 int deltaX = x - mLastXIntercept; 
 int deltaY = y - mLastYIntercept; 
 //水平滑動則攔截 
 if (Math.abs(deltaX) > Math.abs(deltaY) + 5) { 
  intercepted = true; 
 } else { 
  intercepted = false; 
 } 
 break; 
 case MotionEvent.ACTION_UP: 
 //不攔截,否則子元素?zé)o法收到 
 intercepted = false; 
 break; 
 } 
 //因?yàn)楫?dāng)ViewGroup中的子View可能消耗了down事件,在onTouchEvent無法獲取, 
 // 無法對mLastX賦初值,所以在這里賦值一次 
 mLastX = x; 
 mLastY = y; 
 mLastYIntercept = y; 
 mLastXIntercept = x; 
 return intercepted; 
 } 

在down事件不需要攔截,返回false,否則的話子view無法收到事件,將全部會由父容器處理,這不是希望的;up事件也要返回false,否則最后子view收不到。

看看move事件,當(dāng)水平滑動距離大于豎直距離時(shí),代表水平滑動,返回true,由父類來進(jìn)行處理,否則交由子view處理。這里move事件就是主要的攔截條件判斷,如果你遇到的不是水平和豎直的條件這么簡單,就可以在這里進(jìn)行改變,比如,ScrollView嵌套了ListView,條件就變成,當(dāng)ListView滑動到底部或頂部時(shí),返回true,交由父類滑動處理,否則自身ListView滑動。

在onTouchEvent中主要是做的滑動切換的處理

@Override 
 public boolean onTouchEvent(MotionEvent event) { 
 mVelocityTracker.addMovement(event); 
 int x = (int) event.getX(); 
 int y = (int) event.getY(); 
 switch (event.getAction()) { 
 case MotionEvent.ACTION_DOWN: 
 if (!mScroller.isFinished()) { 
  mScroller.abortAnimation(); 
 } 
 break; 
 case MotionEvent.ACTION_MOVE: 
 int deltaX = x - mLastX; 
 int deltaY = y - mLastY; 
 if (getScrollX() < 0) { 
  scrollTo(0, 0); 
 } 
 scrollBy(-deltaX, 0); 
 break; 
 case MotionEvent.ACTION_UP: 
 int scrollX = getScrollX(); 
 mVelocityTracker.computeCurrentVelocity(1000); 
 float xVelocityTracker = mVelocityTracker.getXVelocity(); 
 if (Math.abs(xVelocityTracker) > 50) {//速度大于50則滑動到下一個(gè) 
  mChildIndex = xVelocityTracker > 0 ? mChildIndex - 1 : mChildIndex + 1; 
 } else { 
  mChildIndex = (scrollX + mChildWith / 2) / mChildWith; 
 } 
 mChildIndex = Math.max(0, Math.min(mChildIndex, mChildrenSize - 1)); 
 int dx = mChildIndex * mChildWith - scrollX; 
 smoothScrollBy(dx, 0); 
 mVelocityTracker.clear(); 
 break; 
 } 
 mLastY = y; 
 mLastX = x; 
 return true; 
 } 

在這個(gè)嵌套一個(gè)普通的ListView,這樣就可以解決水平和豎直滑動沖突的問題了。

<com.example.lzy.customview.HorizontalScrollViewEx 
 android:layout_width="match_parent" 
 android:layout_height="200dp"> 
 
 <ListView 
 android:id="@+id/listView" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" /> 
 
 <Button 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:background="@android:color/holo_blue_bright" 
 android:text="2" /> 
 
 <Button 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:background="@android:color/holo_green_dark" 
 android:text="3" /> 
 </com.example.lzy.customview.HorizontalScrollViewEx> 

其他的部分代碼如果需要可以下載源碼來看

內(nèi)部攔截法

內(nèi)部攔截法是父容器不攔截任何事件,所有事件都傳遞給子view,如果需要就直接消耗掉,不需要再傳給父容器處理

下面重寫一個(gè)ListView,只需要重寫一個(gè)dispatchTouchEvent方法就OK

public class ListViewEx extends ListView { 
 
 private static final String TAG = "lzy"; 
 private int mLastX; 
 private int mLastY; 
 
 public ListViewEx(Context context) { 
 super(context); 
 } 
 
 public ListViewEx(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 } 
 
 public ListViewEx(Context context, AttributeSet attrs, int defStyleAttr) { 
 super(context, attrs, defStyleAttr); 
 } 
 
 
 @Override 
 public boolean dispatchTouchEvent(MotionEvent ev) { 
 int x = (int) ev.getX(); 
 int y = (int) ev.getY(); 
 
 switch (ev.getAction()) { 
 case MotionEvent.ACTION_DOWN: 
 //子View的所有父ViewGroup都會跳過onInterceptTouchEvent的回調(diào) 
 getParent().requestDisallowInterceptTouchEvent(true); 
 break; 
 case MotionEvent.ACTION_MOVE: 
 int deltaX = x - mLastX; 
 int deltaY = y - mLastY; 
 if (Math.abs(deltaX) > Math.abs(deltaY) + 5) {//水平滑動,使得父類可以執(zhí)行onInterceptTouchEvent 
  getParent().requestDisallowInterceptTouchEvent(false); 
 } 
 break; 
 } 
 mLastX = x; 
 mLastY = y; 
 return super.dispatchTouchEvent(ev); 
 } 
} 

在down事件調(diào)用getParent().requestDisallowInterceptTouchEvent(true),這句代碼的意思是使這個(gè)view的父容器都會跳過onInterceptTouchEvent,在move中判斷如果是水平滑動就由父容器去處理,父容器只需要把之前的onInterceptTouchEvent改為下面那樣,其他不變。

@Override 
 public boolean onInterceptTouchEvent(MotionEvent ev) { 
 int x = (int) ev.getX(); 
 int y = (int) ev.getY(); 
 if (ev.getAction() == MotionEvent.ACTION_DOWN) { 
 mLastX = x; 
 mLastY = y; 
 if (!mScroller.isFinished()) { 
 mScroller.abortAnimation(); 
 return true; 
 } 
 return false; 
 } else { 
 //如果是非down事件,說明子View并沒有攔截父類的onInterceptTouchEvent 
 //說明該事件交由父類處理,所以不需要再傳遞給子類,返回true 
 return true; 
 } 
 } 

最終實(shí)現(xiàn)效果就是下面那樣,兩個(gè)是用兩種方式實(shí)現(xiàn)的,上面的圓圈是一個(gè)簡單的自定義View練習(xí)

下載地址:Android滑動事件沖突

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android自定義ViewGroup橫向布局(1)

    Android自定義ViewGroup橫向布局(1)

    這篇文章主要介紹了Android自定義ViewGroup橫向布局,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • android自定義可拖拽的儀表盤

    android自定義可拖拽的儀表盤

    這篇文章主要為大家詳細(xì)介紹了android自定義可拖拽的儀表盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Kotlin基礎(chǔ)通關(guān)之字符串與數(shù)字類型

    Kotlin基礎(chǔ)通關(guān)之字符串與數(shù)字類型

    這篇文章主要介紹了Kotlin基礎(chǔ)知識中的字符串與數(shù)字類型,編程中的入門知識,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Android Studio 視頻播放失敗 start called in state1 異常怎么解決

    Android Studio 視頻播放失敗 start called in state1 異常怎么解決

    很多朋友問小編在使用MediaPlayer播放音頻時(shí)報(bào)出 E/MediaPlayerNative: start called in state 1, mPlayer(0x0)問題,該如何處理呢,今天小編給大家?guī)砹薃ndroid Studio 視頻播放失敗 start called in state1 異常問題,需要的朋友可以參考下
    2020-03-03
  • Flutter實(shí)現(xiàn)笑嘻嘻的動態(tài)表情的示例代碼

    Flutter實(shí)現(xiàn)笑嘻嘻的動態(tài)表情的示例代碼

    這篇文章主要為大家介紹了如何利用Flutter實(shí)現(xiàn)笑嘻嘻的動態(tài)表情,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Flutter有一定幫助,感興趣的可以了解一下
    2022-04-04
  • android網(wǎng)絡(luò)圖片查看器簡單實(shí)現(xiàn)代碼

    android網(wǎng)絡(luò)圖片查看器簡單實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了android網(wǎng)絡(luò)圖片查看器的簡單實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Android中使用findViewByMe提升組件查找效率

    Android中使用findViewByMe提升組件查找效率

    本文主要介紹了Android中使用findViewByMe提升組件查找效率的相關(guān)知識。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • Android使用AlarmManager設(shè)置鬧鐘功能

    Android使用AlarmManager設(shè)置鬧鐘功能

    這篇文章主要為大家詳細(xì)介紹了Android使用AlarmManager設(shè)置鬧鐘功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • 深入淺析Android Fragment(下篇)

    深入淺析Android Fragment(下篇)

    本篇文章給大家介紹如何管理Fragment回退棧,F(xiàn)ragment如何與Activity交互,F(xiàn)ragment與Activity交互的最佳實(shí)踐,沒有視圖的Fragment的用處,使用Fragment創(chuàng)建對話框,如何與ActionBar,MenuItem集成,對Android Fragment感興趣的朋友可以參考下本篇文章
    2015-10-10
  • Android仿QQ復(fù)制昵稱效果

    Android仿QQ復(fù)制昵稱效果

    這幾天做一個(gè)復(fù)制文本的需求,突然看到QQ上復(fù)制昵稱跟QQ號的效果,覺得很不錯(cuò),就想要模仿一波,辦法比較簡單粗暴,反編譯QQ獲取了那個(gè).9圖片,然后就是用PopWindow實(shí)現(xiàn)了,需要的朋友可以參考下
    2019-05-05

最新評論

阳东县| 叙永县| 益阳市| 荃湾区| 久治县| 城固县| 鸡泽县| 靖边县| 利津县| 天等县| 桦甸市| 栾城县| 房山区| 旌德县| 洛隆县| 休宁县| 大关县| 开原市| 宝丰县| 扎囊县| 五峰| 郴州市| 望城县| 石河子市| 广水市| 北流市| 武山县| 吉林市| 贵德县| 读书| 托克托县| 炉霍县| 屏山县| 东兰县| 武宣县| 桐乡市| 大同市| 犍为县| 姜堰市| 长兴县| 若尔盖县|