Tap — базовий жест сенсорних інтерфейсів: одноразовий дотик пальцем екрана з наступним відпусканням. Tap є первинною дією в мобільних операційних системах — відкриття додатків, натискання кнопок, вибір елементів списку. Розпізнається за 100–300 мс і генерує подію кліка. На iOS обробляється через UITapGestureRecognizer, на Android — через setOnClickListener або View.onClick.
Головне
Tap (дотик, натискання) — жест швидкого дотику сенсорного екрана пальцем або стилусом. Жест складається з двох фаз: дотик вниз і відпускання, які відбуваються в одному місці без переміщення. Система розпізнає Tap, коли часовий інтервал між down і up не перевищує порогового значення (зазвичай 300–500 мс). Якщо користувач тримає палець довше — жест перетворюється на довге натискання.
Tap — основа мобільного UX. На всіх мобільних платформах Tap замінює лівий клік миші, який використовується в десктопних інтерфейсах. На відміну від кліка миші, Tap не має модифікаторів (Shift+клік, Ctrl+клік) і ховера — це обмеження формує дизайн мобільних інтерфейсів. Щоб компенсувати відсутність попереднього перегляду, мобільні платформи використовують візуальний зворотний зв'язок: підсвічування при дотику, ripple-ефект в Android, зміну прозорості в iOS.
Анатомія Tap включає п'ять етапів на рівні системи: пробудження сенсора (дотик), визначення координат, фільтрація шуму (палець не повинен зміщуватися більш ніж на порогову відстань), очікування завершення (відпускання або утримання), класифікація (Tap, довге натискання, перетягування). Сучасні сенсорні контролери обробляють цей цикл за 8–16 мс при частоті опитування 60–120 Гц.
Tap і Click — різні події з різною фізикою. Click — подія миші, що виникає при натисканні та відпусканні кнопки миші в одній позиції. Tap — подія сенсорного екрана, що виникає при дотику пальця. На мобільних пристроях браузер перетворює Tap на подію click із затримкою 300–350 мс (для емуляції подвійного дотику для збільшення). Ця затримка історично була проблемою мобільного вебу, поки Apple і Google не впровадили meta viewport з user-scalable=no.
| Параметр | Tap (сенсорний) | Click (миша) |
|---|---|---|
| Пристрій введення | Палець, стилус | Курсор миші |
| Фази | touchstart → touchend | mousedown → mouseup |
| Попередній перегляд (ховер) | Відсутній | Є (hover) |
| Затримка | 0–500 мс | 0 мс |
| Точність | Низька (палець ширший за курсор) | Висока (піксельна) |
| Модифікатори | Немає | Shift, Ctrl, Cmd |
| Множинні | Мультитач (2+ пальці) | Ні (один курсор) |
Touch Events — це окремий API від Mouse Events. Сенсорні події (touchstart, touchmove, touchend) передають масив точок дотику (TouchList), координати, силу натискання (pressure) і розмір області дотику (radiusX, radiusY). Mouse Events передають лише координати курсора. Сучасні браузери синтезують click із touchend, якщо не було руху пальця та не було події touchcancel. Pointer Events API об'єднує обидва підходи, надаючи уніфіковану обробку всіх пристроїв введення.
UITapGestureRecognizer — стандартний розпізнавач одиночного та множинного Tap в iOS SDK. Підтримує конфігурацію numberOfTapsRequired (кількість послідовних натискань) і numberOfTouchesRequired (кількість одночасно дотичних пальців). Розпізнавач переходить у стан UIGestureRecognizerStateRecognized, коли користувач відпускає палець і дотик не перевищує поріг переміщення.
// UITapGestureRecognizer з підтримкою Double Tap
class InteractiveImageViewController: UIViewController {
private var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Single Tap — показати/сховати елементи керування
let singleTap = UITapGestureRecognizer(
target: self,
action: #selector(handleSingleTap)
)
imageView.addGestureRecognizer(singleTap)
// Double Tap — збільшення зображення
let doubleTap = UITapGestureRecognizer(
target: self,
action: #selector(handleDoubleTap)
)
doubleTap.numberOfTapsRequired = 2
// Single Tap спрацьовує тільки якщо Double Tap не розпізнано
singleTap.require(doubleTap.toFail())
imageView.addGestureRecognizer(doubleTap)
}
@objc private func handleSingleTap() { /* показать контролы */ }
@objc private func handleDoubleTap() { /* зуммировать */ }
}Важливий патерн: при одночасній підтримці Single і Double Tap необхідно викликати require(_:toFail:). Без цього single tap спрацьовуватиме одразу, не даючи системі дочекатися другого натискання. iOS також підтримує розпізнавання Tap через UIControl.addTarget — для UIButton, UISwitch та інших елементів керування. Вбудовані контроли UIKit вже мають стандартну обробку Tap, і додавання UITapGestureRecognizer поверх них може призвести до конфліктів.
View.setOnClickListener — стандартний метод Android SDK для обробки кліків по View. Коли користувач торкається View і відпускає палець на тому ж елементі (touch down → touch up в межах View), викликається метод onClick(). Android автоматично додає ripple-ефект (на API 21+) з анімацією дотику. Кнопка вважається натиснутою в стані PRESSED, який візуально відображається через селектор або RippleDrawable.
// setOnClickListener у Fragment з Data Binding
class ItemListFragment : Fragment() {
private var binding: FragmentItemListBinding? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentItemListBinding.bind(view)
binding.submitButton.setOnClickListener {
submitForm()
}
// Слухач з debounce для запобігання подвійному кліку
binding.submitButton.setOnClickListener(
DebouncingClickListener {
submitForm()
}
)
}
private fun submitForm() {
// Надсилання даних форми
}
}Debounce — важливий патерн в Android-розробці. Користувач може випадково натиснути кнопку двічі за короткий проміжок часу, що призведе до подвійного надсилання форми або подвійного виконання дії. Рішення: обгортка DebouncingClickListener, яка блокує повторні кліки протягом 500–1000 мс. Google рекомендує цей підхід в офіційних прикладах Android Architecture Components. Для RecyclerView передбачено setOnItemClickListener через ListAdapter з callback інтерфейсом.
Double Tap (подвійне натискання) — два послідовних Tap з інтервалом не більше 300–400 мс. Використовується для збільшення зображень (карти, фото), лайків у соціальних мережах (Instagram, Twitter), повернення до початку списку (Телефон, Повідомлення). Triple Tap (потрійне натискання) зустрічається рідше — застосовується в основному для accessibility-функцій (повноекранний режим, VoiceOver) та в іграх.
Реалізація Double Tap вимагає синхронізації з Single Tap: якщо додати обидва жести на один елемент, Single Tap спрацьовуватиме із затримкою (система чекає другого натискання). В iOS ця затримка керується через require(toFail:) — Single Tap відкладається до впевненості, що Double Tap не відбудеться. В Android використовується GestureDetector.OnDoubleTapListener з колбеками onSingleTapConfirmed і onDoubleTap. onSingleTapConfirmed викликається лише після таймауту, коли система впевнена, що це одиночне натискання.
// Double Tap в Android через GestureDetector
class PhotoViewerActivity : AppCompatActivity() {
private var gestureDetector: GestureDetector? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
toggleControls() // показати/сховати контроли
return true
}
override fun onDoubleTap(e: MotionEvent): Boolean {
zoomToPoint(e.x, e.y) // зум у точці дотику
return true
}
})
}
}Instagram-like double tap — популярний UX-патерн для соціальних додатків. Подвійне натискання на фото викликає анімацію лайка (іконка серця). Реалізується через GestureDetector в Android або UITapGestureRecognizer з numberOfTapsRequired=2 в iOS. Для анімації використовується Core Animation на iOS і ObjectAnimator/AnimatorSet на Android. Час відгуку double tap має бути мінімальним — користувач очікує миттєвої анімації після другого натискання.
Human Interface Guidelines Apple та Material Design Google висувають конкретні вимоги до Tap. Мінімальний розмір touch-target: 44×44 pt для iOS та 48×48 dp для Android. Це відповідає ~9 мм на екрані — розмір подушечки пальця середньої дорослої людини. Відстань між touch-цілями має бути не менше 8 pt/dp, щоб запобігти хибним натисканням.
| Правило | Значення | Обґрунтування |
|---|---|---|
| Мінімальний розмір цілі | 44×44 pt (iOS) / 48×48 dp (Android) | Середній розмір подушечки пальця ~9 мм |
| Відступ між цілями | ≥8 pt / ≥8 dp | Запобігання хибним натисканням |
| Візуальний фідбек | Підсвічування / Ripple | Підтвердження реєстрації дотику |
| Тривалість анімації натискання | 100–200 мс | Достатньо для сприйняття, не гальмує інтерфейс |
| Обробка Double Tap | Вимагає затримки Single Tap | Запобігання хибному спрацьовуванню |
| Edge-області екрана | Збільшена зона попадання | Компенсація хвату пристрою |
Візуальний зворотний зв'язок обов'язковий для Tap. Користувач повинен бачити, що дотик зареєстровано: зміна кольору, прозорості, ripple-анімація або підсвічування. Без фідбеку користувач може натиснути повторно, викликаючи небажані дії. В iOS стандартна анімація touch highlight — зміна прозорості на 0.3 з тривалістю 0.15 с. В Android — Material ripple-ефект, що поширюється від точки дотику. Не використовуйте затримку перед візуальним фідбеком — користувач повинен бачити реакцію одночасно з дотиком.
Часті запитання
Tap — сенсорна подія, Click — подія миші. У браузері Tap перетворюється на Click із затримкою 300 мс (для відрізнення від Double Tap Zoom). Сучасні браузери (Chrome 32+, Safari 9.1+) вимикають цю затримку при meta viewport з width=device-width. Використовуйте Pointer Events API для уніфікованої обробки: pointerdown/pointerup підходять для всіх пристроїв введення (миша, тач, стилус).
Мінімальний touch target — 44×44 точки (iOS) або 48×48 dp (Android). Це відповідає приблизно 9×9 мм на фізичному екрані. Якщо кнопка візуально менша (наприклад, іконка 24×24), збільшіть hit area через UIEdgeInsets (iOS) або TouchDelegate (Android). Відступ між сусідніми цілями має бути не менше 8 одиниць, щоб уникнути хибних натискань.
Double-click prevention реалізується через debounce-механізм: після першого кліка кнопка блокується на 500–1000 мс. В Android використовуйте DebouncingClickListener (готове рішення з Architecture Components). В iOS — вимикайте isEnabled кнопки одразу після натискання та вмикайте через DispatchQueue.main.asyncAfter. У веб-додатках — встановлюйте прапорець disabled на елементі button після першого кліка.
Long Tap (довге натискання) — утримання пальця на екрані 500+ мс без переміщення. Tap — швидкий дотик (100–300 мс). Tap виконує основну дію (Primary Action), Long Tap — вторинну (контекстне меню, редагування). На iOS Tap обробляється UITapGestureRecognizer, Long Press — UILongPressGestureRecognizer. На Android — setOnClickListener vs setOnLongClickListener.
Так, стилуси обробляються як Tap через стандартний сенсорний API. Apple Pencil передає force (сила натискання), altitudeAngle (кут нахилу) та azimuth (азимут). S Pen в Android передає аналогічні параметри через MotionEvent.getPressure() та getAxisValue(MotionEvent.AXIS_TILT). Для стилусів можна зменшити touch target до 24×24 точок, оскільки точність стилуса вища за палець.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.