Android滑動(dòng)沖突的解決技巧
滑動(dòng)沖突的原理
Android
的事件分發(fā)機(jī)制是基于ViewGroup
的。當(dāng)用戶在屏幕上觸摸時(shí),事件會(huì)首先傳遞給最頂層的ViewGroup
。ViewGroup
會(huì)根據(jù)自己的滑動(dòng)方向和滑動(dòng)能力來(lái)決定是否攔截事件。如果ViewGroup
攔截了事件,則事件不會(huì)傳遞給子View
。如果ViewGroup
沒(méi)有攔截事件,則事件會(huì)傳遞給子View
。
如果子View
也需要響應(yīng)滑動(dòng)事件,則子View
需要重寫(xiě)onTouchEvent()
方法來(lái)處理事件。子View
可以通過(guò)requestDisallowInterceptTouchEvent()
方法來(lái)告訴父ViewGroup
不要攔截事件。
滑動(dòng)沖突是指兩個(gè)或多個(gè)View
同時(shí)收到滑動(dòng)事件,導(dǎo)致無(wú)法正?;瑒?dòng)?;瑒?dòng)沖突的原因有很多,例如:
- 兩個(gè)
View
的滑動(dòng)方向相同,例如RecyclerView
和ScrollView
同時(shí)滑動(dòng)。 - 兩個(gè)
View
的滑動(dòng)方向不同,但滑動(dòng)范圍重疊,例如HorizontalScrollView
和WebView
同時(shí)滑動(dòng)。
解決方法
Android
滑動(dòng)沖突的主要解決思想有兩種:外部攔截法和內(nèi)部攔截法。
- 外部攔截法:由父
View
攔截事件,然后根據(jù)需要將事件傳遞給子View
。 - 內(nèi)部攔截法:由子
View
攔截事件,然后根據(jù)需要將事件傳遞給父View
。
外部攔截法
外部攔截法是Android
默認(rèn)的滑動(dòng)沖突解決方式。在這種方式下,父View
會(huì)先攔截事件,然后根據(jù)需要將事件傳遞給子View
。
父View
可以通過(guò)重寫(xiě)onInterceptTouchEvent()
方法來(lái)實(shí)現(xiàn)外部攔截法。在onInterceptTouchEvent()
方法中,我們可以根據(jù)事件的類型和位置來(lái)判斷是否需要攔截事件。如果需要攔截事件,則返回true
,否則返回false
。
class CustomParentView(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs) { private var downX: Float = 0F private var downY: Float = 0F override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { when (ev.action) { MotionEvent.ACTION_DOWN -> { downX = ev.x downY = ev.y } MotionEvent.ACTION_MOVE -> { val deltaX = ev.x - downX val deltaY = ev.y - downY // 根據(jù)滑動(dòng)方向判斷是否攔截事件 if (Math.abs(deltaX) > Math.abs(deltaY)) { return true } } } return super.onInterceptTouchEvent(ev) } override fun onTouchEvent(event: MotionEvent): Boolean { // 處理滑動(dòng)邏輯 return true } // 其他相關(guān)代碼 }
優(yōu)點(diǎn): 簡(jiǎn)單易用,適用于大多數(shù)滑動(dòng)沖突問(wèn)題。
缺點(diǎn): 可能會(huì)導(dǎo)致父ViewGroup
無(wú)法響應(yīng)事件,例如父ViewGroup
的子View
正在滑動(dòng),而父ViewGroup
的滑動(dòng)事件也被攔截了。
內(nèi)部攔截法
內(nèi)部攔截法是指由子View
攔截事件,然后根據(jù)需要將事件傳遞給父View
。
子View
可以通過(guò)重寫(xiě)dispatchTouchEvent()
方法來(lái)實(shí)現(xiàn)內(nèi)部攔截法。在dispatchTouchEvent()
方法中,我們可以根據(jù)事件的類型和位置來(lái)判斷是否需要攔截事件。如果需要攔截事件,則調(diào)用requestDisallowInterceptTouchEvent()
方法來(lái)告訴父View
不要攔截事件。
class MyView : View { // 通過(guò)重寫(xiě) dispatchTouchEvent 方法實(shí)現(xiàn)內(nèi)部攔截 override fun dispatchTouchEvent(ev: MotionEvent): Boolean { when (ev.action) { MotionEvent.ACTION_DOWN -> { // 按下時(shí),禁止父View攔截事件 parent.requestDisallowInterceptTouchEvent(true) } MotionEvent.ACTION_MOVE -> { // 根據(jù)業(yè)務(wù)邏輯判斷是否攔截事件 if (shouldInterceptTouchEvent(ev)) { return true } } MotionEvent.ACTION_UP -> { // 手指抬起時(shí),允許父View攔截事件 parent.requestDisallowInterceptTouchEvent(false) } } return super.dispatchTouchEvent(ev) } }
優(yōu)點(diǎn): 不會(huì)導(dǎo)致父ViewGroup
無(wú)法響應(yīng)事件,適用于父ViewGroup
和子View
都需要滑動(dòng)的情況。
缺點(diǎn): 需要重寫(xiě)子View
的dispatchTouchEvent()
方法,可能會(huì)導(dǎo)致代碼復(fù)雜。
注意事項(xiàng)和優(yōu)化技巧
- 在判斷是否需要攔截事件時(shí),需要考慮事件的方向、滑動(dòng)距離等因素。
- 如果父
ViewGroup
和子View
都需要滑動(dòng),則可以使用事件分發(fā)機(jī)制來(lái)解決滑動(dòng)沖突。 - 避免過(guò)多的嵌套, 盡量減少布局的嵌套層次,以降低滑動(dòng)沖突的概率。
總結(jié)
Android
滑動(dòng)沖突的解決方式主要有外部攔截法和內(nèi)部攔截法兩種。希望本文能幫助讀者解決滑動(dòng)沖突問(wèn)題,提高Android
開(kāi)發(fā)水平。
到此這篇關(guān)于Android滑動(dòng)沖突的解決方式的文章就介紹到這了,更多相關(guān)Android滑動(dòng)沖突內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android時(shí)分秒計(jì)時(shí)器的兩種實(shí)現(xiàn)方法
這篇文章主要介紹了Android時(shí)分秒計(jì)時(shí)器的兩種實(shí)現(xiàn)方法,分別是Chronometer控件和handler+timer+timerTask方式,非常不錯(cuò),感興趣的朋友一起看下吧2016-08-08Android實(shí)現(xiàn)3D層疊式卡片圖片展示
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)3D層疊式卡片圖片展示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10Android實(shí)現(xiàn)獲取meta-data和build.gradle的值
這篇文章主要介紹了Android實(shí)現(xiàn)獲取meta-data和build.gradle的值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03Android應(yīng)用中內(nèi)嵌SQLite數(shù)據(jù)庫(kù)的基本操作指南
這篇文章主要介紹了Android應(yīng)用中內(nèi)嵌SQLite數(shù)據(jù)庫(kù)的基本操作指南,包括創(chuàng)建DAO類接口以及相關(guān)的增刪查改等操作的明說(shuō),需要的朋友可以參考下2016-02-02Android 判斷ip地址合法實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 判斷ip地址合法實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-06-06Android自定義AvatarImageView實(shí)現(xiàn)頭像顯示效果
這篇文章主要為大家詳細(xì)介紹了Android自定義AvatarImageView實(shí)現(xiàn)頭像顯示效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09使用RoundedBitmapDrawable生成圓角圖片的方法
由于RoundedBitmapDrawable類沒(méi)有直接提供生成圓形圖片的方法,所以生成圓形圖片首先需要對(duì)原始圖片進(jìn)行裁剪,將圖片裁剪成正方形,最后再生成圓形圖片,具體實(shí)現(xiàn)方法,可以參考下本文2016-09-09