添加引导步骤

使用 Compose 构建更出色的应用
使用适用于 Android TV OS 的 Jetpack Compose,以最少的代码创建漂亮的 UI。

您的应用程序可能包含用户需要执行的多步任务。例如,您的应用可能需要引导用户完成购买额外内容、设置复杂的配置设置或只是确认决定。所有这些任务都需要引导用户完成一个或多个有序步骤或决定。

androidx.leanback 库 提供用于实现多步用户任务的类。此页面讨论如何使用 GuidedStepSupportFragment 类引导用户完成一系列决定以完成任务。GuidedStepSupportFragment 使用 TV UI 最佳实践,使多步任务在电视设备上易于理解和导航。

提供步骤的详细信息

GuidedStepSupportFragment 代表一系列步骤中的单个步骤。从视觉上看,它提供了一个指导视图,其中包含该步骤可能的动作或决定的列表。

图 1. 指导步骤示例。

对于多步任务中的每个步骤,扩展 GuidedStepSupportFragment 并提供有关该步骤以及用户可以采取的操作的上下文信息。覆盖 onCreateGuidance() 并返回一个新的 GuidanceStylist.Guidance,其中包含上下文信息,例如步骤标题、说明和图标,如下例所示

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);
}

通过在您活动的 onCreate() 方法中调用 GuidedStepSupportFragment.add(),将您的 GuidedStepSupportFragment 子类添加到所需的活动。

如果您的活动仅包含 GuidedStepSupportFragment 对象,请使用 GuidedStepSupportFragment.addAsRoot() 而不是 add() 来添加第一个 GuidedStepSupportFragment。使用 addAsRoot() 有助于确保如果用户在查看第一个 GuidedStepSupportFragment 时按下电视遥控器上的后退按钮,则 GuidedStepSupportFragment 和父活动都会关闭。

注意:以编程方式添加 GuidedStepSupportFragment 对象,而不是在您的布局 XML 文件中添加。

创建和处理用户操作

通过覆盖 onCreateActions() 添加用户操作。在您的覆盖中,为每个操作项添加一个新的 GuidedAction,并提供操作字符串、说明和 ID。使用 GuidedAction.Builder 添加新操作。

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());
...

操作不限于单行选择。以下是可以创建的其他类型的操作:

  • 通过设置 infoOnly(true) 添加信息标签操作,以提供有关用户选择的更多信息。当 infoOnly 为 true 时,用户无法选择该操作。
  • 通过设置 editable(true) 添加可编辑文本操作。当 editable 为 true 时,用户可以使用遥控器或连接的键盘在选定的操作中输入文本。覆盖 onGuidedActionEditedAndProceed() 以获取用户输入的修改后的文本。您还可以覆盖 onGuidedActionEditCanceled() 以了解用户何时取消输入。
  • 通过使用 checkSetId() 和一个公共 ID 值将操作分组为一个集合,添加一组行为类似于可选中单选按钮的操作。同一列表中具有相同检查集 ID 的所有操作都被视为链接。当用户选择该集合中的一个操作时,该操作将被选中,而所有其他操作将被取消选中。
  • onCreateActions() 中使用 GuidedDatePickerAction.Builder 而不是 GuidedAction.Builder 添加日期选择器操作。覆盖 onGuidedActionEditedAndProceed() 以获取用户输入的修改后的日期值。
  • 添加一个使用子操作的操作,让用户从扩展的选择列表中进行选择。子操作在添加子操作部分中进行了描述。
  • 添加一个出现在操作列表右侧且易于访问的按钮操作。按钮操作在添加按钮操作部分中进行了描述。

您还可以添加一个视觉指示器,指示选择操作会导致新的步骤,方法是设置 hasNext(true)

对于可以设置的所有不同属性,请参阅 GuidedAction

要响应操作,请覆盖 onGuidedActionClicked() 并处理传入的 GuidedAction。通过检查 GuidedAction.getId() 来识别选定的操作。

添加子操作

某些操作可能需要您向用户提供额外的选择。一个GuidedAction可以指定一个子操作列表,这些子操作显示为子操作菜单。

图 2. 指导步骤子操作。

子操作列表可以包含常规操作或单选按钮操作,但不包含日期选择器或可编辑文本操作。此外,子操作不能拥有自己的子操作集,因为系统不支持多于一级子操作。

要添加子操作,首先创建并填充一个GuidedAction对象的列表,这些对象充当子操作,如下例所示

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());
...

onCreateActions()中,创建一个顶级GuidedAction,当选中时显示子操作列表

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());
...
}

最后,通过覆盖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;
}

添加按钮操作

如果您的引导步骤包含大量的操作,用户可能需要滚动列表才能访问最常用的操作。使用按钮操作将常用的操作与操作列表分开。按钮操作显示在操作列表旁边,易于导航。

图 3. 指导步骤按钮操作。

按钮操作的创建和处理方式与常规操作相同,但是您在onCreateButtonActions()而不是onCreateActions()中创建按钮操作。在onGuidedActionClicked()中响应按钮操作。

将按钮操作用于简单的操作,例如步骤之间的导航操作。不要将日期选择器操作或其他可编辑操作用作按钮操作。此外,按钮操作不能有子操作。

将引导步骤分组到引导序列中

一个GuidedStepSupportFragment代表单个步骤。要创建步骤的有序序列,请使用GuidedStepSupportFragment.add()将多个GuidedStepSupportFragment对象组合在一起,以将序列中的下一个步骤添加到片段堆栈。

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());
    }
...

如果用户按下电视遥控器上的“返回”按钮,设备将显示片段堆栈中的前一个GuidedStepSupportFragment。如果您提供自己的GuidedAction以返回到上一步,则可以通过调用getFragmentManager().popBackStack()来实现“返回”行为。如果您需要将用户返回到序列中更早的步骤,请使用popBackStackToGuidedStepSupportFragment()返回到片段堆栈中的特定GuidedStepSupportFragment

当用户完成序列中的最后一步时,使用finishGuidedStepSupportFragments()从当前堆栈中删除所有GuidedStepSupportFragment实例并返回到原始父活动。如果第一个GuidedStepSupportFragment是使用addAsRoot()添加的,则调用finishGuidedStepSupportFragments()也会关闭父活动。

自定义步骤演示

GuidedStepSupportFragment类可以使用自定义主题来控制演示方面,例如标题文本格式或步骤转换动画。自定义主题必须继承自Theme_Leanback_GuidedStep,并可以为GuidanceStylistGuidedActionsStylist中定义的属性提供覆盖值。

要将自定义主题应用于您的GuidedStepSupportFragment,请执行以下操作之一

  • 通过将android:theme属性设置为Android清单中活动元素来将主题应用于父活动。设置此属性会将主题应用于所有子视图,如果父活动仅包含GuidedStepSupportFragment对象,这是应用自定义主题最直接的方法。
  • 如果您的活动已经使用自定义主题,并且您不想将GuidedStepSupportFragment样式应用于活动中的其他视图,请将LeanbackGuidedStepTheme_guidedStepTheme属性添加到您现有的自定义活动主题。此属性指向仅活动中的GuidedStepSupportFragment对象使用的自定义主题。
  • 如果您在属于同一整体多步骤任务的不同活动中使用GuidedStepSupportFragment对象,并希望在所有步骤中使用一致的视觉主题,请覆盖GuidedStepSupportFragment.onProvideTheme()并返回您的自定义主题。

有关如何添加样式和主题的更多信息,请参阅样式和主题

GuidedStepSupportFragment类使用特殊的样式类来访问和应用主题属性。GuidanceStylist类使用主题信息来控制左侧引导视图的显示,而GuidedActionsStylist类使用主题信息来控制右侧操作视图的显示。

要自定义步骤的视觉样式(超出主题自定义提供的范围),请对GuidanceStylistGuidedActionsStylist进行子类化,并在GuidedStepSupportFragment.onCreateGuidanceStylist()GuidedStepSupportFragment.onCreateActionsStylist()中返回您的子类。有关您可以在这些子类中自定义的内容的详细信息,请参阅GuidanceStylistGuidedActionsStylist的文档。