Thêm một bước có hướng dẫn

Tạo dựng ứng dụng hiệu quả hơn bằng Compose
Tạo giao diện người dùng đẹp mắt với mã tối thiểu bằng Jetpack Compose cho hệ điều hành Android TV.

Ứng dụng của bạn có thể có các tác vụ nhiều bước cho người dùng. Ví dụ: ứng dụng của bạn có thể cần hướng dẫn người dùng mua thêm nội dung, thiết lập một chế độ cài đặt cấu hình phức tạp hoặc xác nhận một quyết định. Tất cả những việc này đều yêu cầu người dùng thực hiện một hoặc nhiều bước hoặc quyết định theo trình tự.

Thư viện androidx.leanback không dùng nữa cung cấp các lớp để triển khai các tác vụ nhiều bước của người dùng. Trang này thảo luận về cách sử dụng lớp GuidedStepSupportFragment để hướng dẫn người dùng đưa ra một loạt quyết định nhằm hoàn thành một tác vụ bằng cách sử dụng GuidedStepSupportFragment.

Cung cấp thông tin chi tiết cho một bước

GuidedStepSupportFragment biểu thị một bước duy nhất trong một loạt các bước. Về mặt hình ảnh, thành phần này cung cấp một chế độ xem hướng dẫn với danh sách các hành động hoặc quyết định có thể có cho bước đó.

Hình 1. Ví dụ về một bước có hướng dẫn.

Đối với mỗi bước trong tác vụ nhiều bước, hãy mở rộng GuidedStepSupportFragment và cung cấp thông tin ngữ cảnh về bước và các hành động mà người dùng có thể thực hiện. Ghi đè onCreateGuidance() và trả về một GuidanceStylist.Guidance mới chứa thông tin về bối cảnh, chẳng hạn như tiêu đề, nội dung mô tả và biểu tượng của bước, như minh hoạ trong ví dụ sau:

Kotlin

override fun onCreateGuidance(savedInstanceState: Bundle?): GuidanceStylist.Guidance {
    return GuidanceStylist.Guidance(
            getString(R.string.guidedstep_first_title),
            getString(R.string.guidedstep_first_description),
            getString(R.string.guidedstep_first_breadcrumb),
            activity.getDrawable(R.drawable.guidedstep_main_icon_1)
    )
}

Java

@Override
public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
    String title = getString(R.string.guidedstep_first_title);
    String breadcrumb = getString(R.string.guidedstep_first_breadcrumb);
    String description = getString(R.string.guidedstep_first_description);
    Drawable icon = getActivity().getDrawable(R.drawable.guidedstep_main_icon_1);
    return new GuidanceStylist.Guidance(title, description, breadcrumb, icon);
}

Thêm lớp con GuidedStepSupportFragment vào hoạt động mà bạn muốn bằng cách gọi GuidedStepSupportFragment.add() trong phương thức onCreate() của hoạt động.

Nếu hoạt động của bạn chỉ chứa các đối tượng GuidedStepSupportFragment, hãy dùng GuidedStepSupportFragment.addAsRoot() thay vì add() để thêm GuidedStepSupportFragment đầu tiên. Việc sử dụng addAsRoot() giúp đảm bảo rằng nếu người dùng nhấn nút Quay lại trên điều khiển từ xa của TV khi xem GuidedStepSupportFragment đầu tiên, thì cả GuidedStepSupportFragment và hoạt động mẹ đều đóng.

Lưu ý: Thêm các đối tượng GuidedStepSupportFragment theo phương thức lập trình, không phải trong tệp XML bố cục.

Tạo và xử lý thao tác của người dùng

Thêm hành động của người dùng bằng cách ghi đè onCreateActions(). Trong phương thức ghi đè, hãy thêm một GuidedAction mới cho mỗi mục thao tác và cung cấp chuỗi thao tác, nội dung mô tả và mã nhận dạng. Sử dụng GuidedAction.Builder để thêm hành động mới.

Kotlin

