Nhóm mục tiêu lấy tiêu điểm

Bạn có thể nhóm nhiều mục tiêu lấy tiêu điểm với nhau bằng đối tượng sửa đổi focusGroup. Việc nhóm cho phép bạn quản lý các hệ phân cấp tiêu điểm, tách biệt các vùng giao diện người dùng logic (chẳng hạn như thanh công cụ, thao tác trên hộp thoại hoặc danh sách thẻ) và chặn khi tiêu điểm đi vào hoặc thoát khỏi một vùng.

Các khái niệm về nhóm tiêu điểm: nhập, thoát và duyệt qua mặc định

Nhóm tiêu điểm thiết lập một ranh giới điều hướng gắn kết xung quanh các mục tiêu lấy tiêu điểm con. Để hiểu cách tiêu điểm di chuyển qua ranh giới này, bạn cần nắm được 2 khái niệm chính:

  • Enter: Sự kiện xảy ra khi tiêu điểm chuyển từ một phần tử bất kỳ bên ngoài nhóm tiêu điểm sang một phần tử bên trong nhóm.
  • Thoát: Sự kiện xảy ra khi tiêu điểm rời khỏi phần tử nội bộ cuối cùng của nhóm và chuyển sang mục tiêu tiêu điểm bên ngoài.
Sơ đồ minh hoạ hiệu ứng chuyển đổi Nhập và Thoát trên ranh giới nhóm tiêu điểm.
Hình 1. Nhóm tiêu điểm có các sự kiện nhập và thoát.

Hành vi duyệt qua tiêu điểm mặc định

Theo mặc định, khi một nhóm phỏng vấn nhận được tiêu điểm từ bên ngoài:

  1. Vào nhóm: Compose sẽ tự động chọn một mục tiêu lấy tiêu điểm con bên trong. Đối với chế độ điều hướng một chiều (Tab), chế độ này sẽ chọn thành phần con đầu tiên theo thứ tự xuất hiện trực quan. Đối với thao tác điều hướng hai chiều (phím mũi tên hoặc D-pad), thao tác này sẽ chọn thành phần con gần nhất về mặt hình học với hướng đến.
  2. Điều hướng trong nhóm: Khi bạn nhấn phím điều hướng nhiều lần, tiêu điểm sẽ di chuyển giữa các mục tiêu lấy tiêu điểm ngang hàng được nhóm này bao quanh.
  3. Thoát khỏi nhóm: Sau khi người dùng di chuyển qua mục tiêu lấy tiêu điểm cuối cùng trong nhóm, lần nhấn phím tiếp theo sẽ thoát khỏi nhóm và di chuyển tiêu điểm đến mục tiêu lấy tiêu điểm lân cận bên ngoài nhóm.

Tuỳ chỉnh việc chuyển hướng mục nhập tiêu điểm

Trong nhiều thiết kế giao diện người dùng, mục tiêu nhập mặc định (chẳng hạn như phần tử con đầu tiên theo thứ tự xuất hiện) không phải là lựa chọn hợp lý hoặc thuận tiện nhất cho người dùng.

Ý định và trường hợp sử dụng

Hãy cân nhắc hộp thoại xác nhận có nút "Huỷ" ở bên trái và nút "Xác nhận" chính ở bên phải. Khi người dùng di chuyển xuống thanh nút từ một trường trong biểu mẫu:

  • Hành vi mặc định: Tiêu điểm sẽ nằm trên nút "Huỷ" vì đây là nút đầu tiên theo thứ tự xuất hiện trực quan.
  • Hành vi dự kiến: Vì "Xác nhận" là hành động được đề xuất chính, nên bạn có thể muốn tiêu điểm chuyển thẳng đến "Xác nhận" khi người dùng vào nhóm nút từ trước đó trong thứ tự tiêu điểm, đồng thời vẫn cho phép người dùng nhấn Trái để chọn "Huỷ" nếu cần.
Mục nhập tiêu điểm mặc định vào một nhóm nút.
Hình 2. Các nút Huỷ và Xác nhận có mục tiêu nhập tiêu điểm mặc định.

Các trường hợp sử dụng phổ biến khác bao gồm:

  • Di chuyển tiêu điểm trực tiếp đến thẻ hiện được chọn khi nhập TabRow.
  • Di chuyển tiêu điểm trực tiếp đến chế độ điều khiển "Phát / Tạm dừng" khi vào thanh phát nội dung nghe nhìn.

Triển khai bằng onEnter và FocusRequester

Cách chuyển hướng tiêu điểm khi vào một nhóm tiêu điểm:

  1. Áp dụng đối tượng sửa đổi focusGroup cho vùng chứa mẹ bao quanh các mục tiêu lấy tiêu điểm có liên quan.
  2. Áp dụng đối tượng sửa đổi focusProperties cho vùng chứa và định cấu hình lệnh gọi lại onEnter.
  3. Trong lệnh gọi lại onEnter (có phạm vi là FocusEnterExitScope), hãy gọi requestFocus() trên FocusRequester được liên kết với thành phần con mặc định ưu tiên bằng cách sử dụng focusRequester.

val defaultChildRequester = remember { FocusRequester() }

Row(
    modifier = Modifier
        .focusGroup()
        .focusProperties {
            // Intercept entry into this group and redirect focus to the primary action
            onEnter = {
                defaultChildRequester.requestFocus()
            }
        }
) {
    Button(onClick = { /* Cancel action */ }) {
        Text("Cancel")
    }
    Button(
        onClick = { /* Confirm action */ },
        modifier = Modifier.focusRequester(defaultChildRequester)
    ) {
        Text("Confirm (Default)")
    }
}

Bên trong onEnter và onExit, bạn cũng có thể gọi cancelFocusChange() để chặn hoàn toàn các quá trình chuyển đổi tiêu điểm trên ranh giới hoặc kiểm tra requestedFocusDirection để tuỳ chỉnh việc định tuyến dựa trên việc người dùng có điều hướng bằng Tab, Down hay Left hay không.

Theo mặc định, các vùng chứa có thể cuộn là nhóm tiêu điểm

Trong Jetpack Compose, các vùng chứa có thể cuộn như LazyRow, LazyColumn và LazyVerticalGrid sẽ tự động hoạt động như các nhóm tiêu điểm. Bạn không cần áp dụng rõ ràng đối tượng sửa đổi focusGroup cho các thành phần này để đặt lệnh gọi lại onEnter hoặc onExit.