Tap — gestul de bază al interfețelor tactile: atingerea unică a ecranului cu degetul urmată de eliberare. Tap este acțiunea principală (primary action) în sistemele de operare mobile — deschiderea aplicațiilor, apăsarea butoanelor, selectarea elementelor din listă. Este recunoscut în 100–300 ms și generează evenimentul de clic. Pe iOS este procesat prin UITapGestureRecognizer, pe Android — prin setOnClickListener sau View.onClick.
Principalele
Tap (atingere, apăsare) — gestul de atingere rapidă a ecranului tactil cu degetul sau stiloul. Gestul constă din două faze: atingere (touch down) și eliberare (touch up), care au loc în același loc fără deplasare. Sistemul recunoaște Tap atunci când intervalul de timp între down și up nu depășește valoarea prag (de obicei 300–500 ms). Dacă utilizatorul ține degetul mai mult — gestul se transformă în Long Press.
Tap — baza UX-ului mobil. Pe toate platformele mobile, Tap înlocuiește clicul stâng al mouse-ului utilizat în interfețele desktop. Spre deosebire de clicul mouse-ului, Tap nu are modificatori (Shift+clic, Ctrl+clic) și hover — această limitare formează designul interfețelor mobile. Pentru a compensa lipsa previzualizării, platformele mobile utilizează feedback vizual: highlight la atingere, efect ripple în Android, schimbarea transparenței în iOS.
Anatomia Tap include cinci etape la nivel de sistem: activarea senzorului (atingere), determinarea coordonatelor, filtrarea zgomotului (degetul nu trebuie să se deplaseze mai mult decât distanța prag), așteptarea finalizării (eliberare sau menținere), clasificare (Tap, Long Press, Drag). Controlerele tactile moderne procesează acest ciclu în 8–16 ms la o frecvență de interogare de 60–120 Hz.
Tap și Click — evenimente diferite cu fizică diferită. Click — eveniment de mouse care apare la apăsarea și eliberarea butonului mouse-ului în aceeași poziție. Tap — eveniment de ecran tactil care apare la atingerea cu degetul. Pe dispozitivele mobile, browserul transformă Tap în eveniment click cu o întârziere de 300–350 ms (pentru a emula dublul tap pentru zoom). Această întârziere a fost istoric o problemă a web-ului mobil, până când Apple și Google au introdus meta viewport cu user-scalable=no.
| Parametru | Tap (tactil) | Click (mouse) |
|---|---|---|
| Dispozitiv de intrare | Deget, stilou | Cursor mouse |
| Faze | touchstart → touchend | mousedown → mouseup |
| Previzualizare (hover) | Lipsește | Există (hover) |
| Întârziere | 0–500 ms | 0 ms |
| Precizie | Scăzută (degetul mai lat decât cursorul) | Ridicată (pixel) |
| Modificatori | Nu | Shift, Ctrl, Cmd |
| Multiple | Multitouch (2+ degete) | Nu (un cursor) |
Touch Events — este un API separat de Mouse Events. Evenimentele tactile (touchstart, touchmove, touchend) transmit un tablou de puncte de atingere (TouchList), coordonate, forța de apăsare (pressure) și dimensiunea zonei de atingere (radiusX, radiusY). Mouse Events transmite doar coordonatele cursorului. Browserele moderne sintetizează click din touchend, dacă nu a existat mișcare a degetului și nici eveniment touchcancel. Pointer Events API combină ambele abordări, oferind procesare unificată pentru toate dispozitivele de intrare.
UITapGestureRecognizer — recunoscătorul standard pentru Tap simplu și multiplu în iOS SDK. Suportă configurarea numberOfTapsRequired (numărul de atingeri consecutive) și numberOfTouchesRequired (numărul de degete care ating simultan). Recunoscătorul trece în starea UIGestureRecognizerStateRecognized atunci când utilizatorul eliberează degetul și atingerea nu depășește pragul de deplasare.
// UITapGestureRecognizer cu suport pentru Double Tap
class InteractiveImageViewController: UIViewController {
private var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Single Tap — arată/ascunde elementele de control
let singleTap = UITapGestureRecognizer(
target: self,
action: #selector(handleSingleTap)
)
imageView.addGestureRecognizer(singleTap)
// Double Tap — zoom-ul imaginii
let doubleTap = UITapGestureRecognizer(
target: self,
action: #selector(handleDoubleTap)
)
doubleTap.numberOfTapsRequired = 2
// Single Tap se activează numai dacă Double Tap nu este recunoscut
singleTap.require(doubleTap.toFail())
imageView.addGestureRecognizer(doubleTap)
}
@objc private func handleSingleTap() { /* afișează controalele */ }
@objc private func handleDoubleTap() { /* aplică zoom */ }
}Model important: la suportul simultan pentru Single și Double Tap, trebuie apelat require(_:toFail:). Fără aceasta, single tap va acționa imediat, nepermițând sistemului să aștepte a doua atingere. iOS suportă și recunoașterea Tap prin UIControl.addTarget — pentru UIButton, UISwitch și alte elemente de control. Controalele încorporate UIKit au deja procesare standard Tap, iar adăugarea UITapGestureRecognizer peste ele poate duce la conflicte.
View.setOnClickListener — metoda standard Android SDK pentru procesarea clicurilor pe View. Când utilizatorul atinge View și eliberează degetul pe același element (touch down → touch up în limitele View), este apelată metoda onClick(). Android adaugă automat efect ripple (la API 21+) cu animație de atingere. Butonul este considerat apăsat în starea PRESSED, care este afișată vizual prin selector sau RippleDrawable.
// setOnClickListener în Fragment cu 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()
}
// Ascultător cu debounce pentru prevenirea dublului clic
binding.submitButton.setOnClickListener(
DebouncingClickListener {
submitForm()
}
)
}
private fun submitForm() {
// Trimiterea datelor formularului
}
}Debounce — un model important în programarea Android. Utilizatorul poate apăsa accidental butonul de două ori într-un interval scurt de timp, ceea ce duce la trimiterea dublă a formularului sau executarea dublă a acțiunii. Soluție: învelișul DebouncingClickListener care blochează clicurile repetate în 500–1000 ms. Google recomandă utilizarea acestei abordări în exemplele oficiale Android Architecture Components. Pentru RecyclerView este prevăzut setOnItemClickListener prin ListAdapter cu interfață callback.
Double Tap (atingere dublă) — două Tap-uri consecutive cu un interval de cel mult 300–400 ms. Utilizat pentru zoom-ul imaginilor (hărți, fotografii), like-uri în rețele sociale (Instagram, Twitter), revenirea la începutul listei (Phone, Messages). Triple Tap (atingere triplă) este mai rar întâlnit — utilizat în principal pentru funcții de accesibilitate (mod ecran complet, VoiceOver) și în jocuri.
Implementarea Double Tap necesită sincronizare cu Single Tap: dacă adăugați ambele gesturi pe același element, Single Tap va funcționa cu întârziere (sistemul așteaptă a doua atingere). În iOS, această întârziere este controlată prin require(toFail:) — Single Tap este amânat până când sistemul este sigur că Double Tap nu va avea loc. În Android se utilizează GestureDetector.OnDoubleTapListener cu callback-urile onSingleTapConfirmed și onDoubleTap. onSingleTapConfirmed este apelat numai după timeout, când sistemul este sigur că este o atingere simplă.
// Double Tap în Android prin 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() // arată/ascunde controalele
return true
}
override fun onDoubleTap(e: MotionEvent): Boolean {
zoomToPoint(e.x, e.y) // zoom în punctul de atingere
return true
}
})
}
}Instagram-like double tap — un model UX popular pentru aplicațiile sociale. Atingerea dublă pe o fotografie declanșează animația de like (icoana inimii). Se implementează prin GestureDetector în Android sau UITapGestureRecognizer cu numberOfTapsRequired=2 în iOS. Pentru animație se utilizează Core Animation pe iOS și ObjectAnimator/AnimatorSet pe Android. Timpul de răspuns al double tap trebuie să fie minim — utilizatorul așteaptă o animație instantanee după a doua atingere.
Human Interface Guidelines Apple și Material Design Google impun cerințe specifice pentru Tap. Dimensiunea minimă a touch-target: 44×44 pt pentru iOS și 48×48 dp pentru Android. Aceasta corespunde la ~9 mm pe ecran — dimensiunea vârfului degetului unui adult mediu. Distanța dintre țintele tactile trebuie să fie de cel puțin 8 pt/dp pentru a preveni atingerile false.
| Regulă | Valoare | Justificare |
|---|---|---|
| Dimensiunea minimă a țintei | 44×44 pt (iOS) / 48×48 dp (Android) | Dimensiunea medie a vârfului degetului ~9 mm |
| Distanța între ținte | ≥8 pt / ≥8 dp | Prevenirea atingerilor false |
| Feedback vizual | Highlight / Ripple | Confirmarea înregistrării atingerii |
| Durata animației de atingere | 100–200 ms | Suficient pentru percepție, nu încetinește interfața |
| Procesarea Double Tap | Necesită întârzierea Single Tap | Prevenirea activării false |
| Zonele de margine ale ecranului | Zonă de atingere mărită | Compensarea prinderii dispozitivului |
Feedback vizual este obligatoriu pentru Tap. Utilizatorul trebuie să vadă că atingerea a fost înregistrată: schimbare de culoare, opacity, animație ripple sau highlight. Fără feedback, utilizatorul poate apăsa din nou, provocând acțiuni nedorite. În iOS, animația standard touch highlight — schimbarea transparenței la 0.3 cu durata de 0.15 s. În Android — efectul Material ripple care se răspândește din punctul de atingere. Nu utilizați întârziere înainte de feedback vizual — utilizatorul trebuie să vadă reacția simultan cu atingerea.
Întrebări frecvente
Tap — eveniment tactil, Click — eveniment de mouse. În browser, Tap este transformat în Click cu o întârziere de 300 ms (pentru a distinge de Double Tap Zoom). Browserele moderne (Chrome 32+, Safari 9.1+) dezactivează această întârziere la meta viewport cu width=device-width. Utilizați Pointer Events API pentru procesare unificată: pointerdown/pointerup sunt potrivite pentru toate dispozitivele de intrare (mouse, tactil, stilou).
Touch target minim — 44×44 puncte (iOS) sau 48×48 dp (Android). Aceasta corespunde aproximativ 9×9 mm pe ecranul fizic. Dacă butonul este vizual mai mic (de exemplu, pictogramă 24×24), măriți zona de atingere prin UIEdgeInsets (iOS) sau TouchDelegate (Android). Distanța dintre țintele adiacente trebuie să fie de cel puțin 8 unități pentru a evita atingerile false.
Double-click prevention se implementează prin mecanismul debounce: după primul clic, butonul este blocat timp de 500–1000 ms. În Android utilizați DebouncingClickListener (soluție gata din Architecture Components). În iOS — dezactivați isEnabled al butonului imediat după apăsare și reactivați prin DispatchQueue.main.asyncAfter. În aplicațiile web — setați flag-ul disabled pe elementul button după primul clic.
Long Tap (Long Press) — menținerea degetului pe ecran timp de 500+ ms fără mișcare. Tap — atingere rapidă (100–300 ms). Tap execută acțiunea principală (Primary Action), Long Tap — acțiunea secundară (meniu contextual, editare). În iOS, Tap este procesat de UITapGestureRecognizer, Long Press — de UILongPressGestureRecognizer. În Android — setOnClickListener vs setOnLongClickListener.
Da, stilourile sunt procesate ca Tap prin API-ul tactil standard. Apple Pencil transmite force (forța de apăsare), altitudeAngle (unghiul de înclinare) și azimuth (azimutul). S Pen în Android transmite parametri similari prin MotionEvent.getPressure() și getAxisValue(MotionEvent.AXIS_TILT). Pentru stilouri, touch target poate fi redus la 24×24 de puncte, deoarece precizia stiloului este mai mare decât a degetului.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și