Skip to content

Instantly share code, notes, and snippets.

@afrishberg
Last active September 5, 2021 08:40
Show Gist options
  • Save afrishberg/ed6447fcaab1cae40352083adfde47b4 to your computer and use it in GitHub Desktop.
Save afrishberg/ed6447fcaab1cae40352083adfde47b4 to your computer and use it in GitHub Desktop.
A frame layout that is aware of taps but doesn't intercept touch events from children
package com.example.ui.views
import android.content.Context
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.widget.FrameLayout
typealias TapListener = () -> Unit
typealias EventAwareTapListener = (MotionEvent) -> Unit
class TapAwareFrameLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
var tapListener : TapListener? = null
var longTapListener: EventAwareTapListener? = null
val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
tapListener?.invoke()
return super.onSingleTapConfirmed(e)
}
override fun onLongPress(e: MotionEvent?) {
println("TAPAWARE onLongPress")
e?.let {
longTapListener?.invoke(it)
}
super.onLongPress(e)
}
})
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
if (listeningToTouchEvents()) {
gestureDetector.onTouchEvent(event)
}
return super.onInterceptTouchEvent(event)
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
val listeningToTouchEvents = listeningToTouchEvents()
if (listeningToTouchEvents) {
gestureDetector.onTouchEvent(event)
}
return super.onTouchEvent(
event) || (event?.action == MotionEvent.ACTION_DOWN && listeningToTouchEvents)
}
private fun listeningToTouchEvents() = tapListener != null || longTapListener != null
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment