lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Sự kiện Nhập liệu

Trên Android, có nhiều cách để can thiệp vào các sự kiện từ tương tác của một người dùng với ứng dụng của bạn. Khi xem xét các sự kiện trong giao diện người dùng của bạn, cách tiếp cận là chụp lại sự kiện từ đối tượng Dạng xem cụ thể mà người dùng tương tác với. Lớp Dạng xem sẽ cung cấp phương thức để làm việc này.

Trong các lớp Dạng xem khác nhau mà bạn sẽ sử dụng để soạn bố trí của mình, bạn có thể thấy một vài phương pháp gọi lại công khai dường như hữu ích đối với sự kiện UI. Những phương pháp này được khuôn khổ Android gọi khi xảy ra hành động tương ứng trên đối tượng đó. Ví dụ, khi một Dạng xem (chẳng hạn như một Nút) được chạm vào, phương pháp onTouchEvent() được gọi trên đối tượng đó. Tuy nhiên, để can thiệp vào điều này, bạn phải mở rộng lớp và khống chế phương pháp đó. Tuy nhiên, việc mở rộng mọi đối tượng Dạng xem để xử lý một sự kiện như vậy sẽ là không thực tế. Đây là lý do tại sao lớp Dạng xem cũng chứa một tập hợp giao diện lồng nhau cùng các phương pháp gọi lại mà bạn có thể định nghĩa dễ dàng hơn nhiều. Những giao diện này, được gọi là đối tượng theo dõi sự kiện, là tấm vé để bạn chụp lại tương tác giữa người dùng với UI của bạn.

Trong khi các đối tượng theo dõi sự kiện sẽ thường được sử dụng để theo dõi tương tác của người dùng, có thể có lúc bạn muốn mở rộng một lớp Dạng xem để xây dựng một thành phần tùy chỉnh. Có thể là bạn muốn mở rộng lớp Button để khiến cái gì đó trông ấn tượng hơn. Trong trường hợp này, bạn sẽ có thể định nghĩa các hành vi sự kiện mặc định cho lớp của mình bằng cách sử dụng bộ xử lý sự kiện của lớp.

Đối tượng theo dõi Sự kiện

Đối tượng theo dõi sự kiện là một giao diện trong lớp View chứa một phương pháp gọi lại đơn lẻ. Những phương pháp này sẽ được khuôn khổ Android gọi khi Dạng xem mà đối tượng theo dõi đã được đăng ký với bị kích khởi bởi tương tác giữa người dùng với mục trong UI.

Trong giao diện của đối tượng theo dõi sự kiện là những phương pháp gọi lại sau:

onClick()
Từ View.OnClickListener. Phương pháp này được gọi khi người dùng chạm vào mục (khi ở chế độ cảm ứng), hoặc lấy tiêu điểm vào một mục bằng phím điều hướng hoặc bi xoay và nhấn phím "enter" phù hợp hoặc nhấn bi xoay.
onLongClick()
Từ View.OnLongClickListener. Phương pháp này được gọi khi người gọi chạm và giữ mục (khi ở chế độ cảm ứng), hoặc lấy tiêu điểm vào một mục bằng phím điều hướng hoặc bi xoay và nhấn và giữ phím "enter" phù hợp hoặc nhấn và giữ bi xoay (trong một giây).
onFocusChange()
Từ View.OnFocusChangeListener. Phương pháp này được gọi khi người dùng điều hướng lên hoặc ra khỏi một mục bằng cách sử dụng các phím điều hướng hoặc bi xoay.
onKey()
Từ View.OnKeyListener. Phương pháp này được gọi khi người dùng được lấy tiêu điểm vào một mục và nhấn hoặc nhả phím cứng trên thiết bị.
onTouch()
Từ View.OnTouchListener. Phương pháp này được gọi khi người dùng thực hiện một hành động được coi như một sự kiện chạm, bao gồm nhấn, nhả, hoặc bất kỳ động tác chuyển động nào trên màn hình (trong đường biên của mục đó).
onCreateContextMenu()
Từ View.OnCreateContextMenuListener. Phương pháp này được gọi khi một Menu Ngữ cảnh đang được xây dựng (kết quả của một sự kiện "nhấp giữ" kéo dài). Xem phần thảo luận về menu ngữ cảnh trong hướng dẫn dành cho nhà phát triển Menu .

Những phương pháp này là phương pháp duy nhất nằm trong giao diện tương ứng của chúng. Để định nghĩa một trong những phương pháp này và xử lý sự kiện của bạn, hãy triển khai giao diện lồng nhau trong Hoạt động của bạn hoặc định nghĩa nó thành một lớp vô danh. Sau đó, chuyển một thực thể triển khai của bạn tới phương pháp View.set...Listener() tương ứng. (Ví dụ, gọi setOnClickListener() và chuyển cho nó triển khai OnClickListener của bạn.)

Ví dụ bên dưới cho biết cách đăng ký một đối tượng theo dõi khi nhấp cho một Nút.

// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(mCorkyListener);
    ...
}

Bạn cũng có thể thấy tiện hơn khi triển khai OnClickListener như một phần trong Hoạt động của mình. Làm vậy sẽ tránh phải tải lớp bổ sung và phân bổ đối tượng. Ví dụ:

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

Lưu ý rằng phương pháp gọi lại onClick() trong ví dụ trên không có giá trị trả về, nhưng một số phương pháp đối tượng theo dõi sự kiện khác phải trả về một boolean. Lý do này phụ thuộc vào sự kiện. Với số ít sự kiện thực hiện như vậy, sau đây là lý do:

  • onLongClick() - Trả về một boolean cho biết bạn đã xử lý sự kiện và sự kiện không nên được tiếp tục hay không. Cụ thể, trả về true để cho biết rằng bạn đã xử lý sự kiện và nó nên dừng ở đây; trả về false nếu bạn chưa xử lý nó và/hoặc sự kiện sẽ tiếp tục đối với bất kỳ đối tượng theo dõi khi nhấp nào khác.
  • onKey() - Trả về một boolean cho biết bạn đã xử lý sự kiện và sự kiện không nên được tiếp tục hay không. Cụ thể, trả về true sẽ cho biết rằng bạn đã xử lý sự kiện và nó nên dừng ở đây; trả về false nếu bạn chưa xử lý nó và/hoặc sự kiện sẽ tiếp tục đối với bất kỳ đối tượng theo dõi trên phím nào khác.
  • onTouch() - Trả về một boolean cho biết đối tượng theo dõi của bạn có xử lý sự kiện này hay không. Điều quan trọng đó là sự kiện này có thể có nhiều hành động nối tiếp nhau. Vì vậy, nếu bạn trả về false khi nhận được sự kiện hành động hướng xuống, bạn sẽ cho biết rằng mình chưa xử lý sự kiện và cũng không quan tâm tới các hành động sau đó từ sự kiện này. Vì thế, bạn sẽ không bị gọi vì bất kỳ hành động nào khác trong sự kiện, chẳng hạn như một cử chỉ ngón tay, hay sự kiện hành động cho sự kiện hướng lên.

Ghi nhớ rằng các sự kiện phím cứng luôn được chuyển tới Dạng xem đang được lấy tiêu điểm. Chúng được chuyển bắt đầu từ trên cùng của phân cấp Dạng xem, rồi xuống dưới, tới khi chúng đến đích phù hợp. Nếu Dạng xem của bạn (hoặc con của Dạng xem) hiện có tiêu điểm, khi đó bạn có thể thấy hành trình của sự kiện qua phương pháp dispatchKeyEvent(). Một cách khác để chụp lại các sự kiện phím bấm thông qua Dạng xem của mình, bạn cũng có thể nhận tất cả sự kiện bên trong Hoạt động của mình bằng onKeyDown()onKeyUp().

Đồng thời, khi nghĩ tới nhập liệu văn bản cho ứng dụng của bạn, hãy nhớ rằng nhiều thiết bị chỉ có các phương pháp nhập liệu mềm. Những phương pháp như vậy không bắt buộc phải dựa trên phím bấm; một số có thể sử dụng nhập liệu bằng giọng nói, viết tay, v.v. Ngay cả khi một phương pháp nhập liệu trình bày một giao diện như bàn phím, nó sẽ thường không kích khởi họ sự kiện onKeyDown(). Bạn không nên xây dựng UI yêu cầu kiểm soát các thao tác nhấn phím cụ thể trừ khi muốn giới hạn ứng dụng của bạn ở một số thiết bị có bàn phím cứng. Cụ thể, không được dựa vào những phương pháp này để xác thực nhập liệu khi người dùng nhấn phím quay lại; thay vào đó, hãy sử dụng các hành động như IME_ACTION_DONE để báo hiệu với phương pháp nhập liệu bạn kỳ vọng ứng dụng của mình sẽ phản ứng như thế nào để nó có thể thay đổi UI của mình cho có nghĩa. Tránh các giả định về cách thức hoạt động của một phương pháp nhập liệu mềm và chỉ tin tưởng để nó cung cấp văn bản đã có định dạng cho ứng dụng của mình.

Lưu ý: Android sẽ gọi bộ xử lý sự kiện trước rồi mới tới bộ xử lý mặc định phù hợp từ định nghĩa lớp. Như thế, việc trả về true từ những đối tượng theo dõi sự kiện này sẽ dừng việc lan truyền sự kiện tới đối tượng theo dõi sự kiện khác và cũng sẽ chặn phương pháp gọi lại tới bộ xử lý sự kiện mặc định trong Dạng xem. Vì thế, hãy chắc chắn rằng bạn muốn chấm dứt sự kiện khi trả về true.

Bộ xử lý Sự kiện

Nếu bạn đang xây dựng một thành phần tùy chỉnh từ Dạng xem, khi đó bạn sẽ có thể định nghĩa một vài phương pháp gọi lại được sử dụng như bộ xử lý sự kiện mặc định. Trong tài liệu về Thành phần Tùy chỉnh, bạn sẽ tìm hiểu về một số phương pháp gọi lại phổ biến được sử dụng để xử lý sự kiện, bao gồm:

Có một số phương pháp khác mà bạn cần lưu ý, chúng không thuộc lớp Dạng xem, nhưng có thể tác động trực tiếp tới cách bạn có thể xử lý sự kiện. Vì thế, khi quản lý các sự kiện phức tạp hơn bên trong một bố trí, hãy xét những phương pháp khác sau:

Chế độ Cảm ứng

Khi một người dùng đang điều hướng trong một giao diện người dùng bằng phím hướng hoặc bi xoay, cần lấy tiêu điểm tới các mục có thể hành động (như nút) sao cho người dùng có thể thấy mục nào sẽ chấp nhận nhập liệu. Tuy nhiên, nếu thiết bị có khả năng cảm ứng, và người dùng bắt đầu tương tác với giao diện bằng cách chạm vào nó, khi đó không còn cần tô sáng mục hay lấy tiêu điểm tới một Dạng xem cụ thể nữa. Do đó, có một chế độ cho tương tác có tên là "chế độ cảm ứng."

Đối với thiết bị có khả năng cảm ứng, sau khi người dùng chạm vào màn hình, thiết bị sẽ vào chế độ cảm ứng. Từ điểm này trở đi, chỉ những Dạng xem mà isFocusableInTouchMode() là đúng mới có thể lấy tiêu điểm, chẳng hạn như chế độ xem các widget chỉnh sửa văn bản. Các Dạng xem chạm được, chẳng hạn như nút, sẽ không lấy được tiêu điểm khi chạm; chúng sẽ chỉ đơn giản khởi chạy đối tượng theo dõi khi nhấp của mình khi được nhấn.

Bất cứ khi nào một người dùng nhấn phím hướng hoặc cuộn bằng bi xoay, thiết bị sẽ thoát chế độ cảm ứng, và tìm một dạng xem để lấy tiêu điểm. Lúc này, người dùng có thể tiếp tục tương tác với giao diện người dùng mà không chạm vào màn hình.

Trạng thái chế độ cảm ứng sẽ được duy trì trên toàn bộ hệ thống (tất cả cửa sổ và hoạt động). Để truy vấn trạng thái hiện tại, bạn có thể gọi isInTouchMode() để xem liệu thiết bị có đang ở trong chế độ cảm ứng hay không.

Xử lý Tiêu điểm

Khuôn khổ sẽ xử lý chuyển động của tiêu điểm thường xuyên hồi đáp lại nhập liệu của người dùng. Việc này bao gồm thay đổi tiêu điểm khi Dạng xem bị loại bỏ hoặc ẩn đi, hoặc khi Dạng xem mới có sẵn. Dạng xem thể hiện sự sẵn sàng lấy tiêu điểm của chúng thông qua phương pháp isFocusable(). Để thay đổi việc liệu một Dạng xem có thể lấy tiêu điểm hay không, hãy gọi setFocusable(). Khi ở trong chế độ cảm ứng, bạn có thể truy vấn xem Dạng xem có cho phép lấy tiêu điểm bằng isFocusableInTouchMode() hay không. Bạn có thể thay đổi điều này bằng setFocusableInTouchMode().

Chuyển động tiêu điểm được dựa trên một giải thuật tìm kiếm đối tượng gần nhất theo một hướng cho trước. Trong các trường hợp hiếm gặp, giải thuật mặc định có thể không khớp với hành vi theo ý định của nhà phát triển. Trong những tình huống này, bạn có thể cung cấp các khống chế rõ ràng với các thuộc tính XML sau trong tệp bố trí: nextFocusDown, nextFocusLeft, nextFocusRight, và nextFocusUp. Thêm một trong những thuộc tính này vào Dạng xem mà từ đó tiêu điểm đang rời khỏi. Định nghĩa giá trị của thuộc tính là id của Dạng xem cần được lấy tiêu điểm. Ví dụ:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

Thông thưởng, trong bố trí thẳng đứng này, việc điều hướng lên từ Nút đầu tiên sẽ không đi tới đâu hết và việc điều hướng xuống từ Nút thứ hai cũng vậy. Giờ thì khi Nút trên cùng đã định nghĩa Nút dưới cùng là nextFocusUp (và ngược lại), tiêu điểm điều hướng sẽ luân chuyển từ trên-xuống-dưới và dưới-lên-trên.

Nếu bạn muốn khai báo một Dạng xem là có thể lấy tiêu điểm trong UI của mình (thông thường thì không), hãy thêm thuộc tính XML android:focusable vào Dạng xem, trong khai báo bố trí của bạn. Đặt giá trị true. Bạn cũng có thể khai báo một Dạng xem là có thể lấy tiêu điểm trong khi ở Chế độ Cảm ứng bằng android:focusableInTouchMode.

Để yêu cầu một Dạng xem cụ thể để lấy tiêu điểm, hãy gọi requestFocus().

Để theo dõi các sự kiện tiêu điểm (được thông báo khi một Dạng xem nhận được hoặc mất tiêu điểm), hãy sử dụng onFocusChange(), như được đề cập trong phần Đối tượng theo dõi Sự kiện bên trên.