یک حرکت لمسی زمانی اتفاق میافتد که کاربر یک یا چند انگشت خود را روی صفحه لمسی قرار میدهد و برنامه شما این الگوی لمس را به عنوان یک حرکت تفسیر میکند. دو مرحله برای تشخیص ژست وجود دارد:
- در حال جمعآوری دادههای رویداد لمسی.
- تفسیر داده ها برای تعیین اینکه آیا با معیارهای حرکاتی که برنامه شما پشتیبانی می کند مطابقت دارد یا خیر.
کلاس های اندروید ایکس
مثالهای این سند از کلاسهای GestureDetectorCompat
و MotionEventCompat
استفاده میکنند. این کلاس ها در کتابخانه AndroidX هستند. در صورت امکان از کلاس های AndroidX برای ارائه سازگاری با دستگاه های قبلی استفاده کنید. MotionEventCompat
جایگزینی برای کلاس MotionEvent
نیست . در عوض، روشهای ابزار ثابتی را ارائه میکند که شی MotionEvent
خود را برای دریافت اکشن مرتبط با آن رویداد به آن پاس میدهید.
داده ها را جمع آوری کنید
هنگامی که یک کاربر یک یا چند انگشت خود را روی صفحه قرار میدهد، این کار باعث میشود که در نمائی که رویدادهای لمسی را دریافت میکند، روی onTouchEvent()
پاسخ تماس بگیرد. برای هر دنباله ای از رویدادهای لمسی - مانند موقعیت، فشار، اندازه، و اضافه کردن یک انگشت دیگر - که به عنوان یک حرکت مشخص می شود، onTouchEvent()
چندین بار شلیک می شود.
ژست زمانی شروع می شود که کاربر برای اولین بار صفحه را لمس می کند، تا زمانی که سیستم موقعیت انگشت یا انگشتان کاربر را ردیابی می کند ادامه می یابد و با ثبت آخرین رویداد خروج آخرین انگشت کاربر از صفحه به پایان می رسد. در طول این تعامل، MotionEvent
ارائه شده به onTouchEvent()
جزئیات هر تعامل را ارائه می دهد. برنامه شما میتواند از دادههای ارائهشده توسط MotionEvent
استفاده کند تا تشخیص دهد آیا حرکتی که برایش مهم است رخ میدهد یا خیر.
از رویدادهای لمسی برای یک فعالیت یا نمایش عکس بگیرید
برای رهگیری رویدادهای لمسی در یک Activity
یا View
، پاسخ تماس onTouchEvent()
لغو کنید.
قطعه کد زیر از getAction()
برای استخراج عملی که کاربر از پارامتر event
انجام می دهد استفاده می کند. این دادههای خامی را به شما میدهد که برای تعیین اینکه آیا حرکتی که برایتان مهم است رخ میدهد یا خیر.
کاتلین
class MainActivity : Activity() { ... // This example shows an Activity. You can use the same approach if you are // subclassing a View. override fun onTouchEvent(event: MotionEvent): Boolean { return when (event.action) { MotionEvent.ACTION_DOWN -> { Log.d(DEBUG_TAG, "Action was DOWN") true } MotionEvent.ACTION_MOVE -> { Log.d(DEBUG_TAG, "Action was MOVE") true } MotionEvent.ACTION_UP -> { Log.d(DEBUG_TAG, "Action was UP") true } MotionEvent.ACTION_CANCEL -> { Log.d(DEBUG_TAG, "Action was CANCEL") true } MotionEvent.ACTION_OUTSIDE -> { Log.d(DEBUG_TAG, "Movement occurred outside bounds of current screen element") true } else -> super.onTouchEvent(event) } } }
جاوا
public class MainActivity extends Activity { ... // This example shows an Activity. You can use the same approach if you are // subclassing a View. @Override public boolean onTouchEvent(MotionEvent event){ switch(event.getAction()) { case (MotionEvent.ACTION_DOWN) : Log.d(DEBUG_TAG,"Action was DOWN"); return true; case (MotionEvent.ACTION_MOVE) : Log.d(DEBUG_TAG,"Action was MOVE"); return true; case (MotionEvent.ACTION_UP) : Log.d(DEBUG_TAG,"Action was UP"); return true; case (MotionEvent.ACTION_CANCEL) : Log.d(DEBUG_TAG,"Action was CANCEL"); return true; case (MotionEvent.ACTION_OUTSIDE) : Log.d(DEBUG_TAG,"Movement occurred outside bounds of current screen element"); return true; default : return super.onTouchEvent(event); } }
این کد با ضربه زدن، لمس و نگه داشتن و کشیدن کاربر، پیام هایی مانند زیر را در Logcat تولید می کند:
GESTURES D Action was DOWN GESTURES D Action was UP GESTURES D Action was MOVE
برای ژستهای سفارشی، میتوانید پردازش خود را روی این رویدادها انجام دهید تا تعیین کنید آیا آنها نشاندهنده حرکتی هستند که باید انجام دهید. با این حال، اگر برنامه شما از حرکات متداول مانند دو ضربه سریع، لمس و نگه داشتن، پرت کردن و غیره استفاده می کند، می توانید از کلاس GestureDetector
استفاده کنید. GestureDetector
تشخیص حرکات معمول را بدون پردازش رویدادهای لمسی فردی برای شما آسانتر میکند. این بیشتر در Detect gestures مورد بحث قرار گرفته است.
رویدادهای لمسی را برای یک نمای واحد ثبت کنید
به عنوان جایگزینی برای onTouchEvent()
، می توانید یک شی View.OnTouchListener
را با استفاده از متد setOnTouchListener()
به هر شی View
متصل کنید. این کار امکان گوش دادن به رویدادهای لمسی را بدون طبقهبندی یک View
موجود، همانطور که در مثال زیر نشان داده شده است:
کاتلین
findViewById<View>(R.id.my_view).setOnTouchListener { v, event -> // Respond to touch events. true }
جاوا
View myView = findViewById(R.id.my_view); myView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // Respond to touch events. return true; } });
مراقب ایجاد شنونده ای باشید که برای رویداد ACTION_DOWN
false
را برمی گرداند. اگر این کار را انجام دهید، شنونده برای توالی رویدادهای بعدی ACTION_MOVE
و ACTION_UP
فراخوانی نمی شود. این به این دلیل است که ACTION_DOWN
نقطه شروع همه رویدادهای لمسی است.
اگر یک نمای سفارشی ایجاد میکنید، میتوانید onTouchEvent()
همانطور که قبلا توضیح داده شد لغو کنید.
تشخیص حرکات
اندروید کلاس GestureDetector
را برای تشخیص ژست های متداول ارائه می دهد. برخی از ژستهایی که پشتیبانی میکند عبارتند از onDown()
، onLongPress()
و onFling()
. می توانید از GestureDetector
در ارتباط با متد onTouchEvent()
که قبلا توضیح داده شد استفاده کنید.
همه حرکات پشتیبانی شده را شناسایی کنید
وقتی یک شی GestureDetectorCompat
نمونه سازی می کنید، یکی از پارامترهایی که می گیرد کلاسی است که رابط GestureDetector.OnGestureListener
را پیاده سازی می کند. GestureDetector.OnGestureListener
هنگامی که یک رویداد لمسی خاص رخ می دهد به کاربران اطلاع می دهد. برای اینکه آبجکت GestureDetector
شما بتواند رویدادها را دریافت کند، روش onTouchEvent()
view یا اکتیویتی را لغو کنید و همه رویدادهای مشاهده شده را به نمونه آشکارساز منتقل کنید.
در قطعه زیر، مقدار بازگشتی true
از فردی on <TouchEvent>
نشان میدهد که رویداد لمسی مدیریت میشود. مقدار بازگشتی false
رویدادها را از طریق پشته view به پایین منتقل می کند تا زمانی که لمس با موفقیت انجام شود.
اگر قطعه زیر را در یک برنامه آزمایشی اجرا کنید، می توانید احساس کنید که هنگام تعامل با صفحه لمسی چگونه اقدامات انجام می شود و محتوای MotionEvent
برای هر رویداد لمسی چیست. سپس می بینید که چه مقدار داده برای تعاملات ساده تولید می شود.
کاتلین
private const val DEBUG_TAG = "Gestures" class MainActivity : Activity(), GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener { private lateinit var mDetector: GestureDetectorCompat // Called when the activity is first created. public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Instantiate the gesture detector with the // application context and an implementation of // GestureDetector.OnGestureListener. mDetector = GestureDetectorCompat(this, this) // Set the gesture detector as the double-tap // listener. mDetector.setOnDoubleTapListener(this) } override fun onTouchEvent(event: MotionEvent): Boolean { return if (mDetector.onTouchEvent(event)) { true } else { super.onTouchEvent(event) } } override fun onDown(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDown: $event") return true } override fun onFling( event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean { Log.d(DEBUG_TAG, "onFling: $event1 $event2") return true } override fun onLongPress(event: MotionEvent) { Log.d(DEBUG_TAG, "onLongPress: $event") } override fun onScroll( event1: MotionEvent, event2: MotionEvent, distanceX: Float, distanceY: Float ): Boolean { Log.d(DEBUG_TAG, "onScroll: $event1 $event2") return true } override fun onShowPress(event: MotionEvent) { Log.d(DEBUG_TAG, "onShowPress: $event") } override fun onSingleTapUp(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onSingleTapUp: $event") return true } override fun onDoubleTap(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDoubleTap: $event") return true } override fun onDoubleTapEvent(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDoubleTapEvent: $event") return true } override fun onSingleTapConfirmed(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onSingleTapConfirmed: $event") return true } }
جاوا
public class MainActivity extends Activity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{ private static final String DEBUG_TAG = "Gestures"; private GestureDetectorCompat mDetector; // Called when the activity is first created. @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Instantiate the gesture detector with the // application context and an implementation of // GestureDetector.OnGestureListener. mDetector = new GestureDetectorCompat(this,this); // Set the gesture detector as the double-tap // listener. mDetector.setOnDoubleTapListener(this); } @Override public boolean onTouchEvent(MotionEvent event){ if (this.mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString()); return true; } @Override public void onLongPress(MotionEvent event) { Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); } @Override public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) { Log.d(DEBUG_TAG, "onScroll: " + event1.toString() + event2.toString()); return true; } @Override public void onShowPress(MotionEvent event) { Log.d(DEBUG_TAG, "onShowPress: " + event.toString()); } @Override public boolean onSingleTapUp(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString()); return true; } @Override public boolean onDoubleTap(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); return true; } @Override public boolean onDoubleTapEvent(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString()); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); return true; } }
زیر مجموعه ای از حرکات پشتیبانی شده را شناسایی کنید
اگر میخواهید فقط چند حرکت را پردازش کنید، میتوانید به جای اجرای رابط GestureDetector.OnGestureListener
GestureDetector.SimpleOnGestureListener
را گسترش دهید.
GestureDetector.SimpleOnGestureListener
یک پیاده سازی برای همه متدهای on <TouchEvent>
با برگرداندن false
برای همه آنها فراهم می کند. این به شما امکان می دهد فقط روش هایی را که به آنها اهمیت می دهید نادیده بگیرید. به عنوان مثال، قطعه کد زیر کلاسی را ایجاد می کند که GestureDetector.SimpleOnGestureListener
را گسترش می دهد و onFling()
و onDown()
را لغو می کند.
چه از GestureDetector.OnGestureListener
یا GestureDetector.SimpleOnGestureListener
استفاده کنید، این بهترین تمرین برای پیاده سازی متد onDown()
است که true
را برمی گرداند. این به این دلیل است که همه ژستها با یک پیام onDown()
شروع میشوند. اگر false
از onDown()
برگردانید، همانطور که GestureDetector.SimpleOnGestureListener
به طور پیش فرض انجام می دهد، سیستم فرض می کند که می خواهید بقیه ژست را نادیده بگیرید و سایر روش های GestureDetector.OnGestureListener
نامیده نمی شوند. این ممکن است باعث ایجاد مشکلات غیرمنتظره در برنامه شما شود. فقط اگر واقعاً میخواهید یک ژست کامل را نادیده بگیرید، از onDown()
false
را برگردانید.
کاتلین
private const val DEBUG_TAG = "Gestures" class MainActivity : Activity() { private lateinit var mDetector: GestureDetectorCompat public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mDetector = GestureDetectorCompat(this, MyGestureListener()) } override fun onTouchEvent(event: MotionEvent): Boolean { mDetector.onTouchEvent(event) return super.onTouchEvent(event) } private class MyGestureListener : GestureDetector.SimpleOnGestureListener() { override fun onDown(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDown: $event") return true } override fun onFling( event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean { Log.d(DEBUG_TAG, "onFling: $event1 $event2") return true } } }
جاوا
public class MainActivity extends Activity { private GestureDetectorCompat mDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDetector = new GestureDetectorCompat(this, new MyGestureListener()); } @Override public boolean onTouchEvent(MotionEvent event){ if (this.mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } class MyGestureListener extends GestureDetector.SimpleOnGestureListener { private static final String DEBUG_TAG = "Gestures"; @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString()); return true; } } }