Cử chỉ nhiều điểm chạm là khi nhiều con trỏ (ngón tay) nhấn vào màn hình tại . Tài liệu này mô tả cách phát hiện các cử chỉ liên quan đến nhiều con trỏ.
Theo dõi nhiều con trỏ
Khi nhiều con trỏ nhấn vào màn hình cùng một lúc, hệ thống sẽ tạo các sự kiện chạm sau đây:
ACTION_DOWN
: được gửi khi con trỏ đầu tiên nhấn vào màn hình. Thao tác này sẽ khởi động cử chỉ. Chiến lược phát hành đĩa đơn dữ liệu con trỏ cho con trỏ này luôn nằm ở chỉ mục0
trongMotionEvent
ACTION_POINTER_DOWN
: được gửi khi con trỏ bổ sung vào màn hình sau lần đầu tiên. Bạn có thể nhận được chỉ mục của con trỏ vừa giảm xuống bằng cách sử dụnggetActionIndex()
.ACTION_MOVE
: được gửi khi thay đổi xảy ra trong một cử chỉ, liên quan đến bất kỳ số lượng giá trị nào con trỏ.ACTION_POINTER_UP
: được gửi khi con trỏ phụ dịch lên. Bạn có thể lấy chỉ mục của con trỏ vừa tăng lên bằng cách sử dụnggetActionIndex()
.ACTION_UP
: được gửi khi con trỏ cuối cùng rời khỏi màn hình.ACTION_CANCEL
: cho biết toàn bộ cử chỉ, bao gồm tất cả con trỏ, đã bị huỷ.
Cử chỉ bắt đầu và kết thúc
Cử chỉ là một chuỗi sự kiện bắt đầu bằng một ACTION_DOWN
sự kiện và kết thúc bằng ACTION_UP
hoặc
Sự kiện ACTION_CANCEL
. Mỗi lần chỉ có một cử chỉ đang hoạt động. Chiến lược phát hành đĩa đơn
các thao tác XUỐNG, DI CHUYỂN, LÊN và HUỶ áp dụng cho toàn bộ cử chỉ. Ví dụ: một
sự kiện có ACTION_MOVE
có thể cho biết chuyển động của tất cả các con trỏ
tại thời điểm đó.
Theo dõi con trỏ
Sử dụng chỉ mục và ID của con trỏ để theo dõi từng con trỏ
vị trí trong MotionEvent
.
- Chỉ mục:
MotionEvent
lưu trữ con trỏ thông tin trong một mảng. Chỉ mục của con trỏ là vị trí của nó trong . Hầu hết phương thứcMotionEvent
đều lấy chỉ mục con trỏ làm tham số thay vì mã con trỏ. - Mã nhận dạng: mỗi con trỏ cũng có một mục ánh xạ mã nhận dạng cố định qua các sự kiện chạm để cho phép theo dõi một con trỏ riêng lẻ trên toàn bộ cử chỉ.
Con trỏ riêng lẻ xuất hiện trong một sự kiện chuyển động theo thứ tự không xác định. Do đó,
chỉ mục của con trỏ có thể thay đổi từ sự kiện này sang sự kiện tiếp theo, nhưng mã con trỏ
của một con trỏ được đảm bảo không đổi miễn là con trỏ đó
đang hoạt động. Sử dụng
getPointerId()
để lấy mã nhận dạng của con trỏ nhằm theo dõi con trỏ trên tất cả
sự kiện chuyển động trong một cử chỉ. Sau đó, đối với các sự kiện chuyển động liên tiếp, hãy sử dụng toán tử
findPointerIndex()
để lấy chỉ mục con trỏ cho một mã con trỏ nhất định trong sự kiện chuyển động đó.
Ví dụ:
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); ... }
Để hỗ trợ nhiều con trỏ chạm, bạn có thể lưu tất cả con trỏ đang hoạt động vào bộ nhớ đệm
ID của họ tại ACTION_POINTER_DOWN
cá nhân và
Thời gian diễn ra sự kiện ACTION_DOWN
. Xoá con trỏ khỏi bộ nhớ đệm tại
sự kiện ACTION_POINTER_UP
và ACTION_UP
của họ. Bạn có thể
Bạn sẽ thấy những mã nhận dạng được lưu vào bộ nhớ đệm này hữu ích để xử lý chính xác các sự kiện hành động khác. Cho
Ví dụ: khi xử lý một sự kiện ACTION_MOVE
, hãy tìm chỉ mục cho
mỗi mã nhận dạng con trỏ đang hoạt động được lưu vào bộ nhớ đệm, hãy truy xuất toạ độ của con trỏ bằng cách sử dụng
getX()
và
getY()
rồi so sánh những toạ độ này với toạ độ đã lưu vào bộ nhớ đệm
khám phá xem con trỏ nào đã di chuyển.
Dùng hàm getActionIndex()
với
Sự kiện ACTION_POINTER_UP
và ACTION_POINTER_DOWN
. Đừng sử dụng hàm này với các sự kiện ACTION_MOVE
, vì
luôn trả về 0
.
Truy xuất thao tác MotionEvent
Sử dụng
getActionMasked()
hoặc phiên bản tương thích
MotionEventCompat.getActionMasked()
để truy xuất hành động của MotionEvent
. Không giống như trước
getAction()
getActionMasked()
được thiết kế để hoạt động với nhiều
con trỏ. Phương thức này trả về hành động không có chỉ mục con trỏ. Đối với các thao tác có
chỉ mục con trỏ hợp lệ, hãy sử dụng getActionIndex()
để trả về chỉ mục của
con trỏ liên kết với hành động như minh hoạ trong đoạn mã sau:
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 ""; }
Tài nguyên khác
Để biết thêm thông tin liên quan đến các sự kiện đầu vào, hãy xem các bài viết sau tài liệu tham khảo:
- Tổng quan về sự kiện đầu vào
- Cảm biến tổng quan
- Tạo ảnh động tuỳ chỉnh chế độ xem tương tác
- Kéo và chuyển tỷ lệ