When working with Kotlin Android development, one of the most common issues developers face is touch events not triggering. This problem can appear when building interactive apps such as drawing boards, games, or custom views. Understanding how to handle onTouchEvent, GestureDetector, and View.OnTouchListener is critical to solving this issue.

Why Kotlin Touch Events May Not Trigger
There are several common reasons why touch events fail to trigger in a Kotlin Android application:
- Parent view intercepts touch events – for example, a ScrollView or RecyclerView may consume the event before it reaches the target view.
- Clickable or focusable conflicts – if your view is not marked as clickable or focusable, it might ignore touch gestures.
- Incorrect override – forgetting to return
true
inonTouchEvent()
oronInterceptTouchEvent()
will stop further propagation. - Layer overlap – another view may be blocking touch detection.
Basic Example: Handling onTouchEvent
Let’s start with a simple example in Kotlin where we handle touch events directly using onTouchEvent()
inside a custom view.
class TouchView(context: Context, attrs: AttributeSet) : View(context, attrs) { override fun onTouchEvent(event: MotionEvent): Boolean { when (event.action) { MotionEvent.ACTION_DOWN -> { Log.d("TouchView", "Finger pressed at: ${event.x}, ${event.y}") return true } MotionEvent.ACTION_MOVE -> { Log.d("TouchView", "Finger moved at: ${event.x}, ${event.y}") return true } MotionEvent.ACTION_UP -> { Log.d("TouchView", "Finger lifted") return true } } return super.onTouchEvent(event) } }
In this example, returning true
ensures that the touch event is consumed and not ignored. If you return false
, Android assumes your view does not care about touch inputs.
Using OnTouchListener
Another common way to detect touch events is by setting an OnTouchListener
on a view.
myButton.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { Log.d("TouchEvent", "Button pressed") true } MotionEvent.ACTION_UP -> { Log.d("TouchEvent", "Button released") true } else -> false } }
If false
is returned, the event may propagate upwards, sometimes causing touch events not to trigger as expected. Always return true
if you want to consume the event fully.
Preventing Parent Views from Blocking Touch Events
When working with nested views like ScrollView, sometimes the parent intercepts the gesture. To fix this, you can disable the interception using:
myView.setOnTouchListener { v, event -> v.parent.requestDisallowInterceptTouchEvent(true) // Handle your touch logic true }
Using GestureDetector for Advanced Gestures
If you want to detect double taps, swipes, or long presses, GestureDetector
is more powerful.
class GestureActivity : AppCompatActivity() { private lateinit var gestureDetector: GestureDetectorCompat override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_gesture) gestureDetector = GestureDetectorCompat(this, object : GestureDetector.SimpleOnGestureListener() { override fun onSingleTapUp(e: MotionEvent): Boolean { Log.d("Gesture", "Single Tap Detected") return true } override fun onLongPress(e: MotionEvent) { Log.d("Gesture", "Long Press Detected") } override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean { Log.d("Gesture", "Fling Detected") return true } }) val touchLayout: View = findViewById(R.id.touchLayout) touchLayout.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) true } } }
Common Mistakes to Avoid
- Not setting focusable/clickable – Ensure your view has
android:clickable="true"
or set programmatically. - Returning false – Returning false too early will cancel touch event processing.
- Overlaying invisible views – Make sure no transparent layout is intercepting touches.
Comparison: OnTouchListener vs OnTouchEvent
Method | Usage | Pros | Cons |
---|---|---|---|
onTouchEvent() | Custom View handling | Direct, flexible, good for drawing apps | Only for views you extend |
OnTouchListener | Set on any view | Easy, no custom view needed | Requires correct return handling |
GestureDetector | Complex gestures | Supports swipes, double taps, etc. | More boilerplate code |
Best Practices
- Always return
true
when you consume an event. - Use
requestDisallowInterceptTouchEvent(true)
for nested scrollable parents. - Use
GestureDetector
for advanced gesture detection instead of reinventing the wheel. - Check for overlapping layouts that may block touch input.
Conclusion
If your Kotlin touch events are not triggering, the problem usually comes from either event interception, incorrect return values, or focusability issues. By carefully implementing onTouchEvent()
, OnTouchListener
, or GestureDetector
, you can ensure smooth and reliable touch handling in your Android applications. With these best practices, you will be able to build interactive and responsive mobile apps that handle user gestures effectively.
For more details, you can also check the official Android documentation on gesture handling.