1 以下的場景都是乙各,使用viewpager2實現(xiàn)了抖音視頻切換播放的場景邏輯
需求是 要求觀看到某一集視頻要求該視頻必須完整看完墨礁,才能切換到下一集視頻。
此刻 我們必須將viewpager2切換到當前的fragment進行上滑攔截耳峦,或者上滑攔截
2 大家通常的用法是重寫viewpager2恩静,但是 viewpager2 是final類型,禁止重寫蹲坷。我們只能另尋方案
3 可能大家會覺得比較簡單驶乾,但是你測試的時候會發(fā)現(xiàn),如果上劃一下段距離循签,在下拉 必然可以拉倒下一個item级乐,攔截事件只有在當前的item在屏幕底部的時候有效,有時候就無法攔截县匠,這個很煩躁风科。
4 解決方法是 它本身是用了recycleview,你可以把他當成這個乞旦。也就是說 我們需要監(jiān)聽每一個recycleview的item的 touch事件贼穆,進行實踐攔截。
5 上代碼
1
override fun onStart() {
super.onStart()
setScroll()
}
private fun setScroll() {
// Initialize the NoSwipeItemTouchListener with default settings
noSwipeListener = NoSwipeItemTouchListener(
currentpostion,
requireContext(),
disableUpScroll = false,
disableDownScroll = false
)
touchInterceptor = ViewPagerTouchInterceptor(getViewPager())
// touchInterceptor.addTouchInterceptorToViewPager(noSwipeListener)
// 上劃和下滑都可以滑動
setVerticalScroll(true, true)
}
// 設(shè)置是否可以上劃或者下滑 false 不可以滑動 true 可以滑動
fun setVerticalScroll(up: Boolean, down: Boolean) {
// Remove existing listener
touchInterceptor?.removeTouchInterceptorFromViewPager()
// Create a new listener with updated settings
noSwipeListener = NoSwipeItemTouchListener(
currentpostion,
requireContext(),
disableUpScroll = up,
disableDownScroll = down
)
touchInterceptor.addTouchInterceptorToViewPager(noSwipeListener)
}
override fun onDestroy() {
super.onDestroy()
RecrodTypeManager.setUserFeed("play")
touchInterceptor?.removeTouchInterceptorFromViewPager()
touchInterceptor == null
}
2 攔截器兰粉,重點就是 move方法里的故痊,我要獲取 rv.scrollToPosition(position)
,這個方法在你向下滑動后玖姑,如果突然向上滑動愕秫,我們要進行攔截慨菱,不然此時快速切換,是可以滑動到下一個item的豫领,我們要滑動回當前位置抡柿。這個是重點
class NoSwipeItemTouchListener(
private val position: Int,
context: Context,
private val disableUpScroll: Boolean = false,
private val disableDownScroll: Boolean = false
) : RecyclerView.OnItemTouchListener {
// private var startY = 0f
private val threshold = 5 // 滑動閾值,根據(jù)需要調(diào)整
private var startX = 0f
private var startY = 0f
private var lastX = 0f
private var lastY = 0f
private var diffY = 0f
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
// startY = e.y
startX = event.x
startY = event.y
lastX = startX
lastY = startY
}
MotionEvent.ACTION_MOVE -> {
val currentX = event.x
val currentY = event.y
val diffX = currentX - lastX
diffY = currentY - lastY
if (Math.abs(diffX) > threshold || Math.abs(diffY) > threshold) {
if (Math.abs(diffX) > Math.abs(diffY)) {
// 左右滑動
if (diffX > 0) {
onSwipeRight()
} else {
onSwipeLeft()
}
} else {
// 上下滑動
if (diffY > 0) {
// LogUtil.d("diffY", "diffY: diffY")
//如果向上滑動禁止了 則攔截這個事件 等恐,并且回到原位
if (!disableUpScroll) {
if (diffY<-5){
rv.scrollToPosition(position)
LogUtil.d("scrollToPosition", "scrollToPosition")
}
return true
}
}
}
// 更新lastX和lastY以適應(yīng)連續(xù)滑動
lastX = currentX
lastY = currentY
}
}
MotionEvent.ACTION_UP,MotionEvent.ACTION_CANCEL -> {
// 結(jié)束時重置狀態(tài)
startX = 0f
startY = 0f
lastX = 0f
lastY = 0f
}
}
return false
}
private fun onSwipeRight() {
LogUtil.d("SwipeDirection", "Detected right")
// 處理向右滑動邏輯
}
private fun onSwipeLeft() {
LogUtil.d("SwipeDirection", "Detected left")
// 處理向左滑動邏輯
}
private fun onSwipeUp() {
LogUtil.d("SwipeDirection", "Detected up")
// 處理向上滑動邏輯
}
private fun onSwipeDown() {
LogUtil.d("SwipeDirection", "Detected down")
// 處理向下滑動邏輯
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
3 viewpager2 設(shè)置每一個item的監(jiān)聽方法
class ViewPagerTouchInterceptor(private val viewPager: ViewPager2?) {
private var recyclerView: RecyclerView? = null
private var listener: RecyclerView.OnItemTouchListener? = null
init {
recyclerView = getRecyclerViewFromViewPager(viewPager)
}
private fun getRecyclerViewFromViewPager(viewPager: ViewPager2?): RecyclerView? {
for (i in 0 until (viewPager?.childCount ?: 0)) {
val child = viewPager?.getChildAt(i)
if (child is RecyclerView) {
return child
}
}
return null
}
fun addTouchInterceptorToViewPager(listener: RecyclerView.OnItemTouchListener) {
this.listener = listener
recyclerView?.addOnItemTouchListener(listener)
}
fun removeTouchInterceptorFromViewPager() {
listener?.let {
recyclerView?.removeOnItemTouchListener(it)
}
}
}
4 里面的getviewpager是我項目里的實例洲劣,自己自行替換即可