Google is committed to advancing racial equity for Black communities. See how.

Callback

abstract class Callback
kotlin.Any
   ↳ androidx.recyclerview.widget.ItemTouchHelper.Callback

This class is the contract between ItemTouchHelper and your application. It lets you control which touch behaviors are enabled per each ViewHolder and also receive callbacks when user performs these actions.

To control which actions user can take on each view, you should override getMovementFlags(RecyclerView, ViewHolder) and return appropriate set of direction flags. (LEFT, RIGHT, START, END, UP, DOWN). You can use makeMovementFlags(int, int) to easily construct it. Alternatively, you can use SimpleCallback.

If user drags an item, ItemTouchHelper will call onMove(recyclerView, dragged, target). Upon receiving this callback, you should move the item from the old position (dragged.getAdapterPosition()) to new position (target.getAdapterPosition()) in your adapter and also call RecyclerView.Adapter#notifyItemMoved(int, int). To control where a View can be dropped, you can override canDropOver(RecyclerView, ViewHolder, ViewHolder). When a dragging View overlaps multiple other views, Callback chooses the closest View with which dragged View might have changed positions. Although this approach works for many use cases, if you have a custom LayoutManager, you can override chooseDropTarget(ViewHolder, java.util.List, int, int) to select a custom drop target.

When a View is swiped, ItemTouchHelper animates it until it goes out of bounds, then calls onSwiped(ViewHolder, int). At this point, you should update your adapter (e.g. remove the item) and call related Adapter#notify event.

Summary

Constants
static Int

static Int

Public constructors

This class is the contract between ItemTouchHelper and your application.

Public methods
open Boolean
canDropOver(@NonNull recyclerView: RecyclerView, @NonNull current: RecyclerView.ViewHolder, @NonNull target: RecyclerView.ViewHolder)

Return true if the current ViewHolder can be dropped over the the target ViewHolder.

open RecyclerView.ViewHolder!
chooseDropTarget(@NonNull selected: RecyclerView.ViewHolder, @NonNull dropTargets: MutableList<RecyclerView.ViewHolder!>, curX: Int, curY: Int)

Called by ItemTouchHelper to select a drop target from the list of ViewHolders that are under the dragged View.

open Unit
clearView(@NonNull recyclerView: RecyclerView, @NonNull viewHolder: RecyclerView.ViewHolder)

Called by the ItemTouchHelper when the user interaction with an element is over and it also completed its animation.

open Int
convertToAbsoluteDirection(flags: Int, layoutDirection: Int)

Converts a given set of flags to absolution direction which means START and END are replaced with LEFT and RIGHT depending on the layout direction.

open static Int
convertToRelativeDirection(flags: Int, layoutDirection: Int)

Replaces a movement direction with its relative version by taking layout direction into account.

open Long
getAnimationDuration(@NonNull recyclerView: RecyclerView, animationType: Int, animateDx: Float, animateDy: Float)

Called by the ItemTouchHelper when user action finished on a ViewHolder and now the View will be animated to its final position.

open Int

When finding views under a dragged view, by default, ItemTouchHelper searches for views that overlap with the dragged View.

open static ItemTouchUIUtil

Returns the ItemTouchUIUtil that is used by the Callback class for visual changes on Views in response to user interactions.

open Float

Returns the fraction that the user should move the View to be considered as it is dragged.

abstract Int
getMovementFlags(@NonNull recyclerView: RecyclerView, @NonNull viewHolder: RecyclerView.ViewHolder)

Should return a composite flag which defines the enabled move directions in each state (idle, swiping, dragging).

open Float

Defines the minimum velocity which will be considered as a swipe action by the user.

open Float

Returns the fraction that the user should move the View to be considered as swiped.

open Float

Defines the maximum velocity ItemTouchHelper will ever calculate for pointer movements.

open Int
interpolateOutOfBoundsScroll(@NonNull recyclerView: RecyclerView, viewSize: Int, viewSizeOutOfBounds: Int, totalSize: Int, msSinceStartScroll: Long)

Called by the ItemTouchHelper when user is dragging a view out of bounds.

open Boolean

Returns whether ItemTouchHelper should start a swipe operation if a pointer is swiped over the View.

open Boolean

Returns whether ItemTouchHelper should start a drag and drop operation if an item is long pressed.

open static Int
makeFlag(actionState: Int, directions: Int)

Shifts the given direction flags to the offset of the given action state.

open static Int
makeMovementFlags(dragFlags: Int, swipeFlags: Int)

Convenience method to create movement flags.

