จัดการการแตะสัมผัสหลายแบบ

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

ท่าทางสัมผัสแบบมัลติทัชคือการที่เคอร์เซอร์หลายตัว (นิ้ว) แตะหน้าจอ ในเวลาเดียวกัน เอกสารนี้อธิบายวิธีตรวจหาท่าทางสัมผัสที่เกี่ยวข้อง เคอร์เซอร์หลายตัว

ติดตามเคอร์เซอร์หลายตัว

เมื่อมีเคอร์เซอร์หลายตัวแตะหน้าจอพร้อมกัน ระบบจะสร้าง กิจกรรมการแตะต่อไปนี้

  • ACTION_DOWN: ส่งเมื่อตัวชี้ตัวแรกแตะหน้าจอ การดำเนินการนี้จะเริ่มต้นท่าทางสัมผัส ข้อมูลตัวชี้ของตัวชี้นี้จะอยู่ที่ดัชนี 0 เสมอใน MotionEvent
  • ACTION_POINTER_DOWN: ส่งเมื่อมีตัวชี้พิเศษเข้ามาบนหน้าจอหลังจากจุดแรก คุณสามารถดู ดัชนีของตัวชี้ที่เพิ่งลดลงโดยใช้ getActionIndex()
  • ACTION_MOVE: ส่งเมื่อมีการเปลี่ยนแปลงในท่าทางสัมผัสที่เกี่ยวข้องกับจำนวน ตัวชี้
  • ACTION_POINTER_UP: ส่งเมื่อตัวชี้ที่ไม่ใช่เคอร์เซอร์หลักเพิ่มขึ้น คุณสามารถดูดัชนีของ ตัวชี้ที่เพิ่งเพิ่มขึ้นโดยใช้ getActionIndex()
  • ACTION_UP: ส่งเมื่อตัวชี้ตัวสุดท้ายออกจากหน้าจอ
  • ACTION_CANCEL: บ่งชี้ว่าท่าทางสัมผัสทั้งหมดรวมถึงเคอร์เซอร์ทั้งหมดถูกยกเลิก

ท่าทางสัมผัสเริ่มต้นและสิ้นสุด

ท่าทางสัมผัสคือชุดเหตุการณ์ที่ขึ้นต้นด้วย ACTION_DOWN และลงท้ายด้วย ACTION_UP หรือ ACTION_CANCEL เหตุการณ์ มีท่าทางสัมผัสที่ใช้งานอยู่ 1 ท่าทางสัมผัสในแต่ละครั้ง การทำงาน "ลง" "เลื่อน" "ขึ้น" และ "ยกเลิก" จะมีผลกับท่าทางสัมผัสทั้งหมด ตัวอย่างเช่น เหตุการณ์ที่มี ACTION_MOVE จะบ่งบอกถึงการเคลื่อนไหวสำหรับตัวชี้ทั้งหมด ลดลงได้ในตอนนี้

ติดตามเคอร์เซอร์

ใช้ดัชนีและรหัสของเคอร์เซอร์เพื่อติดตามแต่ละเคอร์เซอร์ ตำแหน่งภายใน MotionEvent

  • ดัชนี: MotionEvent เคอร์เซอร์จัดเก็บ ในอาร์เรย์ ดัชนีของตัวชี้คือตำแหน่งของตัวชี้ภายในเครื่องหมายนี้ อาร์เรย์ เมธอด MotionEvent ส่วนใหญ่จะใช้ดัชนีตัวชี้เป็น พารามิเตอร์ แทนที่จะเป็นรหัสเคอร์เซอร์
  • รหัส: ตัวชี้แต่ละรายการยังมีการแมปรหัสที่จะยังคงอยู่ คงอยู่ตลอดเหตุการณ์การแตะเพื่อให้ติดตามตัวชี้แต่ละรายการได้ กับท่าทางสัมผัสทั้งหมด

ตัวชี้แต่ละจุดจะปรากฏภายในเหตุการณ์การเคลื่อนไหวตามลำดับที่ไม่ได้กำหนด ดังนั้น ดัชนีของตัวชี้สามารถเปลี่ยนจากเหตุการณ์หนึ่งเป็นเหตุการณ์ถัดไป แต่รหัสตัวชี้ ของตัวชี้นั้นอยู่คงที่ตราบเท่าที่ตัวชี้นั้นยังคงอยู่ ใช้งานอยู่ ใช้เมนู getPointerId() ในการรับ ID ของตัวชี้เพื่อติดตามตัวชี้ทั่วทั้ง เหตุการณ์การเคลื่อนไหวในท่าทางสัมผัส จากนั้น สำหรับเหตุการณ์การเคลื่อนไหวต่อเนื่อง ให้ใช้ findPointerIndex() เพื่อรับดัชนีตัวชี้สำหรับรหัสตัวชี้ในเหตุการณ์การเคลื่อนไหวนั้น เช่น

Kotlin

private var mActivePointerId: Int = 0

override fun onTouchEvent(event: MotionEvent): Boolean {
    ...
    // Get the pointer ID.
    mActivePointerId = event.getPointerId(0)

    // ... Many touch events later...

    // Use the pointer ID to find the index of the active pointer
    // and fetch its position.
    val (x: Float, y: Float) = event.findPointerIndex(mActivePointerId).let { pointerIndex ->
        // Get the pointer's current position.
        event.getX(pointerIndex) to event.getY(pointerIndex)
    }
    ...
}

Java

private int mActivePointerId;

public boolean onTouchEvent(MotionEvent event) {
    ...
    // Get the pointer ID.
    mActivePointerId = event.getPointerId(0);

    // ... Many touch events later...

    // Use the pointer ID to find the index of the active pointer
    // and fetch its position.
    int pointerIndex = event.findPointerIndex(mActivePointerId);
    // Get the pointer's current position.
    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);
    ...
}

หากต้องการรองรับเคอร์เซอร์แบบสัมผัสหลายจุด คุณสามารถแคชเคอร์เซอร์ที่ใช้งานอยู่ทั้งหมดกับ บัตรได้ที่ ACTION_POINTER_DOWN ส่วนบุคคลและ ACTION_DOWN เวลาของกิจกรรม ลบตัวชี้ออกจากแคชของคุณที่ ACTION_POINTER_UPและACTION_UPเหตุการณ์ คุณอาจ รหัสที่แคชไว้เหล่านี้มีประโยชน์ในการจัดการเหตุการณ์การดำเนินการอื่นๆ ได้อย่างถูกต้อง สำหรับ ตัวอย่างเช่น เมื่อประมวลผลเหตุการณ์ ACTION_MOVE ให้ค้นหาดัชนีสำหรับ ID ตัวชี้ที่ใช้งานอยู่ที่แคชไว้แต่ละรายการ ให้ดึงข้อมูลพิกัดของตัวชี้โดยใช้ วันที่ getX() และ getY() แล้วเปรียบเทียบพิกัดเหล่านี้กับพิกัดที่แคชไว้เพื่อ จะค้นพบว่าตัวชี้ใดบ้างที่ย้ายไปแล้ว

ใช้ฟังก์ชัน getActionIndex() กับ ACTION_POINTER_UP และ ACTION_POINTER_DOWN เหตุการณ์ เท่านั้น อย่าใช้ฟังก์ชันนี้กับเหตุการณ์ ACTION_MOVE เพราะเป็น แสดงผล 0 เสมอ

ดึงข้อมูลการดำเนินการ MotionEvent รายการ

ใช้เมนู getActionMasked() หรือเวอร์ชันความเข้ากันได้ วันที่ MotionEventCompat.getActionMasked() เพื่อดึงการทำงานของ MotionEvent ไม่เหมือนกับก่อนหน้านี้ getAction() getActionMasked()ได้รับการออกแบบมาให้ทำงานร่วมกับ ตัวชี้ โดยจะแสดงผลการทำงานโดยไม่มีดัชนีตัวชี้ สำหรับการดำเนินการที่มี ดัชนีตัวชี้ที่ถูกต้อง ใช้ getActionIndex() เพื่อแสดงผลดัชนีของ เคอร์เซอร์ที่เชื่อมโยงกับการดำเนินการดังที่แสดงในข้อมูลโค้ดต่อไปนี้

Kotlin

val (xPos: Int, yPos: Int) = MotionEventCompat.getActionMasked(event).let { action ->
    Log.d(DEBUG_TAG, "The action is ${actionToString(action)}")
    // Get the index of the pointer associated with the action.
    MotionEventCompat.getActionIndex(event).let { index ->
        // The coordinates of the current screen contact, relative to
        // the responding View or Activity.
        MotionEventCompat.getX(event, index).toInt() to MotionEventCompat.getY(event, index).toInt()
    }
}

if (event.pointerCount > 1) {
    Log.d(DEBUG_TAG, "Multitouch event")

} else {
    // Single touch event.
    Log.d(DEBUG_TAG, "Single touch event")
}

...

// Given an action int, returns a string description.
fun actionToString(action: Int): String {
    return when (action) {
        MotionEvent.ACTION_DOWN -> "Down"
        MotionEvent.ACTION_MOVE -> "Move"
        MotionEvent.ACTION_POINTER_DOWN -> "Pointer Down"
        MotionEvent.ACTION_UP -> "Up"
        MotionEvent.ACTION_POINTER_UP -> "Pointer Up"
        MotionEvent.ACTION_OUTSIDE -> "Outside"
        MotionEvent.ACTION_CANCEL -> "Cancel"
        else -> ""
    }
}

Java

int action = MotionEventCompat.getActionMasked(event);
// Get the index of the pointer associated with the action.
int index = MotionEventCompat.getActionIndex(event);
int xPos = -1;
int yPos = -1;

Log.d(DEBUG_TAG,"The action is " + actionToString(action));

if (event.getPointerCount() > 1) {
    Log.d(DEBUG_TAG,"Multitouch event");
    // The coordinates of the current screen contact, relative to
    // the responding View or Activity.
    xPos = (int)MotionEventCompat.getX(event, index);
    yPos = (int)MotionEventCompat.getY(event, index);

} else {
    // Single touch event.
    Log.d(DEBUG_TAG,"Single touch event");
    xPos = (int)MotionEventCompat.getX(event, index);
    yPos = (int)MotionEventCompat.getY(event, index);
}
...

// Given an action int, returns a string description
public static String actionToString(int action) {
    switch (action) {

        case MotionEvent.ACTION_DOWN: return "Down";
	case MotionEvent.ACTION_MOVE: return "Move";
	case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down";
	case MotionEvent.ACTION_UP: return "Up";
	case MotionEvent.ACTION_POINTER_UP: return "Pointer Up";
	case MotionEvent.ACTION_OUTSIDE: return "Outside";
	case MotionEvent.ACTION_CANCEL: return "Cancel";
    }
    return "";
}
รูปที่ 1 การวาดภาพแบบมัลติทัช รูปแบบ

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับเหตุการณ์การป้อนข้อมูลได้ดังต่อไปนี้ การอ้างอิง: