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 bằng đối tượng sửa đổi focusGroup. Tính năng nhóm cho phép bạn quản lý 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ụ, hành động trong hộp thoại hoặc danh sách thẻ) và chặn khi tiêu điểm vào hoặc thoát khỏi một vùng.

Khái niệm về phỏng vấn nhóm: vào, thoát và duyệt qua mặc định

Nhóm tiêu điểm thiết lập ranh giới điều hướng gắn kết xung quanh các mục tiêu 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 hai khái niệm chính:

  • Enter: Sự kiện xảy ra khi tiêu điểm chuyển từ bất kỳ phần tử nào 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ơ đồ cho thấy hiệu ứng chuyển đổi Enter (Vào) và Exit (Thoát) trên ranh giới của nhóm tiêu điểm.
Hình 1. Phỏng vấn nhóm 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 tự động chọn một mục tiêu lấy tiêu điểm con nội bộ. Đối với thao tác di chuyển một chiều (Tab), thao tác 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. Di chuyển trong nhóm: Thao tác nhấn phím điều hướng nhiều lần sẽ di chuyển tiêu điểm giữa các mục tiêu lấy tiêu điểm đồng cấp trong nhóm.
  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 bên trong nhóm, thao tác 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 lệnh chuyển hướng mục lấy 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ư mục 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.

Mục đích và trường hợp sử dụng

Hãy xem xét một 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 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 nhập nhóm nút từ trước đó theo thứ tự tiêu điểm, trong khi vẫn cho phép người dùng nhấn phím Mũi tên trái để chọn "Huỷ" nếu cần.
Mục tiêu lấy tiêu điểm mặc định trong một nhóm nút.
Hình 2. 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 nút đ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 chuyển 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 (trong phạm vi FocusEnterExitScope), hãy gọi requestFocus() trên FocusRequester liên kết với phần tử con mặc định ưu tiên bằ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 quá trình chuyển đổi tiêu điểm qua ranh giới hoặc kiểm tra requestedFocusDirection để tuỳ chỉnh định tuyến dựa trên việc người dùng có điều hướng bằng phím Tab, Xuống hay Trái hay không.

Theo mặc định, các vùng chứa có thể cuộn là nhóm lấy 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 đóng vai trò là nhóm tiêu điểm. Bạn không cần phải áp dụng rõ ràng đối tượng sửa đổi focusGroup cho các thành phần đó để đặt lệnh gọi lại onEnter hoặc onExit.