open Unit
onChildDraw(@NonNull c: Canvas, @NonNull recyclerView: RecyclerView, @NonNull viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean)

Called by ItemTouchHelper on RecyclerView's onDraw callback.

open Unit
onChildDrawOver(@NonNull c: Canvas, @NonNull recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder!, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean)

Called by ItemTouchHelper on RecyclerView's onDraw callback.

abstract Boolean
onMove(@NonNull recyclerView: RecyclerView, @NonNull viewHolder: RecyclerView.ViewHolder, @NonNull target: RecyclerView.ViewHolder)

Called when ItemTouchHelper wants to move the dragged item from its old position to the new position.

open Unit
onMoved(@NonNull recyclerView: RecyclerView, @NonNull viewHolder: RecyclerView.ViewHolder, fromPos: Int, @NonNull target: RecyclerView.ViewHolder, toPos: Int, x: Int, y: Int)

Called when onMove(RecyclerView, ViewHolder, ViewHolder) returns true.

open Unit
onSelectedChanged(@Nullable viewHolder: RecyclerView.ViewHolder?, actionState: Int)

Called when the ViewHolder swiped or dragged by the ItemTouchHelper is changed.

abstract Unit
onSwiped(@NonNull viewHolder: RecyclerView.ViewHolder, direction: Int)

Called when a ViewHolder is swiped by the user.

Constants

DEFAULT_DRAG_ANIMATION_DURATION

static val DEFAULT_DRAG_ANIMATION_DURATION: Int
Value: 200

DEFAULT_SWIPE_ANIMATION_DURATION

static val DEFAULT_SWIPE_ANIMATION_DURATION: Int
Value: 250

Public constructors

<init>

Callback()

This class is the contract between ItemTouchHelper and your application. It lets you control which touch behaviors are enabled per each ViewHolder and also receive callbacks when user performs these actions.

To control which actions user can take on each view, you should override getMovementFlags(RecyclerView, ViewHolder) and return appropriate set of direction flags. (LEFT, RIGHT, START, END, UP, DOWN). You can use makeMovementFlags(int, int) to easily construct it. Alternatively, you can use SimpleCallback.

If user drags an item, ItemTouchHelper will call onMove(recyclerView, dragged, target). Upon receiving this callback, you should move the item from the old position (dragged.getAdapterPosition()) to new position (target.getAdapterPosition()) in your adapter and also call RecyclerView.Adapter#notifyItemMoved(int, int). To control where a View can be dropped, you can override canDropOver(RecyclerView, ViewHolder, ViewHolder). When a dragging View overlaps multiple other views, Callback chooses the closest View with which dragged View might have changed positions. Although this approach works for many use cases, if you have a custom LayoutManager, you can override chooseDropTarget(ViewHolder, java.util.List, int, int) to select a custom drop target.

When a View is swiped, ItemTouchHelper animates it until it goes out of bounds, then calls onSwiped(ViewHolder, int). At this point, you should update your adapter (e.g. remove the item) and call related Adapter#notify event.

Public methods

canDropOver

open fun canDropOver(
    @NonNull recyclerView: RecyclerView,
    @NonNull current: RecyclerView.ViewHolder,
    @NonNull target: RecyclerView.ViewHolder
): Boolean

Return true if the current ViewHolder can be dropped over the the target ViewHolder.

This method is used when selecting drop target for the dragged View. After Views are eliminated either via bounds check or via this method, resulting set of views will be passed to chooseDropTarget(ViewHolder, java.util.List, int, int).

Default implementation returns true.

Parameters
recyclerView RecyclerView: The RecyclerView to which ItemTouchHelper is attached to.
current RecyclerView.ViewHolder: The ViewHolder that user is dragging.
target RecyclerView.ViewHolder: The ViewHolder which is below the dragged ViewHolder.
Return
Boolean True if the dragged ViewHolder can be replaced with the target ViewHolder, false otherwise.

chooseDropTarget

open fun chooseDropTarget(
    @NonNull selected: RecyclerView.ViewHolder,
    @NonNull dropTargets: MutableList<RecyclerView.ViewHolder!>,
    curX: Int,
    curY: Int
): RecyclerView.ViewHolder!

Called by ItemTouchHelper to select a drop target from the list of ViewHolders that are under the dragged View.

Default implementation filters the View with which dragged item have changed position in the drag direction. For instance, if the view is dragged UP, it compares the view.getTop() of the two views before and after drag started. If that value is different, the target view passes the filter.

Among these Views which pass the test, the one closest to the dragged view is chosen.

