ตรวจหาท่าทางสัมผัสทั่วไป

ลองใช้วิธีการเขียน
Jetpack Compose เป็นชุดเครื่องมือ UI ที่แนะนำสำหรับ Android ดูวิธีใช้การแตะและการป้อนข้อมูลในการเขียน

ท่าทางสัมผัสการแตะเกิดขึ้นเมื่อผู้ใช้วางนิ้วอย่างน้อย 1 นิ้วบน และแอปจะตีความรูปแบบการแตะนี้เป็นท่าทางสัมผัส มี การตรวจจับด้วยท่าทางสัมผัสมี 2 ระยะ ดังนี้

  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;
        }
    }
}

แหล่งข้อมูลเพิ่มเติม