মূল বিষয়
UIGestureRecognizer হল UIKit-এর একটি অ্যাবস্ট্রাক্ট বেস ক্লাস যা জেসচার শনাক্তকরণ প্রক্রিয়াকে পৃথক অবজেক্টে বিভক্ত করে। প্রতিটি সাবক্লাস একটি জেসচার প্রকার হ্যান্ডল করে: UITapGestureRecognizer নির্দিষ্ট সংখ্যক স্পর্শের ট্যাপ হ্যান্ডল করে, UISwipeGestureRecognizer একটি নির্দিষ্ট দিকে সোয়াইপ হ্যান্ডল করে। ডেভেলপার addGestureRecognizer(:) মেথডের মাধ্যমে UIView-এ রিকগনাইজার যোগ করে, এবং UIKit স্বয়ংক্রিয়ভাবে স্পর্শ ট্র্যাক করে, অবস্থা আপডেট করে এবং শনাক্তকরণে অ্যাকশন কল করে।
UIGestureRecognizer (iOS 3.2, 2010)-এর আগে, ডেভেলপাররা UIResponder মেথড — touchesBegan, touchesMoved, touchesEnded — ওভাররাইড করত এবং ম্যানুয়ালি স্পর্শের পথ বিশ্লেষণ করত। এর ফলে কোড ডুপ্লিকেশন এবং একসঙ্গে একাধিক স্পর্শ হ্যান্ডল করতে ত্রুটি হত। Apple এই লজিক UIGestureRecognizer-এ এনক্যাপসুলেট করেছে, মাল্টিটাচ, জেসচার বাতিল এবং একটি ভিউতে একাধিক রিকগনাইজারের একসঙ্গে পরিচালনার সমর্থন যোগ করেছে।
WWDC সেশন অনুসারে, Gesture Recognizer iPad-এ 11টি একসঙ্গে স্পর্শ এবং iPhone-এ 5টি হ্যান্ডল করে। IT Sectr-এ, আমরা সব UIKit প্রকল্পে ব্যবহারকারী ইনপুট হ্যান্ডল করার মানক উপায় হিসেবে UIGestureRecognizer ব্যবহার করি — এটি ম্যানুয়াল touchesBegan ট্র্যাকিংয়ের সাথে সম্পর্কিত বাগ দূর করেছে।
প্রতিটি UIGestureRecognizer 7টি সম্ভাব্য অবস্থার মধ্য দিয়ে যায়, যা UIGestureRecognizer.State এনামে সংজ্ঞায়িত। এই অবস্থাগুলি শনাক্তকরণ জীবনচক্র প্রতিফলিত করে: স্পর্শ সনাক্তকরণ থেকে সম্পূর্ণ বা বাতিল হওয়া পর্যন্ত। কাস্টম রিকগনাইজার ইমপ্লিমেন্ট এবং দ্বন্দ্ব ডিবাগ করার জন্য অবস্থা বোঝা গুরুত্বপূর্ণ।
| অবস্থা | অর্থ | কখন ঘটে |
|---|---|---|
| .possible | প্রাথমিক অবস্থা, জেসচার এখনও শনাক্ত হয়নি | ভিউতে যোগ করার সাথে সাথেই |
| .began | জেসচার শনাক্ত হয়েছে এবং কার্যকর করা শুরু হয়েছে | pan/longPress-এর জন্য প্রথম আঙুল নড়াচড়ায় |
| .changed | জেসচার প্যারামিটার পরিবর্তিত হয়েছে (কোঅর্ডিনেট, কোণ) | প্রতিটি আঙুল নড়াচড়ায় |
| .ended | ব্যবহারকারী আঙুল তুলেছেন, জেসচার সম্পন্ন | touchesEnded-এ |
| .cancelled | জেসচার সিস্টেম দ্বারা বাধাপ্রাপ্ত (ইনকামিং কল, ওরিয়েন্টেশন পরিবর্তন) | touchesCancelled-এ |
| .failed | শর্ত অনুযায়ী জেসচার শনাক্ত হয়নি | শনাক্তকরণ ছাড়া touchesCancelled-এ |
| .recognized | .ended-এর সমার্থক; জেসচার সফলভাবে শনাক্ত হয়েছে | .ended-এর মতোই |
ডিসক্রিট জেসচার (tap, swipe) .possible থেকে সরাসরি .ended বা .failed-এ যায়। কন্টিনিউয়াস জেসচার (pan, pinch, rotation, longPress) .possible → .began → .changed (পুনরাবৃত্ত) → .ended-এর মধ্য দিয়ে যায়। অ্যাকশন মেথডে gestureRecognizer.state চেক করুন — এটি জেসচারের শুরু, পরিবর্তন এবং শেষ আলাদা করতে দেয়।
UIKit 7টি বিল্ট-ইন UIGestureRecognizer সাবক্লাস প্রদান করে, যা অধিকাংশ ইন্টারঅ্যাকশন পরিস্থিতি কভার করে। প্রতিটি সাবক্লাসের নির্দিষ্ট সেটিংস রয়েছে: ট্যাপের জন্য numberOfTapsRequired, সোয়াইপের জন্য direction, লং প্রেসের জন্য minimumPressDuration।
কাস্টম জেসচারের জন্য (যেমন, জিগজ্যাগ আঁকা), touchesBegan, touchesMoved, touchesEnded ওভাররাইড করে এবং অবস্থা আপডেট করে UIGestureRecognizer-এর সাবক্লাস তৈরি করা হয়। Apple যেখানে সম্ভব বিল্ট-ইন ক্লাস ব্যবহার করার পরামর্শ দেয় — সেগুলি অপ্টিমাইজড এবং একে অপরের সাথে সঠিকভাবে ইন্টারঅ্যাক্ট করে।
যখন একটি UIView-এ একাধিক UIGestureRecognizer ব্যবহার করা হয় (যেমন, ট্যাপ এবং ডাবল-ট্যাপ), তখন একটি শনাক্তকরণ দ্বন্দ্ব ঘটে: ডাবল ট্যাপে, সিঙ্গেল ট্যাপ প্রথমে ফায়ার করে। Apple একটি জেসচারের শনাক্তকরণ বিলম্বিত করার জন্য require(toFail:) মেথড প্রদান করে যতক্ষণ না অন্যটি ব্যর্থ হয়।
প্রক্রিয়াটি এভাবে কাজ করে: tapRecognizer.require(toFail: doubleTapRecognizer) কল করে, আপনি নির্দিষ্ট করেন যে tapRecognizer .recognized অবস্থায় যাবে শুধুমাত্র doubleTapRecognizer .failed-এ শেষ হওয়ার পর। এটি সিঙ্গেল ট্যাপ কার্যকর করার আগে ~0.3 সেকেন্ড বিলম্ব যোগ করে — ব্যবহারকারী দুবার ট্যাপ করে, এবং প্রথম ট্যাপ উপেক্ষিত হয়। বিকল্প পদ্ধতি হল UIGestureRecognizerDelegate যার gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) মেথড রয়েছে, যা একসঙ্গে শনাক্তকরণের অনুমতি দেয় (যেমন, ম্যাপের জন্য pan + pinch)।
WWDC 2020 অনুসারে, UIKit অ্যাপ্লিকেশনে প্রায় 15% বাগ জেসচার দ্বন্দ্বের ভুল কনফিগারেশনের সাথে সম্পর্কিত। IT Sectr-এ, আমরা পদ্ধতিটি মানক করেছি: প্রতিটি স্ক্রিনে require(toFail:) অগ্রাধিকার সহ একটি জেসচার স্কিম রয়েছে — এটি ডাবল-ট্যাপ ফায়ারিং বাগ সম্পূর্ণরূপে দূর করেছে।
UIImageView-তে একটি সিঙ্গেল ট্যাপ হ্যান্ডলার যোগ করে। ট্যাপ করলে, ছবির অস্বচ্ছতা পরিবর্তিত হয় — একটি সহজ উদাহরণ যা ভিউতে জেসচার বাইন্ডিং দেখায়।
import UIKit
class ImageViewController: UIViewController {
@IBOutlet private var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(
target: self,
action: #selector(handleTap(_:))
)
tap.numberOfTapsRequired = 1
imageView.addGestureRecognizer(tap)
imageView.isUserInteractionEnabled = true
}
@objc private func handleTap(_: UITapGestureRecognizer) {
UIView.animate(withDuration: 0.2) {
self.imageView.alpha = self.imageView.alpha == 1.0 ? 0.5 : 1.0
}
}
}
মূল বিষয়: UIImageView-এ isUserInteractionEnabled ডিফল্টরূপে false — এই ফ্লাগ ছাড়া, Gesture Recognizer স্পর্শ পাবে না। UIView এবং UIButton-এর জন্য, এই ফ্লাগ ডিফল্টরূপে সক্রিয়। অ্যাকশন মেথড UITapGestureRecognizer প্যারামিটার গ্রহণ করে, যার মাধ্যমে ট্যাপ কোঅর্ডিনেট নির্ধারণ করতে location(in:) পাওয়া যায়।
পূর্ববর্তী স্ক্রিনে ফিরে যেতে বাম সোয়াইপ ইমপ্লিমেন্ট করে। দিক কনফিগারেশন এবং কন্ট্রোলারের রুট ভিউতে জেসচার বাইন্ডিং প্রদর্শন করে।
import UIKit
class DetailViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let swipeLeft = UISwipeGestureRecognizer(
target: self,
action: #selector(handleSwipe(_:))
)
swipeLeft.direction = .left
view.addGestureRecognizer(swipeLeft)
}
@objc private func handleSwipe(_: UISwipeGestureRecognizer) {
navigationController?.popViewController(animated: true)
}
}
UISwipeGestureRecognizer একটি ডিসক্রিট জেসচার: এটি শনাক্তকরণের পরপরই .recognized-এ চলে যায়, কোনো মধ্যবর্তী .changed অবস্থা ছাড়া। তাই, অ্যাকশনে অবস্থা চেক করার প্রয়োজন নেই — জেসচার হয় শনাক্ত হয় (অ্যাকশন ফায়ার হয়) বা না হয়। direction প্রপার্টি চারটি মানের একটি গ্রহণ করে: .left, .right, .up, .down। একাধিক দিক সমর্থনের জন্য, প্রতিটির জন্য আলাদা রিকগনাইজার তৈরি করুন।
দেখায় কিভাবে দ্বন্দ্ব ছাড়া একটি ভিউতে সিঙ্গেল এবং ডাবল ট্যাপ কনফিগার করতে হয়। ডাবল-ট্যাপ রিকগনাইজারের অগ্রাধিকার রয়েছে — সিঙ্গেল ট্যাপ শুধুমাত্র তখনই ফায়ার হয় যদি ডাবল ট্যাপ শনাক্ত না হয়।
import UIKit
class TapViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let singleTap = UITapGestureRecognizer(
target: self,
action: #selector(handleSingleTap)
)
singleTap.numberOfTapsRequired = 1
let doubleTap = UITapGestureRecognizer(
target: self,
action: #selector(handleDoubleTap)
)
doubleTap.numberOfTapsRequired = 2
singleTap.require(toFail: doubleTap)
view.addGestureRecognizer(singleTap)
view.addGestureRecognizer(doubleTap)
}
@objc private func handleSingleTap() {
print("Single tap — after 0.3s delay")
}
@objc private func handleDoubleTap() {
print("Double tap — instant")
}
}
require(toFail:) ছাড়া, ডাবল ট্যাপে, প্রথমে handleSingleTap ফায়ার হয়, তারপর handleDoubleTap — এটি UX ভেঙে দেয়। require(toFail:) দিয়ে, সিঙ্গেল ট্যাপ ~0.3 সেকেন্ড অপেক্ষা করে যাতে নিশ্চিত হয় দ্বিতীয় ট্যাপ আসছে না। IT Sectr-এ, এই প্যাটার্ন ইমেজ এডিটর এবং গ্যালারিতে ব্যবহৃত হয়, যেখানে ডাবল ট্যাপ জুম করে এবং সিঙ্গেল ট্যাপ একটি এলিমেন্ট নির্বাচন করে।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
হ্যাঁ, UIView একসঙ্গে একাধিক UIGestureRecognizer ইনস্ট্যান্স সমর্থন করে। দ্বন্দ্ব সমাধানের জন্য, require(toFail:) মেথড ব্যবহার করুন যা শনাক্তকরণ ক্রম নির্ধারণ করে। সমান্তরাল জেসচার অপারেশনের জন্য (যেমন, ম্যাপে pan + pinch), gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) ডেলিগেট মেথড true রিটার্ন করে ইমপ্লিমেন্ট করুন।
UIGestureRecognizer একটি উচ্চ-স্তরের অ্যাবস্ট্রাকশন যা স্বয়ংক্রিয়ভাবে স্পর্শ প্যাটার্ন শনাক্ত করে এবং অবস্থা পরিচালনা করে। touchesBegan হল UIResponder-এর একটি নিম্ন-স্তরের মেথড যাতে ম্যানুয়াল কোঅর্ডিনেট ট্র্যাকিং, সময় নির্ধারণ এবং স্পর্শ বাতিলের প্রয়োজন হয়। Gesture Recognizer সরল, আরও নির্ভরযোগ্য এবং মানক জেসচারের জন্য পছন্দনীয়; touchesBegan শুধুমাত্র কাস্টম গ্রাফিক্সের জন্য যুক্তিযুক্ত।
নেটিভ SwiftUI মডিফায়ার ব্যবহার করে: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture। এগুলি SwiftUI হায়ারার্কিতে একীভূত UIGestureRecognizer-এর ডিক্লারেটিভ অ্যানালগ। প্রয়োজন হলে, UIViewRepresentable-এর মাধ্যমে UIKit রিকগনাইজার মোড়ানো যায়, কিন্তু Apple নেটিভ SwiftUI জেসচার ব্যবহারের পরামর্শ দেয়।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন