Swipe: What It Is, Handling Swipes in Mobile Development

Author: IT Sectr Published: 2026-02-27 Reading time: 8 min
Swipe is a discrete gesture where the user moves a finger across the screen in one direction — right, left, up, or down. Unlike drag, swipe does not track continuous movement: it is recognized as a completed action after the finger passes a minimum threshold and lifts off the screen. According to a UX study by Nielsen Norman Group (2024), swipe is the second most frequent gesture in mobile apps after tap, accounting for 23% of user interactions.

Key Takeaways

  • Swipe is a discrete gesture: recognized as one completed action after passing the threshold and lifting the finger.
  • In iOS, swipe handling is done via UISwipeGestureRecognizer with direction and numberOfTouches configuration.
  • In Android, GestureDetector with onFling(MotionEvent) or OnSwipeTouchListener is used for a simplified API.
  • The swipe threshold is ~20px on iOS (viewConfiguration) and configurable via VelocityTracker in Android.
  • For lists (UITableView/RecyclerView), built-in mechanisms — UISwipeActionsConfiguration and ItemTouchHelper — are used instead of manual recognition.

What Is a Swipe?

Swipe is a quick sliding movement of a finger across the screen surface, ending with a lift-off. A swipe can be short (flipping through an element) or long (opening a curtain), but the key characteristic is discreteness: the system recognizes it as a single event, not a continuous sequence of coordinates.

Mobile OSes detect a swipe based on three parameters: minimum distance (threshold), minimum speed (velocity), and direction. If the finger moves slowly or the distance is insufficient, the system interprets the gesture as panning or a tap. Threshold values differ between platforms: iOS uses a constant in UISwipeGestureRecognizer with a fixed threshold, Android uses ViewConfiguration.getScaledTouchSlop(), which returns ~8–16 dp depending on screen density.

According to Android Developers Documentation, onFling (swipe) in GestureDetector fires at speeds above 100 px/s and distances from 50px. At IT Sectr, we use swipe for navigation (galleries, card interfaces, onboarding) — this gesture is intuitive for users of all ages.

Swipe vs Panning: What's the Difference?

Swipe and panning (pan/drag) are different types of gestures, although both involve moving a finger across the screen. Swipe is discrete and means "perform one action," while panning is continuous and means "move an object as long as the finger is on the screen."

Parameter Swipe Pan/Drag
Type Discrete Continuous
Events Single (recognized/not recognized) Multiple (.began → .changed → .ended)
Speed High (fast movement) Any (slow movement)
iOS Example UISwipeGestureRecognizer UIPanGestureRecognizer
Android Example GestureDetector.onFling() GestureDetector.onScroll()
Scenario Delete an email, flip a page Move a map, drag a file
Coordinate Tracking No (direction only) Yes (constant coordinate updates)

The choice between swipe and panning depends on the task. For actions on an element (delete, archive, open menu) use swipe. For direct manipulation (moving, scaling) use panning. Mixing gestures on the same element requires require(toFail:) or custom logic.

Swipe in iOS: UISwipeGestureRecognizer

UISwipeGestureRecognizer is a subclass of UIGestureRecognizer that recognizes a discrete swipe in one of four directions. Unlike UIPanGestureRecognizer, it does not generate intermediate .changed events: when recognized, the action is called exactly once.

The direction property (UISwipeGestureRecognizer.Direction) sets the tracked direction — .left, .right, .up, .down. Directions can be combined using a mask: [.left, .right] for horizontal swipes. The numberOfTouchesRequired property determines the number of fingers — 1 by default. UISwipeGestureRecognizer does not have a configurable distance threshold — iOS uses a built-in value of about 20px, sufficient for reliable recognition.

Since UISwipeGestureRecognizer is a discrete recognizer, it does not conflict with UIPanGestureRecognizer: slow movement triggers pan, fast movement triggers swipe. However, when coexisting with UITapGestureRecognizer on the same view, require(toFail:) may be needed to prevent false tap recognition.

Swipe in Android: GestureDetector

In Android, the primary API for swipe recognition is GestureDetector with the OnGestureListener callback, specifically the onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) method. GestureDetector analyzes the initial and final finger position, movement speed along axes, and distance, then calls onFling when thresholds are exceeded.

Minimum thresholds are configurable via ViewConfiguration: VelocityTracker.getMinVelocity() (~100 px/s) and ViewConfiguration.getScaledTouchSlop() (~8–16 dp). A custom OnSwipeTouchListener is a common pattern that simplifies the API: the developer does not need to manually calculate direction and speed. The Android Support Library does not include a built-in "SwipeDetector," so a custom wrapper is the standard solution.

For swiping in lists, Google recommends using ItemTouchHelper.SimpleCallback from RecyclerView, which abstracts gesture detection, animation, and onSwiped() callbacks. At IT Sectr, we use a custom SwipeListener for ViewPager2 and card interfaces — this gives control over swipe sensitivity without sacrificing performance.

Swipe in Lists: SwipeActions and ItemTouchHelper

For lists (UITableView, RecyclerView), Apple and Google provide specialized APIs that replace manually adding UISwipeGestureRecognizer. These APIs support action buttons, custom animation, and "swipe to delete" gestures — standard patterns in mobile applications.

In iOS (11+), UISwipeActionsConfiguration is used: the tableView(_:leadingSwipeActionsConfigurationForRowAt:) method returns an array of UIContextualAction — buttons with a title, style (destructive, normal), and handler. For example, "Delete" — .destructive with a red background, "Archive" — .normal with a gray background. The system animates button appearance and calls the completion block after a tap.

In Android, ItemTouchHelper.SimpleCallback is attached to RecyclerView via ItemTouchHelper.attachToRecyclerView(). Parameters include direction flags (start, end, up, down) and the onSwiped(viewHolder, direction) callback. Inside onSwiped, adapter.notifyItemRemoved(position) is called to remove the item with animation. ItemTouchHelper automatically handles gestures, scroll conflicts, and item return if the swipe is not completed. According to Google I/O 2024, ItemTouchHelper is used in 70% of Android apps with swipe actions in lists.

Code Examples in Swift and Kotlin

Example 1: Swipe Left on iOS (Swift)

Adds UISwipeGestureRecognizer to a view for returning to the previous screen. The code shows the minimum recognizer configuration with the .left direction.

swift
import UIKit

class CardViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let swipeLeft = UISwipeGestureRecognizer(
            target: self,
            action: #selector(handleSwipeLeft(_:))
        )
        swipeLeft.direction = .left
        swipeLeft.numberOfTouchesRequired = 1
        view.addGestureRecognizer(swipeLeft)
    }

    @objc private func handleSwipeLeft(_: UISwipeGestureRecognizer) {
        guard let nav = navigationController else { return }
        if nav.viewControllers.count > 1 {
            nav.popViewController(animated: true)
        } else {
            nav.dismiss(animated: true)
        }
    }
}

The recognizer is attached to the controller's root view. The navigationController.viewControllers.count check ensures pop is only performed when there is a previous screen in the stack. For modal controllers, dismiss is used. The code does not require state checking — UISwipeGestureRecognizer is discrete and calls the action only on successful recognition.

Example 2: Swipe in Android (Kotlin) with Custom OnSwipeTouchListener

Implements a simple GestureDetector wrapper that determines the swipe direction and calls onSwipeLeft/Right callbacks.

kotlin
import android.content.Context
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View

open class OnSwipeTouchListener(context: Context) : View.OnTouchListener {

    private val gestureDetector = GestureDetector(context, GestureListener())

    override fun onTouch(v: View, event: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(event)
    }

