Poin utama
Swipe adalah gerakan geser cepat jari di permukaan layar yang diakhiri dengan pengangkatan. Swipe bisa pendek (menggulir elemen) atau panjang (membuka tirai), tetapi karakteristik utamanya adalah diskrit: sistem mengenalinya sebagai satu peristiwa, bukan sebagai urutan koordinat yang berkelanjutan.
OS seluler menentukan swipe berdasarkan tiga parameter: jarak minimum (ambang batas), kecepatan minimum (velocity) dan arah. Jika jari bergerak lambat atau jarak tidak mencukupi, sistem menafsirkan gerakan sebagai pan atau tap. Nilai ambang berbeda antar platform: iOS menggunakan konstanta UISwipeGestureRecognizer dengan ambang tetap, Android — ViewConfiguration.getScaledTouchSlop(), mengembalikan ~8–16 dp tergantung kepadatan layar.
Menurut Android Developers Documentation, onFling (swipe) di GestureDetector aktif pada kecepatan di atas 100 px/s dan jarak dari 50px. Di IT Sectr kami menggunakan swipe untuk navigasi (galeri, antarmuka kartu, orientasi) — gerakan ini intuitif bagi pengguna segala usia.
Swipe dan pan (pan/drag) adalah jenis gerakan yang berbeda, meskipun keduanya menggunakan gerakan jari di layar. Swipe bersifat diskrit dan berarti „lakukan satu tindakan”, sedangkan pan bersifat kontinu dan berarti „pindahkan objek selama jari di layar”.
| Parameter | Swipe | Pan (Pan/Drag) |
|---|---|---|
| Tipe | Diskrit | Kontinu |
| Peristiwa | Satu (dikenali/tidak dikenali) | Banyak (.began → .changed → .ended) |
| Kecepatan | Tinggi (gerakan cepat) | Berapa pun (gerakan lambat) |
| Contoh iOS | UISwipeGestureRecognizer | UIPanGestureRecognizer |
| Contoh Android | GestureDetector.onFling() | GestureDetector.onScroll() |
| Skenario | Hapus email, balik halaman | Pindahkan peta, seret file |
| Pelacakan koordinat | Tidak (hanya arah) | Ya (pembaruan koordinat terus-menerus) |
Pilihan antara swipe dan pan tergantung pada tugas. Untuk tindakan pada elemen (hapus, arsip, buka menu) gunakan swipe. Untuk manipulasi langsung (memindahkan, memperbesar) — pan. Mencampur gerakan pada satu elemen memerlukan require(toFail:) atau logika kustom.
UISwipeGestureRecognizer — subkelas UIGestureRecognizer yang mengenali gesekan diskrit di salah satu dari empat arah. Berbeda dengan UIPanGestureRecognizer, ia tidak menghasilkan peristiwa .changed antara: saat pengenalan, action dipanggil tepat satu kali.
Properti direction (UISwipeGestureRecognizer.Direction) mengatur arah yang dilacak — .left, .right, .up, .down. Dapat digabungkan melalui mask: [.left, .right] untuk gesekan horizontal. Properti numberOfTouchesRequired menentukan jumlah jari — default 1. UISwipeGestureRecognizer tidak memiliki ambang jarak yang dapat dikonfigurasi — iOS menggunakan nilai bawaan sekitar 20px, cukup untuk pengenalan yang andal.
Karena UISwipeGestureRecogniser adalah pengenal diskrit, ia tidak bentrok dengan UIPanGestureRecognizer: pada gerakan lambat pan akan aktif, pada gerakan cepat — swipe. Namun saat berdampingan dengan UITapGestureRecognizer di view yang sama, require(toFail:) mungkin diperlukan untuk mencegah pengenalan tap palsu.
Di Android, API utama untuk pengenalan gesekan adalah GestureDetector dengan callback OnGestureListener, yaitu metode onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY). GestureDetector menganalisis posisi awal dan akhir jari, kecepatan gerakan sepanjang sumbu dan jarak, kemudian memanggil onFling saat melampaui ambang.
Ambang minimum dikonfigurasi melalui ViewConfiguration: VelocityTracker.getMinVelocity() (~100 px/s) dan ViewConfiguration.getScaledTouchSlop() (~8–16 dp). OnSwipeTouchListener kustom adalah pola umum yang menyederhanakan API: pengembang tidak perlu menghitung arah dan kecepatan secara manual. Android Support Library tidak menyertakan „SwipeDetector” bawaan, jadi pembungkus kustom adalah solusi standar.
Untuk gesekan di daftar, Google merekomendasikan menggunakan ItemTouchHelper.SimpleCallback dari RecyclerView, yang mengabstraksi deteksi gerakan, animasi dan callback onSwiped(). Di IT Sectr kami menggunakan SwipeListener kustom untuk ViewPager2 dan antarmuka kartu — ini memberikan kontrol atas sensitivitas gesekan tanpa mengorbankan kinerja.
Untuk daftar (UITableView, RecyclerView) Apple dan Google menyediakan API khusus yang menggantikan penambahan manual UISwipeGestureRecognizer. API ini mendukung tombol tindakan, animasi kustom dan gerakan „gesek untuk menghapus” — pola standar aplikasi mobile.
Di iOS (11+) digunakan UISwipeActionsConfiguration: metode tableView(_:leadingSwipeActionsConfigurationForRowAt:) mengembalikan array UIContextualAction — tombol dengan judul, gaya (destructive, normal) dan handler. Misalnya, „Hapus” — .destructive dengan latar merah, „Arsip” — .normal dengan abu-abu. Sistem sendiri menganimasi kemunculan tombol dan memanggil blok completion setelah ditekan.
Di Android, ItemTouchHelper.SimpleCallback dipasang ke RecyclerView melalui ItemTouchHelper.attachToRecyclerView(). Parameter — flag arah (start, end, up, down) dan callback onSwiped(viewHolder, direction). Di dalam onSwiped, adapter.notifyItemRemoved(position) dipanggil untuk menghapus elemen dengan animasi. ItemTouchHelper secara otomatis menangani gerakan, konflik dengan scroll dan pengembalian elemen jika gesekan tidak selesai. Menurut Google I/O 2024, ItemTouchHelper digunakan di 70% aplikasi Android dengan tindakan gesek di daftar.
Menambahkan UISwipeGestureRecognizer ke view untuk kembali ke layar sebelumnya. Kode menunjukkan konfigurasi minimum pengenal dengan arah .left.
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)
}
}
}
Pengenal dipasang ke root-view controller. Pemeriksaan navigationController.viewControllers.count memastikan pop hanya dilakukan jika ada layar sebelumnya di stack. Untuk controller modal digunakan dismiss. Kode tidak memerlukan pemeriksaan state — UISwipeGestureRecognizer bersifat diskrit dan memanggil action hanya saat pengenalan berhasil.
Mengimplementasikan wrapper sederhana GestureDetector yang menentukan arah gesekan dan memanggil callback onSwipeLeft/Right.
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 memperluas SimpleOnGestureListener, mengimplementasikan onFling. diffX/diffY menentukan arah, SWIPE_THRESHOLD (100px) dan SWIPE_VELOCITY_THRESHOLD (100 px/s) — ambang. Penggunaan: view.setOnTouchListener(OnSwipeTouchListener(context).apply { onSwipeLeft = { dismiss() } }).
Menambahkan tombol hapus saat menggesek ke kiri pada sel tabel. Menggunakan API bawaan iOS 11+ tanpa pengenalan gerakan manual.
func tableView(
_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(
style: .destructive,
title: "Hapus"
) { _, _, 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
}
Metode mengembalikan UISwipeActionsConfiguration dengan array UIContextualAction. style: .destructive secara otomatis mengatur latar merah. performsFirstActionWithFullSwipe = true memungkinkan menjalankan tindakan dengan gesekan penuh tanpa tekanan tambahan. Di IT Sectr kami menggunakan API ini untuk semua daftar dengan tindakan — ini terstandarisasi, mendukung VoiceOver dan tidak memerlukan GestureRecognizer kustom.
Pertanyaan yang sering diajukan
Swipe — gerakan diskrit dengan gerakan cepat dan pengangkatan jari, pan — seretan terus-menerus dengan pelacakan koordinat. UISwipeGestureRecognizer aktif sekali, UIPanGestureRecognizer menghasilkan .began → .changed → .ended. Pilihan tergantung skenario: swipe — untuk tindakan (hapus, balik), pan — untuk memindahkan (peta, slider).
Logika gerakannya identik, tetapi API berbeda. iOS menggunakan UISwipeGestureRecognizer dengan direction. Android menggunakan GestureDetector.onFling() dengan ambang kustom. Hasilnya — UX sama dengan implementasi berbeda. Framework lintas platform (Flutter, React Native) mengabstraksi perbedaan melalui API swipe terpadu.
Di iOS (11+) gunakan UISwipeActionsConfiguration di UITableViewDelegate. Di Android — ItemTouchHelper.SimpleCallback untuk RecyclerView. API ini menggantikan GestureRecognizer manual, mendukung tombol tindakan dan animasi, menangani konflik dengan scroll dengan benar dan beradaptasi dengan HIG platform.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga