Cử chỉ (gesture) là các hoạt động tương tác giữa người dùng và màn hình thiết bị Android bao gồm các hoạt động chạm ngắn (tap), lướt các trang sách điện tử (swipe), phóng to hay thu nhỏ các hình ảnh (pinch), v.v.

Phát hiện cử chỉ người dùng

Như trong bài trước, khi người dùng tương tác với màn hình thiết bị Android, phương thức onTouchEvent() được gọi bởi hệ thống và chuyển đối tượng MotionEvent chứa dữ liệu về tương tác của người dùng với màn hình. Dữ liệu này có thể được dùng để xác định kiểu cử chỉ người dùng bằng cách dùng lớp Android GestureDetectorCompat.

Các bước cơ bản phát hiện cử chỉ người dùng:

  • B1: Khai báo lớp thực thi giao diện OnGestureListener gồm các phương thức callback như onFling(), onDown(), onScroll(), onShowPress(), onSingleTapUp()onLongPress().
  • B2: Tạo một thể hiện của lớp Android GestureDetectorCompat, chuyển một thể hiện của lớp tạo ở bước 1 (B1) như một đối số.
  • B3: Nếu cần xử lý sự kiện sau hai lần chạm liên tiếp (double tap) thì có thể gọi phương thức setOnDoubleTapListener() của lớp Android GestureDetectorCompat
  • B4: gọi phương thức onTouchEvent() của thể hiện lớp Android GestureDetectorCompat

Ứng dụng minh họa phát hiện cử chỉ người dùng dùng lớp Android GestureDetectorCompat

Tạo ứng dụng

Tạo một ứng dụng Android tên CommonGestures, chọn Phone and Tablet và API 14 trong Target Android Devices. Trong Add an Activity to Mobile chọn Empty Activity và nhập CommonGesturesActivity trong Activity Name (tương ứng trong Layout Name là activity_common_gestures) trong Configure Activity.

Tại tập tin activity_common_gestures.xml chọn chế độ Design, chọn TextView mặc định “Hello, World!” và nhập giá trị gestureStatusText tại thuộc tính ID trong cửa sổ Attributes.

Thực thi lớp lắng nghe sự kiện (listener class)

Tạo lớp thực thi giao diện GestureDetector.OnGestureListener và GestureDetector.OnDoubleTapListener (cho sự kiện double tap). Lớp thực thi này có thể là một lớp mới nhưng trong dự án mang tính chất minh họa như CommonGestures chúng ta có thể dùng lớp CommonGesturesActivity để thực thi hai giao diện trên:


public class CommonGesturesActivity extends AppCompatActivity
implements GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener
{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_common_gestures);
   }
}

Chúng ta cần import:


import android.view.GestureDetector;

Lúc này có thể xảy ra lỗi vì chúng ta chưa thực thi các phương thức của các giao diện. Định nghĩa các phương thức sau (bên cạnh phương thức onCreate) trong lớp CommonGesturesActivity:


public class CommonGesturesActivity extends AppCompatActivity
implements GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener
{

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_common_gestures);
  }

  @Override
  public boolean onDown(MotionEvent event) {
    return true;
  }

  @Override
  public boolean onFling(MotionEvent event1, MotionEvent event2,
     float velocityX, float velocityY) {
        return true;
  }

  @Override
  public void onLongPress(MotionEvent event) {

  }

  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2,
       float distanceX, float distanceY) {
       return true;
  }

  @Override
  public void onShowPress(MotionEvent event) {
  }

  @Override
  public boolean onSingleTapUp(MotionEvent event) {
     return true;
  }

  @Override
  public boolean onDoubleTap(MotionEvent event) {
     return true;
  }

  @Override
  public boolean onDoubleTapEvent(MotionEvent event) {
     return true;
  }

  @Override
  public boolean onSingleTapConfirmed(MotionEvent event) {
     return true;
  }
}

Lưu ý chúng ta cần import:


import android.view.MotionEvent;

Tham chiếu đến TextView của giao diện


private TextView gestureText;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_common_gestures);

    gestureText = (TextView)findViewById(R.id.gestureStatusText);
}

Thêm các đoạn mã hiển thị thông tin về cử chỉ người dùng đến TextView trong các phương thức:


@Override
public boolean onDown(MotionEvent event) {
   gestureText.setText ("onDown");
   return true;
}

@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
   gestureText.setText("onFling");
   return true;
}

@Override
public void onLongPress(MotionEvent event) {
   gestureText.setText("onLongPress");
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
   gestureText.setText("onScroll");
   return true;
}

@Override
public void onShowPress(MotionEvent event) {
   gestureText.setText("onShowPress");
}

@Override
public boolean onSingleTapUp(MotionEvent event) {
   gestureText.setText("onSingleTapUp");
   return true;
}

@Override
public boolean onDoubleTap(MotionEvent event) {
   gestureText.setText("onDoubleTap");
   return true;
}

@Override
public boolean onDoubleTapEvent(MotionEvent event) {
   gestureText.setText("onDoubleTapEvent");
   return true;
}

@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
   gestureText.setText("onSingleTapConfirmed");
   return true;
}

Các phương thức trả về giá trị true để xác nhận các sự kiện có thể được xử lý bởi các phương thức mà không cần chuyển đến hàng đợi xử lý sự kiện.

 Tạo thể hiện của lớp GestureDetectorCompat

Chúng ta có thể tạo thể hiện của lớp GestureDetectorCompat trong phương thức onCreate của lớp CommonGesturesActivity:


public class CommonGesturesActivity extends AppCompatActivity
implements GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener
{
  private TextView gestureText;
  private GestureDetectorCompat gDetector;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_common_gestures);

     gestureText = (TextView)findViewById(R.id.gestureStatusText);

     this.gDetector = new GestureDetectorCompat(this,this);
     gDetector.setOnDoubleTapListener(this);
  }

...

}

Thực thi phương thức onTouchEvent()

Bước cuối cùng là thực thi phương thức onTouchEvent() trong lớp CommonGesturesActivity như sau:


@Override
public boolean onTouchEvent(MotionEvent event) {
   this.gDetector.onTouchEvent(event);
   // Be sure to call the superclass implementation
   return super.onTouchEvent(event);
}

Thực thi ứng dụng

Bây giờ chúng ta có thể trải nghiệm ứng dụng CommonGestures trực tiếp trên thiết bị Android (tạo ra tập tin apk và cài đặt. Xem lại tại đây) hay chạy trên máy ảo thông qua con trỏ chuột.

Mã nguồn ứng dụng CommonGestures có thể xem tại GitHub.