Last active
November 7, 2023 06:08
-
-
Save asadmukhtar28/affcf928f9860f44232cc360eaf2ca38 to your computer and use it in GitHub Desktop.
ChildrenSwipeHandlingMotionLayout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context | |
import android.os.SystemClock | |
import android.util.AttributeSet | |
import android.view.MotionEvent | |
import android.view.View | |
import androidx.constraintlayout.motion.widget.MotionLayout | |
import androidx.core.content.PackageManagerCompat.LOG_TAG | |
import kotlin.math.abs | |
/** | |
* Issue: In MotionLayout, swipes over a clickable view doesn't work. | |
*/ | |
class ChildrenSwipeHandlingMotionLayout @JvmOverloads constructor( | |
context: Context, | |
attrs: AttributeSet? = null, | |
defStyle: Int = 0 | |
) : MotionLayout(context, attrs, defStyle) { | |
/* | |
* we don't want to intercept for viewPager because in viewPager we have recycler that automatic | |
* handle touches/swipes gracefully with MotionLayout, we are just concerned about clickable views in headers | |
*/ | |
var viewPagerArea: View? = | |
null | |
private var onActionDownYValue = 0f | |
private var doNotAllowIntercept = false | |
private fun isInViewPagerArea(event: MotionEvent): Boolean { | |
return viewPagerArea?.let { | |
val point = IntArray(2) | |
it.getLocationOnScreen(point) | |
val (_, y) = point | |
if(y == 0) // if viewPager not shown on the screen. | |
return false | |
event.y >= y | |
} ?: true | |
} | |
override fun onInterceptTouchEvent(event: MotionEvent): Boolean { | |
return when { | |
event.actionMasked != MotionEvent.ACTION_DOWN && doNotAllowIntercept -> super.onInterceptTouchEvent( | |
event | |
) // when the user swipe from viewPagerArea, just return from here because it automatically handles the motion layout. | |
else -> when (event.actionMasked) { | |
MotionEvent.ACTION_DOWN -> { | |
onActionDownYValue = event.y | |
doNotAllowIntercept = isInViewPagerArea(event) | |
super.onInterceptTouchEvent(event) | |
} | |
MotionEvent.ACTION_MOVE -> { | |
abs(onActionDownYValue - event.y).takeIf { it > 50 }?.run { | |
onTouchEvent( | |
MotionEvent.obtain( | |
SystemClock.uptimeMillis(), | |
SystemClock.uptimeMillis() + 100, | |
MotionEvent.ACTION_DOWN, | |
event.rawX, | |
event.rawY, | |
0 | |
) | |
) | |
true | |
} ?: super.onInterceptTouchEvent(event) | |
} | |
else -> | |
super.onInterceptTouchEvent(event) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment