Hầu hết các thiết bị Android có màn hình dùng cảm ứng đa điểm (cuộc cách mạng từ iPhone). Với các màn hình cảm ứng đa điểm, người dùng sẽ tương tác với thiết bị Android thông qua thao tác chạm (touch). Thao tác chạm cũng được gọi là cử chỉ người dùng (gesture). Việc phát hiện ra sự kiện chạm hay cử chỉ người dùng là rất quan trọng với các thiết bị Android và hầu hết các thiết bị Android có thể phát hiện nhiều lần chạm tại cùng một thời điểm hay đa chạm (multi-touch).
Sự kiện và xử lý sự kiện Touch
Giống như các sự kiện khác, sự kiện Touch của một view có thể được phát hiện và xử lý thông qua việc đăng ký với trình lắng nghe sự kiện onTouchListener và thực thi phương thức onTouch() tương ứng. Ví dụ xử lý sự kiện Touch cho view – là một ConstraintLayout có thể hiện là myLayout:
myLayout.setOnTouchListener( new ConstraintLayout.OnTouchListener() { public boolean onTouch(View v, MotionEvent m) { // Perform tasks here return true; } } );
onTouch() trả về giá trị logic xác nhận đến hệ thống thực thi Android liệu sự kiện có được chuyển đến các trình lắng nghe sự kiện khác đã được đăng ký hay bỏ qua.
Đối tượng MotionEvent
Để nhận thông tin từ sự kiện Touch, đối tượng MotionEvent phải được chuyển đến phương thức onTouch(). Thông tin có thể là vị trí xảy ra sự kiện Touch thông qua các phương thức getX(), getY() của đối tượng MotionEvent hay kiểu hoạt động (type of action) xảy ra. Đối tượng MotionEvent cũng được dùng trong xử lý sự kiện đa chạm (multi-Touch).
Các kiểu hoạt động của sự kiện Touch
Thông tin về kiểu hoạt động kết hợp với một sự kiện Touch có thể xác định nhờ phương thức getActionMasked() của đối tượng MotionEvent. Một số kiểu hoạt động:
- ACTION_DOWN: xảy ra khi hoạt động chạm của người dùng xảy ra trên một view nào đó cùng với tọa độ của điểm được chạm.
- ACTION_UP: xảy ra khi người dùng rời khỏi màn hìn
- ACTION_MOVE: các hoạt động trung gian giữa ACTION_DOWN và ACTION_UP
Trong trường hợp các sự kiện multi-Touch xảy ra, các hành động gồm các kiểu ACTION_POINTER_DOWN và ACTION_POINTER_UP tương ứng.
Xử lý đa chạm (mutlti-Touch)
Khi xảy ra nhiều lần chạm vào màn hình tại cùng một thời điểm, mỗi một lần chạm được xem như là một con trỏ (pointer). Mỗi con trỏ sẽ được tham chiếu đến một index và được gán một ID. Số con trỏ hay số lần chạm có thể được xác định nhờ phương thức getPointerCount() của đối tượng MotionEvent. ID của một con trỏ tại một index cụ thể trong danh sách các con trỏ hiện tại có thể biết được thông qua phương thức getPointerId() của đối tượng MotionEvent. Ví dụ đoạn mã sau:
public boolean onTouch(View v, MotionEvent m) { int pointerCount = m.getPointerCount(); // lấy ID của pointer tại index = 0 int pointerId = m.getPointerId(0); return true; }
pointerCount >=1 khi sự kiện Touch xảy ra.
Có thể tìm index của một pointer thông qua ID của nó nhờ phương thức findPointerIndex() của đối tượng MotionEvent.
Ví dụ về ứng dụng đa chạm
Tạo một dự án mới với tên ứng dụng là MotionEvent với tên Activity (Activity Name) là MotionEventActvity và tên layout (Layout Name) là activity_motion_event:
Xóa TextView mặc định, thêm hai TextView mới đến giao diện và định vị chúng đến giữa màn hình:
Các thuộc tính của layout và hai TextView như sau:
View | ID | Text |
TextView | textView1 | @string/txt1 |
TextView | textView2 | @string/txt2 |
ConstraintLayout | main |
Tập tin strings.xml:
<resources> <string name="app_name">MotionEvent</string> <string name="txt1">Touch One Status</string> <string name="txt2">Touch Two Status</string> </resources>
Trong lớp MotionEventActivity (tập tin MotionEventActivity.java) tạo phương thức handleTouch() như sau:
void handleTouch(MotionEvent m) { TextView textView1 = (TextView)findViewById(R.id.textView1); TextView textView2 = (TextView)findViewById(R.id.textView2); int pointerCount = m.getPointerCount(); for (int i = 0; i < pointerCount; i++) { int x = (int) m.getX(i); int y = (int) m.getY(i); int id = m.getPointerId(i); int action = m.getActionMasked(); int actionIndex = m.getActionIndex(); String actionString; switch (action) { case MotionEvent.ACTION_DOWN: actionString = "DOWN"; break; case MotionEvent.ACTION_UP: actionString = "UP"; break; case MotionEvent.ACTION_POINTER_DOWN: actionString = "PNTR DOWN"; break; case MotionEvent.ACTION_POINTER_UP: actionString = "PNTR UP"; break; case MotionEvent.ACTION_MOVE: actionString = "MOVE"; break; default: actionString = ""; } String touchStatus = "Action: " + actionString + " Index: " + actionIndex + " ID: " + id + " X: " + x + " Y: " + y; if (id == 0) textView1.setText(touchStatus); else textView2.setText(touchStatus); } }
trong phương thức onCreate đăng ký sự kiện Touch đến trình lắng nghe onTouchListener và thực thi phương thức onTouch()
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_motion_event); ConstraintLayout myLayout = (ConstraintLayout)findViewById(R.id.main); myLayout.setOnTouchListener( new ConstraintLayout.OnTouchListener() { public boolean onTouch(View v, MotionEvent m) { handleTouch(m); return true; } } ); }
Chúng ta cần import thêm một số lớp:
import android.view.MotionEvent; import android.view.View; import android.widget.TextView;
Thực thi chương trình:
Click chuột trái vào màn hình (tượng trưng cho một lần chạm ngón tay của người dùng) và giữ chuột trái:
Thả chuột trái:
Có thể vừa nhấp chuột trái vừa giữ phím Ctrl (tượng trưng việc người dùng chạm hai lần cùng lúc đến màn hình):
Giữ phím Ctrl nhưng thả chuột:
Chúng ta cũng có thể trải nghiệm trực tiếp trên thiết bị Android bằng cách cài tập tin apk trên thiết bị này. Tập tin apk của ứng dụng MotionEvent có thể tải tại đây hay có thể tạo trong Anddroid Studio 3.X (3.0 trở lên) như sau:
- Biên dịch ứng dụng MotionEvent thành tập tin apk bằng cách chọn Build > Build APK(s)
Khi tạo tập tin apk thành công sẽ xuất hiện thông báo bên gốc phải dưới của Android Studio (từ cửa sổ Event log)
- Chọn liên kết locate để đến thư mục debug chứa tập tin apk
Trong thư mục debug sao chép tập tin app-debug.apk đến thiết bị Android và cài đặt. Lúc này chúng ta có thể trải nghiệm trực tiếp ứng dụng MotionEvent trên thiết bị Android.
Toàn bộ mã nguồn của MotionEvent tại GitHub.
Ý kiến bài viết