    private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {

        companion object {
            private const val SWIPE_THRESHOLD = 100
            private const val SWIPE_VELOCITY_THRESHOLD = 100
        }

        override fun onFling(
            e1: MotionEvent?,
            e2: MotionEvent,
            velocityX: Float,
            velocityY: Float
        ): Boolean {
            val diffX = e2.x - e1!!.x
            val diffY = e2.y - e1.y

            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD
                    && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD
                ) {
                    if (diffX > 0) onSwipeRight()
                    else onSwipeLeft()
                    return true
                }
            } else {
                if (Math.abs(diffY) > SWIPE_THRESHOLD
                    && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD
                ) {
                    if (diffY > 0) onSwipeDown()
                    else onSwipeUp()
                    return true
                }
            }
            return false
        }
    }

    open fun onSwipeLeft() {}
    open fun onSwipeRight() {}
    open fun onSwipeUp() {}
    open fun onSwipeDown() {}
}

OnSwipeTouchListener extends SimpleOnGestureListener, implementing onFling. diffX/diffY determine the direction, SWIPE_THRESHOLD (100px) and SWIPE_VELOCITY_THRESHOLD (100 px/s) are the thresholds. Usage: view.setOnTouchListener(OnSwipeTouchListener(context).apply { onSwipeLeft = { dismiss() } }).

Example 3: SwipeActions in iOS (UITableView)

Adds a delete button when swiping left on a table cell. Uses the built-in iOS 11+ API without manual gesture recognition.

swift
func tableView(
    _ tableView: UITableView,
    trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
) -> UISwipeActionsConfiguration? {
    let deleteAction = UIContextualAction(
        style: .destructive,
        title: "Delete"
    ) { _, _, completionHandler in
        items.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .automatic)
        completionHandler(true)
    }
    deleteAction.backgroundColor = .systemRed

    let config = UISwipeActionsConfiguration(actions: [deleteAction])
    config.performsFirstActionWithFullSwipe = true
    return config
}

The method returns UISwipeActionsConfiguration with an array of UIContextualAction. style: .destructive automatically sets the red background. performsFirstActionWithFullSwipe = true allows executing the action with a full swipe without an additional tap. At IT Sectr, we use this API for all lists with actions — it is standardized, supports VoiceOver, and does not require custom GestureRecognizers.

Frequently Asked Questions

How to distinguish a swipe from panning?

Swipe is a discrete gesture with fast movement and finger lift-off, panning is continuous dragging with coordinate tracking. UISwipeGestureRecognizer fires once, UIPanGestureRecognizer generates .began → .changed → .ended. The choice depends on the scenario: swipe is for actions (delete, flip), pan is for movement (map, slider).

Does swipe work the same on iOS and Android?

The gesture logic is identical, but the API differs. iOS uses UISwipeGestureRecognizer with direction. Android uses GestureDetector.onFling() with custom thresholds. The result is the same UX with different implementations. Cross-platform frameworks (Flutter, React Native) abstract the difference through a unified swipe API.

How to handle a swipe in a list?

In iOS (11+), use UISwipeActionsConfiguration in UITableViewDelegate. In Android, use ItemTouchHelper.SimpleCallback for RecyclerView. These APIs replace manual GestureRecognizers, support action buttons and animation, correctly handle scroll conflicts, and adapt to platform HIGs.

Summary

  • Swipe is a discrete fast finger-sliding gesture, the second most frequent after tap (23% of interactions).
  • In iOS, UISwipeGestureRecognizer handles swipes in four directions with a fixed threshold of ~20px.
  • In Android, GestureDetector.onFling() is used with custom speed and distance thresholds.
  • For lists, use UISwipeActionsConfiguration (iOS) and ItemTouchHelper (Android) instead of manual recognizers.
  • Swipe differs from panning in discreteness and high speed — do not confuse these gestures when designing.
  • A custom OnSwipeTouchListener in Android simplifies the GestureDetector API by hiding direction calculation.
  • At IT Sectr, we use swipe for navigation, item deletion, and onboarding — the gesture is intuitive and requires no learning.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also