Try the Compose way  
Jetpack Compose is the recommended UI toolkit for Android. Learn how to work with layouts in Compose.  
[Gestures →](https://developer.android.com/jetpack/compose/touch-input/pointer-input)  
![](https://developer.android.com/static/images/android-compose-ui-logo.png)

Drawing a UI is only one part of creating a custom view. You also need to
make your view respond to user input in a way that closely resembles the
real-world action you're mimicking.

Make the objects in your app act like real objects do. For example, don't let
images in your app pop out of existence and reappear elsewhere, because objects
in the real world don't do that. Instead, move your images from one place to
another.

Users sense even subtle behavior or feel in an interface and react best to
subtleties that mimic the real world. For example, when users fling a UI object,
give them a sense of inertia at the beginning that delays the motion. At the end
of the motion, give them a sense of momentum that carries the object beyond the
fling.

This page demonstrates how to use features of the Android framework to add
these real-world behaviors to your custom view.

You can find additional related information in
[Input events overview](https://developer.android.com/guide/topics/ui/ui-events) and
[Property animation
overview](https://developer.android.com/guide/topics/graphics/prop-animation).

## Handle input gestures

Like many other UI frameworks, Android supports an input event model. User
actions turn into events that trigger callbacks, and you can override the
callbacks to customize how your app responds to the user. The most common input
event in the Android system is *touch* , which triggers
[onTouchEvent(android.view.MotionEvent)](https://developer.android.com/reference/android/view/View#onTouchEvent(android.view.MotionEvent)).
Override this method to handle the event, as follows:  

### Kotlin

```kotlin
override fun onTouchEvent(event: MotionEvent): Boolean {
    return super.onTouchEvent(event)
}
```

### Java

```java
@Override
   public boolean onTouchEvent(MotionEvent event) {
    return super.onTouchEvent(event);
   }
```

Touch events by themselves aren't particularly useful. Modern touch UIs
define interactions in terms of gestures such as tapping, pulling, pushing,
flinging, and zooming. To convert raw touch events into gestures, Android
provides
[GestureDetector](https://developer.android.com/reference/android/view/GestureDetector).

Construct a `GestureDetector` by passing in an instance of a class
that implements
[GestureDetector.OnGestureListener](https://developer.android.com/reference/android/view/GestureDetector.OnGestureListener).
If you only want to process a few gestures, you can extend
[GestureDetector.SimpleOnGestureListener](https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener)
instead of implementing the `GestureDetector.OnGestureListener`
interface. For example, this code creates a class that extends
`GestureDetector.SimpleOnGestureListener` and overrides
[onDown(MotionEvent)](https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener#onDown(android.view.MotionEvent)).  

### Kotlin

```kotlin
private val myListener =  object : GestureDetector.SimpleOnGestureListener() {
    override fun onDown(e: MotionEvent): Boolean {
        return true
    }
}

private val detector: GestureDetector = GestureDetector(context, myListener)
```

### Java

```java
class MyListener extends GestureDetector.SimpleOnGestureListener {
   @Override
   public boolean onDown(MotionEvent e) {
       return true;
   }
}
detector = new GestureDetector(getContext(), new MyListener());
```

Whether or not you use `GestureDetector.SimpleOnGestureListener`,
always implement an
[onDown()](https://developer.android.com/reference/android/view/GestureDetector.OnGestureListener#onDown(android.view.MotionEvent))
method that returns `true`. This is necessary because all gestures
begin with an `onDown()` message. If you return `false`
from `onDown()`, as
`GestureDetector.SimpleOnGestureListener` does, the system assumes
you want to ignore the rest of the gesture, and the other methods of
`GestureDetector.OnGestureListener` aren't called. Only return
`false` from `onDown()` if you want to ignore an entire
gesture.

After you implement `GestureDetector.OnGestureListener` and create
an instance of `GestureDetector`, you can use your
`GestureDetector` to interpret the touch events you receive in
[onTouchEvent()](https://developer.android.com/reference/android/view/GestureDetector#onTouchEvent(android.view.MotionEvent)).  

### Kotlin

```kotlin
override fun onTouchEvent(event: MotionEvent): Boolean {
    return detector.onTouchEvent(event).let { result ->
        if (!result) {
            if (event.action == MotionEvent.ACTION_UP) {
                stopScrolling()
                true
            } else false
        } else true
    }
}
```

### Java

```java
@Override
public boolean onTouchEvent(MotionEvent event) {
   boolean result = detector.onTouchEvent(event);
   if (!result) {
       if (event.getAction() == MotionEvent.ACTION_UP) {
           stopScrolling();
           result = true;
       }
   }
   return result;
}
```

When you pass `onTouchEvent()` a touch event that it doesn't
recognize as part of a gesture, it returns `false`. You can then run
your own custom gesture-detection code.

## Create physically plausible motion

Gestures are a powerful way to control touchscreen devices, but they can be
counterintuitive and difficult to remember unless they produce physically
plausible results.

For example, suppose you want to implement a horizontal fling gesture that
sets the item drawn in the view spinning around its vertical axis. This gesture
makes sense if the UI responds by moving quickly in the direction of the fling,
then slowing down, as if the user pushes on a flywheel and makes it spin.

The documentation on how to
[animate a scroll
gesture](https://developer.android.com/develop/ui/views/touch-and-input/gestures/scroll) gives a detailed explanation about how to implement your own scoll
behavior. But simulating the feel of a flywheel isn't trivial. A lot of physics
and math is required to make a flywheel model work correctly. Fortunately,
Android provides helper classes to simulate this and other behaviors. The
[Scroller](https://developer.android.com/reference/android/widget/Scroller)
class is the basis for handling flywheel-style fling gestures.

To start a fling, call
[fling()](https://developer.android.com/reference/android/widget/Scroller#fling(int, int, int, int, int, int, int, int))
with the starting velocity and the minimum and maximum *x* and *y*
values of the fling. For the velocity value, you can use the value computed by
`GestureDetector`.  

### Kotlin

```kotlin
fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
    scroller.fling(
            currentX,
            currentY,
            (velocityX / SCALE).toInt(),
            (velocityY / SCALE).toInt(),
            minX,
            minY,
            maxX,
            maxY
    )
    postInvalidate()
    return true
}
```

### Java

```java
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
   scroller.fling(currentX, currentY, velocityX / SCALE, velocityY / SCALE, minX, minY, maxX, maxY);
   postInvalidate();
    return true;
}
```
| **Note:** Although the velocity calculated by `GestureDetector` is physically accurate, many developers feel that using this value makes the fling animation too fast. It's common to divide the *x* and *y* velocity by a factor of four to eight.

The call to `fling()` sets up the physics model for the fling
gesture. Afterward, update the `Scroller` by calling
[Scroller.computeScrollOffset()](https://developer.android.com/reference/android/widget/Scroller#computeScrollOffset())
at regular intervals. `computeScrollOffset()` updates the
`Scroller` object's internal state by reading the current time and
using the physics model to calculate the *x* and *y* position at that
time. Call
[getCurrX()](https://developer.android.com/reference/android/widget/Scroller#getCurrX())
and
[getCurrY()](https://developer.android.com/reference/android/widget/Scroller#getCurrY())
to retrieve these values.

Most views pass the `Scroller` object's *x* and *y*
positions directly to
[scrollTo()](https://developer.android.com/reference/android/view/View#scrollTo(int, int)).
This example is a little different: it uses the current scroll *x* position
to set the rotational angle of the view.  

### Kotlin

```kotlin
scroller.apply {
    if (!isFinished) {
        computeScrollOffset()
        setItemRotation(currX)
    }
}
```

### Java

```java
if (!scroller.isFinished()) {
    scroller.computeScrollOffset();
    setItemRotation(scroller.getCurrX());
}
```

The `Scroller` class computes scroll positions for you, but it
doesn't automatically apply those positions to your view. Apply new coordinates
often enough to make the scrolling animation look smooth. There are two ways to
do this:

- Force a redraw by calling [postInvalidate()](https://developer.android.com/reference/android/view/View#postInvalidate()) after calling `fling()`. This technique requires that you compute scroll offsets in [onDraw()](https://developer.android.com/reference/android/view/View#onDraw(android.graphics.Canvas)) and call `postInvalidate()` every time the scroll offset changes.
- Set up a [ValueAnimator](https://developer.android.com/reference/android/animation/ValueAnimator) to animate for the duration of the fling and add a listener to process animation updates by calling [addUpdateListener()](https://developer.android.com/reference/android/animation/ValueAnimator#addUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener)). This technique lets you animate properties of a [View](https://developer.android.com/reference/android/view/View).

## Make your transitions smooth

Users expect a modern UI to transition smoothly between states: UI elements
fading in and out instead of appearing and disappearing, and motions beginning
and ending smoothly instead of starting and stopping abruptly. The Android
[property animation
framework](https://developer.android.com/guide/topics/graphics/prop-animation) makes smooth transitions easier.

To use the animation system, whenever a property changes what affects your
view's appearance, don't change the property directly. Instead, use
`ValueAnimator` to make the change. In the following example,
modifying the selected child component in the view makes the entire rendered
view rotate so that the selection pointer is centered.
`ValueAnimator` changes the rotation over a period of several hundred
milliseconds, rather than immediately setting the new rotation value.  

### Kotlin

```kotlin
autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0).apply {
    setIntValues(targetAngle)
    duration = AUTOCENTER_ANIM_DURATION
    start()
}
```

### Java

```java
autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0);
autoCenterAnimator.setIntValues(targetAngle);
autoCenterAnimator.setDuration(AUTOCENTER_ANIM_DURATION);
autoCenterAnimator.start();
```

If the value you want to change is one of the base `View`
properties, doing the animation is even easier, because views have a built-in
[ViewPropertyAnimator](https://developer.android.com/reference/android/view/ViewPropertyAnimator)
that is optimized for simultaneous animation of multiple properties, as in the
following example:  

### Kotlin

```kotlin
animate()
    .rotation(targetAngle)
    .duration = ANIM_DURATION
    .start()
```

### Java

```java
animate().rotation(targetAngle).setDuration(ANIM_DURATION).start();
```