ท่าทางสัมผัสการแตะเกิดขึ้นเมื่อผู้ใช้วางนิ้วอย่างน้อย 1 นิ้วบน และแอปจะตีความรูปแบบการแตะนี้เป็นท่าทางสัมผัส มี การตรวจจับด้วยท่าทางสัมผัสมี 2 ระยะ ดังนี้
- กำลังรวบรวมข้อมูลกิจกรรมการสัมผัส
- การตีความข้อมูลเพื่อพิจารณาว่าข้อมูลเป็นไปตามเกณฑ์สำหรับแอตทริบิวต์ ที่แอปของคุณรองรับ
คลาส AndroidX
ตัวอย่างในเอกสารฉบับนี้ใช้
GestureDetectorCompat
และ
วันที่ MotionEventCompat
ใหม่ ชั้นเรียนเหล่านี้อยู่ใน AndroidX
คลัง ใช้คลาส AndroidX เมื่อเป็นไปได้เพื่อให้เข้ากันได้กับ
อุปกรณ์รุ่นก่อนหน้า
MotionEventCompat
ไม่ใช่สิ่งที่มาแทนที่
MotionEvent
แต่จะมีวิธียูทิลิตีแบบคงที่ซึ่งคุณต้องส่ง
MotionEvent
ออบเจ็กต์เพื่อรับการดำเนินการที่เชื่อมโยงกับรายการ
กิจกรรม
รวบรวมข้อมูล
เมื่อผู้ใช้วางนิ้วอย่างน้อย 1 นิ้วลงบนหน้าจอ จะทริกเกอร์
Callback
onTouchEvent()
บนมุมมองที่รับกิจกรรมการแตะ สำหรับการสัมผัสแต่ละลำดับ
เหตุการณ์ เช่น ตำแหน่ง ความกดดัน ขนาด และการเพิ่มกิจกรรมอื่น
นิ้ว ซึ่งระบุเป็นท่าทางสัมผัส onTouchEvent()
คือ
เริ่มทำงานหลายครั้ง
ท่าทางสัมผัสจะเริ่มต้นเมื่อผู้ใช้แตะหน้าจอเป็นครั้งแรก และดำเนินต่อไปขณะที่
ระบบจะติดตามตำแหน่งนิ้วของผู้ใช้ และสิ้นสุดโดย
บันทึกเหตุการณ์สุดท้ายของนิ้วสุดท้ายของผู้ใช้ออกจากหน้าจอ
ตลอดการโต้ตอบนี้ MotionEvent
ได้ส่งไปยัง
onTouchEvent()
จะแสดงรายละเอียดของการโต้ตอบทั้งหมด แอปของคุณ
สามารถใช้ข้อมูลที่ได้จาก MotionEvent
เพื่อพิจารณาว่า
ที่อุปกรณ์ให้ความสำคัญ
บันทึกเหตุการณ์การสัมผัสสำหรับกิจกรรมหรือมุมมอง
วิธีสกัดกั้นการสัมผัสใน Activity
หรือ
View
ลบล้างการเรียกกลับของ onTouchEvent()
ข้อมูลโค้ดต่อไปนี้ใช้
getAction()
เพื่อดึงการดำเนินการที่ผู้ใช้ทำจากพารามิเตอร์ event
ซึ่งจะให้ข้อมูลดิบที่จำเป็นเพื่อระบุท่าทางสัมผัสที่คุณสนใจหรือไม่
ถึงจุดนี้
Kotlin
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) } } }
Java
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
ทำให้คุณตรวจหา
โดยไม่ประมวลผลกิจกรรมการสัมผัสแต่ละเหตุการณ์ด้วยตัวเอง นี่คือ
ตามที่ได้อธิบายเพิ่มเติมไว้ในตรวจหาท่าทางสัมผัส
บันทึกเหตุการณ์การสัมผัสสำหรับมุมมองเดียว
สำหรับ onTouchEvent()
คุณสามารถแนบ
วันที่ View.OnTouchListener
ออบเจ็กต์ View
ใดก็ได้
โดยใช้แอตทริบิวต์
setOnTouchListener()
วิธีนี้จะช่วยให้สามารถฟังเหตุการณ์การแตะได้โดยไม่ต้องจัดหมวดหมู่ย่อย
View
ที่มีอยู่ ดังที่แสดงในตัวอย่างต่อไปนี้
Kotlin
findViewById<View>(R.id.my_view).setOnTouchListener { v, event -> // Respond to touch events. true }
Java
View myView = findViewById(R.id.my_view); myView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // Respond to touch events. return true; } });
โปรดระมัดระวังการสร้าง Listener ที่แสดงผล false
สำหรับ
ACTION_DOWN
เหตุการณ์
หากคุณทำเช่นนี้ ผู้ฟังจะไม่ถูกเรียกใช้สำหรับการถัดไป
ACTION_MOVE
และ
ACTION_UP
ลำดับของ
กิจกรรม เพราะ ACTION_DOWN
คือจุดเริ่มต้นของทุกคน
กิจกรรมการสัมผัส
หากคุณกำลังสร้างมุมมองที่กำหนดเอง คุณสามารถลบล้าง
onTouchEvent()
ตามที่อธิบายไว้ก่อนหน้านี้
ตรวจหาท่าทางสัมผัส
Android มีคลาส GestureDetector
สำหรับการตรวจหา
ท่าทางสัมผัสบางส่วนที่แอปรองรับมีดังนี้
onDown()
,
onLongPress()
,
และ
onFling()
คุณสามารถใช้ GestureDetector
ร่วมกับ
onTouchEvent()
ที่อธิบายไว้ก่อนหน้านี้
ตรวจจับท่าทางสัมผัสที่รองรับทั้งหมด
เมื่อคุณสร้างอินสแตนซ์ GestureDetectorCompat
ออบเจ็กต์ใดมุมมองหนึ่ง
คือคลาสที่ใช้งาน
วันที่ GestureDetector.OnGestureListener
ของ Google GestureDetector.OnGestureListener
จะแจ้งผู้ใช้เมื่อ
เหตุการณ์การแตะบางอย่างเกิดขึ้น เพื่อให้
GestureDetector
เพื่อรับเหตุการณ์ ลบล้างมุมมองหรือ
เมธอด onTouchEvent()
ของกิจกรรม และส่งต่อเหตุการณ์ที่สังเกตได้ทั้งหมด
ลงในอินสแตนซ์ตัวตรวจจับ
ในข้อมูลโค้ดต่อไปนี้ ค่าที่ส่งกลับ true
จากค่า
เมธอด on<TouchEvent>
แต่ละรายการจะระบุว่า
การจัดการกิจกรรมการสัมผัส ผลลัพธ์ของ false
ผ่านเหตุการณ์ที่ไม่ผ่าน
ผ่านกองซ้อนมุมมองจนกว่าจะจัดการการแตะได้สำเร็จ
หากเรียกใช้ข้อมูลโค้ดต่อไปนี้ในแอปทดสอบ คุณจะดูได้ว่า
จะทำงานเมื่อคุณโต้ตอบกับหน้าจอสัมผัสและสิ่งที่
เนื้อหาของ MotionEvent
มีไว้สำหรับเหตุการณ์การสัมผัสแต่ละเหตุการณ์ จากนั้นคุณจะเห็น
จำนวนข้อมูลสำหรับการโต้ตอบง่ายๆ ที่สร้างขึ้น
Kotlin
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 } }
Java
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.SimpleOnGestureListener
แทนที่จะใช้เมธอด GestureDetector.OnGestureListener
ของ Google
GestureDetector.SimpleOnGestureListener
มอบองค์ประกอบ
สำหรับ
on<TouchEvent>
วิธีด้วยการส่งคืน
false
สำหรับทุกคน ซึ่งจะช่วยให้คุณลบล้างเฉพาะเมธอดที่คุณ
สนใจ ตัวอย่างเช่น ข้อมูลโค้ดต่อไปนี้สร้างคลาสที่ขยาย
GestureDetector.SimpleOnGestureListener
และการลบล้าง
onFling()
และ onDown()
ไม่ว่าคุณจะใช้ GestureDetector.OnGestureListener
หรือ
GestureDetector.SimpleOnGestureListener
แนวทางปฏิบัติแนะนำคือ
ใช้เมธอด onDown()
ที่ส่งคืน true
ช่วงเวลานี้
เป็นเพราะท่าทางสัมผัสทั้งหมดเริ่มต้นด้วยข้อความ onDown()
หากคุณ
ส่งคืน false
จาก onDown()
ตาม
GestureDetector.SimpleOnGestureListener
จะดำเนินการตามค่าเริ่มต้น โดยระบบ
จะถือว่าคุณต้องการเพิกเฉยต่อท่าทางสัมผัสส่วนที่เหลือ และวิธีอื่นๆ ในการ
ไม่ได้เรียก GestureDetector.OnGestureListener
การดำเนินการนี้อาจทําให้
ปัญหาที่ไม่คาดคิดในแอปของคุณ คืนเฉพาะ false
จาก
onDown()
หากต้องการละเว้นท่าทางสัมผัสทั้งหมดจริงๆ
Kotlin
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 } } }
Java
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; } } }