This method is called on the main thread every time user moves the View. If you want to override it, make sure it does not do any expensive operations.

Parameters
selected RecyclerView.ViewHolder: The ViewHolder being dragged by the user.
dropTargets MutableList<RecyclerView.ViewHolder!>: The list of ViewHolder that are under the dragged View and candidate as a drop.
curX Int: The updated left value of the dragged View after drag translations are applied. This value does not include margins added by RecyclerView.ItemDecorations.
curY Int: The updated top value of the dragged View after drag translations are applied. This value does not include margins added by RecyclerView.ItemDecorations.
Return
RecyclerView.ViewHolder! A ViewHolder to whose position the dragged ViewHolder should be moved to.

clearView

open fun clearView(
    @NonNull recyclerView: RecyclerView,
    @NonNull viewHolder: RecyclerView.ViewHolder
): Unit

Called by the ItemTouchHelper when the user interaction with an element is over and it also completed its animation.

This is a good place to clear all changes on the View that was done in onSelectedChanged(RecyclerView.ViewHolder, int), onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int, * boolean) or onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, boolean).

Parameters
recyclerView RecyclerView: The RecyclerView which is controlled by the ItemTouchHelper.
viewHolder RecyclerView.ViewHolder: The View that was interacted by the user.

convertToAbsoluteDirection

open fun convertToAbsoluteDirection(
    flags: Int,
    layoutDirection: Int
): Int

Converts a given set of flags to absolution direction which means START and END are replaced with LEFT and RIGHT depending on the layout direction.

Parameters
flags Int: The flag value that include any number of movement flags.
layoutDirection Int: The layout direction of the RecyclerView.
Return
Int Updated flags which includes only absolute direction values.

convertToRelativeDirection

open static fun convertToRelativeDirection(
    flags: Int,
    layoutDirection: Int
): Int

Replaces a movement direction with its relative version by taking layout direction into account.

Parameters
flags Int: The flag value that include any number of movement flags.
layoutDirection Int: The layout direction of the View. Can be obtained from ViewCompat#getLayoutDirection(android.view.View).
Return
Int Updated flags which uses relative flags (START, END) instead of LEFT, RIGHT.

getAnimationDuration

open fun getAnimationDuration(
    @NonNull recyclerView: RecyclerView,
    animationType: Int,
    animateDx: Float,
    animateDy: Float
): Long

Called by the ItemTouchHelper when user action finished on a ViewHolder and now the View will be animated to its final position.

Default implementation uses ItemAnimator's duration values. If animationType is ANIMATION_TYPE_DRAG, it returns RecyclerView.ItemAnimator#getMoveDuration(), otherwise, it returns RecyclerView.ItemAnimator#getRemoveDuration(). If RecyclerView does not have any RecyclerView.ItemAnimator attached, this method returns DEFAULT_DRAG_ANIMATION_DURATION or DEFAULT_SWIPE_ANIMATION_DURATION depending on the animation type.

Parameters
recyclerView RecyclerView: The RecyclerView to which the ItemTouchHelper is attached to.
animationType Int: The type of animation. Is one of ANIMATION_TYPE_DRAG, ANIMATION_TYPE_SWIPE_CANCEL or ANIMATION_TYPE_SWIPE_SUCCESS.
animateDx Float: The horizontal distance that the animation will offset
animateDy Float: The vertical distance that the animation will offset
Return
Long The duration for the animation

getBoundingBoxMargin

open fun getBoundingBoxMargin(): Int

When finding views under a dragged view, by default, ItemTouchHelper searches for views that overlap with the dragged View. By overriding this method, you can extend or shrink the search box.

Return
Int The extra margin to be added to the hit box of the dragged View.

getDefaultUIUtil

@NonNull open static fun getDefaultUIUtil(): ItemTouchUIUtil

Returns the ItemTouchUIUtil that is used by the Callback class for visual changes on Views in response to user interactions. ItemTouchUIUtil has different implementations for different platform versions.

By default, Callback applies these changes on RecyclerView.ViewHolder#itemView.

For example, if you have a use case where you only want the text to move when user swipes over the view, you can do the following:

public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder){
                  getDefaultUIUtil().clearView(((ItemTouchViewHolder) viewHolder).textView);
              }
              public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
                  if (viewHolder != null){
                      getDefaultUIUtil().onSelected(((ItemTouchViewHolder) viewHolder).textView);
                  }
              }
              public void onChildDraw(Canvas c, RecyclerView recyclerView,
                      RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
                      boolean isCurrentlyActive) {
                  getDefaultUIUtil().onDraw(c, recyclerView,
                          ((ItemTouchViewHolder) viewHolder).textView, dX, dY,
                          actionState, isCurrentlyActive);
                  return true;
              }
              public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
                      RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
                      boolean isCurrentlyActive) {
                  getDefaultUIUtil().onDrawOver(c, recyclerView,
                          ((ItemTouchViewHolder) viewHolder).textView, dX, dY,
                          actionState, isCurrentlyActive);
                  return true;
              }
          