override fun onCreateActions(actions: MutableList<GuidedAction>, savedInstanceState: Bundle?) {
    super.onCreateActions(actions, savedInstanceState)

    // Add "Continue" user action for this step
    actions.add(GuidedAction.Builder()
            .id(CONTINUE)
            .title(getString(R.string.guidedstep_continue))
            .description(getString(R.string.guidedstep_letsdoit))
            .hasNext(true)
            .build())
    ...

Java

@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
    // Add "Continue" user action for this step
    actions.add(new GuidedAction.Builder()
           .id(CONTINUE)
           .title(getString(R.string.guidedstep_continue))
           .description(getString(R.string.guidedstep_letsdoit))
           .hasNext(true)
           .build());
...

Các thao tác không chỉ giới hạn ở lựa chọn một dòng. Sau đây là các loại hành động khác mà bạn có thể tạo:

  • Thêm một thao tác nhãn thông tin để cung cấp thêm thông tin về lựa chọn của người dùng bằng cách đặt infoOnly(true). Khi infoOnly là true, người dùng không thể chọn thao tác.
  • Thêm một thao tác chỉnh sửa văn bản bằng cách đặt editable(true). Khi editable là true, người dùng có thể nhập văn bản vào một thao tác đã chọn bằng điều khiển từ xa hoặc bàn phím được kết nối. Ghi đè onGuidedActionEditedAndProceed() để nhận văn bản đã sửa đổi mà người dùng nhập. Bạn cũng có thể ghi đè onGuidedActionEditCanceled() để biết thời điểm người dùng huỷ thao tác nhập.
  • Thêm một nhóm thao tác hoạt động như các nút chọn có thể đánh dấu bằng cách sử dụng checkSetId() với giá trị mã nhận dạng chung để nhóm các thao tác thành một nhóm. Tất cả các thao tác trong cùng một danh sách có cùng mã nhận dạng bộ kiểm tra đều được coi là có liên kết. Khi người dùng chọn một trong các thao tác trong nhóm đó, thao tác đó sẽ được đánh dấu và tất cả các thao tác khác sẽ không được đánh dấu.
  • Thêm thao tác bộ chọn ngày bằng cách sử dụng GuidedDatePickerAction.Builder thay vì GuidedAction.Builder trong onCreateActions(). Ghi đè onGuidedActionEditedAndProceed() để nhận giá trị ngày đã sửa đổi mà người dùng nhập.
  • Thêm một thao tác sử dụng các thao tác phụ để cho phép người dùng chọn trong danh sách lựa chọn mở rộng. Các thao tác phụ được mô tả trong phần Thêm thao tác phụ.
  • Thêm một thao tác bằng nút xuất hiện ở bên phải danh sách thao tác và dễ dàng truy cập. Các thao tác trên nút được mô tả trong phần Thêm thao tác trên nút.

Bạn cũng có thể thêm một chỉ báo trực quan cho biết việc chọn một thao tác sẽ dẫn đến một bước mới bằng cách đặt hasNext(true).

Để biết tất cả các thuộc tính khác nhau mà bạn có thể đặt, hãy xem GuidedAction.

Để phản hồi các thao tác, hãy ghi đè onGuidedActionClicked() và xử lý GuidedAction đã truyền vào. Xác định hành động đã chọn bằng cách kiểm tra GuidedAction.getId().

Thêm hành động phụ

Một số hành động có thể yêu cầu bạn cung cấp cho người dùng một nhóm lựa chọn bổ sung. GuidedAction có thể chỉ định một danh sách các thao tác phụ xuất hiện dưới dạng một trình đơn gồm các thao tác con.

Hình 2. Các thao tác phụ của bước có hướng dẫn.

Danh sách thao tác phụ có thể chứa các thao tác thông thường hoặc thao tác nút chọn, nhưng không chứa thao tác bộ chọn ngày hoặc thao tác văn bản có thể chỉnh sửa. Ngoài ra, một thao tác phụ không thể có bộ thao tác phụ riêng, vì hệ thống không hỗ trợ nhiều cấp thao tác phụ.

Để thêm các thao tác phụ, trước tiên, hãy tạo và điền sẵn một danh sách các đối tượng GuidedAction đóng vai trò là các thao tác phụ, như trong ví dụ sau:

Kotlin

subActions.add(GuidedAction.Builder()
        .id(SUBACTION1)
        .title(getString(R.string.guidedstep_subaction1_title))
        .description(getString(R.string.guidedstep_subaction1_desc))
        .build())
...

Java

List<GuidedAction> subActions = new ArrayList<GuidedAction>();
subActions.add(new GuidedAction.Builder()
       .id(SUBACTION1)
       .title(getString(R.string.guidedstep_subaction1_title))
       .description(getString(R.string.guidedstep_subaction1_desc))
       .build());
...

Trong onCreateActions(), hãy tạo một GuidedAction cấp cao nhất hiển thị danh sách các thao tác phụ khi được chọn:

Kotlin

    ...
    actions.add(GuidedAction.Builder()
            .id(SUBACTIONS)
            .title(getString(R.string.guidedstep_subactions_title))
            .description(getString(R.string.guidedstep_subactions_desc))
            .subActions(subActions)
            .build())
    ...

Java

@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
...
    actions.add(new GuidedAction.Builder()
           .id(SUBACTIONS)
           .title(getString(R.string.guidedstep_subactions_title))
           .description(getString(R.string.guidedstep_subactions_desc))
           .subActions(subActions)
           .build());
...
}

Cuối cùng, hãy phản hồi các lựa chọn về thao tác phụ bằng cách ghi đè onSubGuidedActionClicked():

Kotlin

override fun onSubGuidedActionClicked(action: GuidedAction): Boolean {
    // Check for which action was clicked and handle as needed
    when(action.id) {
        SUBACTION1 -> {
            // Subaction 1 selected
        }
    }
    // Return true to collapse the subactions menu or
    // false to keep the menu expanded
    return true
}

Java

@Override
public boolean onSubGuidedActionClicked(GuidedAction action) {
   // Check for which action was clicked and handle as needed
   if (action.getId() == SUBACTION1) {
       // Subaction 1 selected
   }
   // Return true to collapse the subactions menu or
   // false to keep the menu expanded
   return true;
}

Thêm thao tác của nút

Nếu bước có hướng dẫn của bạn có một danh sách dài các hành động, thì người dùng có thể phải di chuyển qua danh sách để truy cập vào các hành động thường dùng nhất. Sử dụng các thao tác trên nút để tách các thao tác thường dùng khỏi danh sách thao tác. Các thao tác của nút xuất hiện bên cạnh danh sách thao tác và rất dễ điều hướng đến.

Hình 3. Các thao tác trên nút của bước có hướng dẫn.

Các thao tác trên nút được tạo và xử lý giống như các thao tác thông thường, nhưng bạn tạo các thao tác trên nút trong onCreateButtonActions() thay vì onCreateActions(). Phản hồi các thao tác trên nút trong onGuidedActionClicked().

Sử dụng thao tác bằng nút cho các thao tác đơn giản, chẳng hạn như thao tác điều hướng giữa các bước. Đừng sử dụng thao tác chọn ngày hoặc các thao tác có thể chỉnh sửa khác làm thao tác của nút. Ngoài ra, các thao tác trên nút không thể có thao tác phụ.

Nhóm các bước có hướng dẫn thành một chuỗi hướng dẫn

GuidedStepSupportFragment biểu thị một bước duy nhất. Để tạo một chuỗi các bước có thứ tự, hãy nhóm nhiều đối tượng GuidedStepSupportFragment lại với nhau bằng cách sử dụng GuidedStepSupportFragment.add() để thêm bước tiếp theo trong chuỗi vào ngăn xếp mảnh.

Kotlin

override fun onGuidedActionClicked(action: GuidedAction) {
    val fm = fragmentManager
    when(action.id) {
        CONTINUE -> GuidedStepSupportFragment.add(fm, SecondStepFragment())
    }
}

Java

@Override
public void onGuidedActionClicked(GuidedAction action) {
    FragmentManager fm = getFragmentManager();
    if (action.getId() == CONTINUE) {
       GuidedStepSupportFragment.add(fm, new SecondStepFragment());
    }
...

Nếu người dùng nhấn nút Quay lại trên điều khiển từ xa của TV, thiết bị sẽ hiện GuidedStepSupportFragment trước đó trên ngăn xếp mảnh. Nếu cung cấp GuidedAction của riêng mình để quay lại bước trước, bạn có thể triển khai hành vi Quay lại bằng cách gọi getFragmentManager().popBackStack(). Nếu bạn cần đưa người dùng quay lại một bước trước đó trong chuỗi, hãy dùng popBackStackToGuidedStepSupportFragment() để quay lại một GuidedStepSupportFragment cụ thể trong ngăn xếp mảnh.

Khi người dùng hoàn tất bước cuối cùng trong chuỗi, hãy dùng finishGuidedStepSupportFragments() để xoá tất cả các thực thể GuidedStepSupportFragment khỏi ngăn xếp hiện tại và quay lại hoạt động mẹ ban đầu. Nếu GuidedStepSupportFragment đầu tiên được thêm bằng addAsRoot(), thì việc gọi finishGuidedStepSupportFragments() cũng sẽ đóng hoạt động mẹ.

Tuỳ chỉnh cách trình bày bước

Lớp GuidedStepSupportFragment có thể sử dụng các giao diện tuỳ chỉnh để kiểm soát các khía cạnh trình bày, chẳng hạn như định dạng văn bản tiêu đề hoặc ảnh động chuyển đổi bước. Các giao diện tuỳ chỉnh phải kế thừa từ Theme_Leanback_GuidedStep và có thể cung cấp các giá trị ghi đè cho các thuộc tính được xác định trong GuidanceStylistGuidedActionsStylist.

Để áp dụng một giao diện tuỳ chỉnh cho GuidedStepSupportFragment, hãy làm theo một trong những cách sau:

  • Áp dụng giao diện cho hoạt động mẹ bằng cách đặt thuộc tính android:theme thành phần tử hoạt động trong tệp kê khai Android. Việc đặt thuộc tính này sẽ áp dụng giao diện cho tất cả các khung hiển thị con và là cách đơn giản nhất để áp dụng một giao diện tuỳ chỉnh nếu hoạt động mẹ chỉ chứa các đối tượng GuidedStepSupportFragment.
  • Nếu hoạt động của bạn đã sử dụng một giao diện tuỳ chỉnh và bạn không muốn áp dụng các kiểu GuidedStepSupportFragment cho những thành phần hiển thị khác trong hoạt động, hãy thêm thuộc tính LeanbackGuidedStepTheme_guidedStepTheme vào giao diện hoạt động tuỳ chỉnh hiện có. Thuộc tính này trỏ đến giao diện tuỳ chỉnh mà chỉ các đối tượng GuidedStepSupportFragment trong hoạt động của bạn sử dụng.
  • Nếu bạn sử dụng các đối tượng GuidedStepSupportFragment trong nhiều hoạt động là một phần của cùng một tác vụ tổng thể gồm nhiều bước và muốn sử dụng một giao diện nhất quán trên tất cả các bước, hãy ghi đè GuidedStepSupportFragment.onProvideTheme() và trả về giao diện tuỳ chỉnh của bạn.

Để biết thêm thông tin về cách thêm kiểu và giao diện, hãy xem phần Kiểu và giao diện.

Lớp GuidedStepSupportFragment sử dụng các lớp nhà tạo kiểu đặc biệt để truy cập và áp dụng các thuộc tính giao diện. Lớp GuidanceStylist sử dụng thông tin về giao diện để kiểm soát cách trình bày chế độ xem hướng dẫn bên trái, trong khi lớp GuidedActionsStylist sử dụng thông tin về giao diện để kiểm soát cách trình bày chế độ xem thao tác bên phải.

Để tuỳ chỉnh kiểu trực quan của các bước ngoài những gì mà chế độ tuỳ chỉnh giao diện cung cấp, hãy tạo lớp con GuidanceStylist hoặc GuidedActionsStylist và trả về lớp con của bạn trong GuidedStepSupportFragment.onCreateGuidanceStylist() hoặc GuidedStepSupportFragment.onCreateActionsStylist(). Để biết thông tin chi tiết về những nội dung bạn có thể tuỳ chỉnh trong các lớp con này, hãy xem tài liệu về GuidanceStylistGuidedActionsStylist.