Return
ItemTouchUIUtil The ItemTouchUIUtil instance that is used by the Callback

getMoveThreshold

open fun getMoveThreshold(@NonNull viewHolder: RecyclerView.ViewHolder): Float

Returns the fraction that the user should move the View to be considered as it is dragged. After a view is moved this amount, ItemTouchHelper starts checking for Views below it for a possible drop.

Parameters
viewHolder RecyclerView.ViewHolder: The ViewHolder that is being dragged.
Return
Float A float value that denotes the fraction of the View size. Default value is .5f .

getMovementFlags

abstract fun getMovementFlags(
    @NonNull recyclerView: RecyclerView,
    @NonNull viewHolder: RecyclerView.ViewHolder
): Int

Should return a composite flag which defines the enabled move directions in each state (idle, swiping, dragging).

Instead of composing this flag manually, you can use makeMovementFlags(int, * int) or makeFlag(int, int).

This flag is composed of 3 sets of 8 bits, where first 8 bits are for IDLE state, next 8 bits are for SWIPE state and third 8 bits are for DRAG state. Each 8 bit sections can be constructed by simply OR'ing direction flags defined in ItemTouchHelper.

For example, if you want it to allow swiping LEFT and RIGHT but only allow starting to swipe by swiping RIGHT, you can return:

makeFlag(ACTION_STATE_IDLE, RIGHT) | makeFlag(ACTION_STATE_SWIPE, LEFT | RIGHT);
          
This means, allow right movement while IDLE and allow right and left movement while swiping.
Parameters
recyclerView RecyclerView: The RecyclerView to which ItemTouchHelper is attached.
viewHolder RecyclerView.ViewHolder: The ViewHolder for which the movement information is necessary.
Return
Int flags specifying which movements are allowed on this ViewHolder.

getSwipeEscapeVelocity

open fun getSwipeEscapeVelocity(defaultValue: Float): Float

Defines the minimum velocity which will be considered as a swipe action by the user.

You can increase this value to make it harder to swipe or decrease it to make it easier. Keep in mind that ItemTouchHelper also checks the perpendicular velocity and makes sure current direction velocity is larger then the perpendicular one. Otherwise, user's movement is ambiguous. You can change the threshold by overriding getSwipeVelocityThreshold(float).

The velocity is calculated in pixels per second.

The default framework value is passed as a parameter so that you can modify it with a multiplier.

Parameters
defaultValue Float: The default value (in pixels per second) used by the ItemTouchHelper.
Return
Float The minimum swipe velocity. The default implementation returns the defaultValue parameter.

getSwipeThreshold

open fun getSwipeThreshold(@NonNull viewHolder: RecyclerView.ViewHolder): Float

Returns the fraction that the user should move the View to be considered as swiped. The fraction is calculated with respect to RecyclerView's bounds.

Default value is .5f, which means, to swipe a View, user must move the View at least half of RecyclerView's width or height, depending on the swipe direction.

Parameters
viewHolder RecyclerView.ViewHolder: The ViewHolder that is being dragged.
Return
Float A float value that denotes the fraction of the View size. Default value is .5f .

getSwipeVelocityThreshold

open fun getSwipeVelocityThreshold(defaultValue: Float): Float

Defines the maximum velocity ItemTouchHelper will ever calculate for pointer movements.

To consider a movement as swipe, ItemTouchHelper requires it to be larger than the perpendicular movement. If both directions reach to the max threshold, none of them will be considered as a swipe because it is usually an indication that user rather tried to scroll then swipe.

The velocity is calculated in pixels per second.

You can customize this behavior by changing this method. If you increase the value, it will be easier for the user to swipe diagonally and if you decrease the value, user will need to make a rather straight finger movement to trigger a swipe.

Parameters
defaultValue Float: The default value(in pixels per second) used by the ItemTouchHelper.
Return
Float The velocity cap for pointer movements. The default implementation returns the defaultValue parameter.

interpolateOutOfBoundsScroll

open fun interpolateOutOfBoundsScroll(
    @NonNull recyclerView: RecyclerView,
    viewSize: Int,
    viewSizeOutOfBounds: Int,
    totalSize