前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android Jetpack架构组件(十)之Slices

Android Jetpack架构组件(十)之Slices

原创
作者头像
xiangzhihong
修改2021-01-18 10:23:55
3.7K0
修改2021-01-18 10:23:55
举报
文章被收录于专栏:向治洪

一、Slices简介

Slice 是一种界面模板,可以在 Google 搜索应用中以及 Google 助理中等其他位置显示您应用中的丰富而动态的互动内容。同时,Slice 支持全屏应用体验之外的互动,可以帮助用户更快地执行任务。

目前,Android Jetpack 内置了对 Slice 的支持,并且可以向后一直扩展到 Android 4.4,覆盖约 95% 的 Android 用户。借助Slice,开发者可以根据应用的设计自定义 Slice 的颜色、文字、图像、视频等。

在这里插入图片描述
在这里插入图片描述

同时,我们还可以在使用Slice 包含切换开关和滑块之类的互动控件。

在这里插入图片描述
在这里插入图片描述

二、使用入门

2.1 下载并安装Slice查看器

为了在不实现 SliceView API 的情况下测试 Slice,我们需要下载一个对应版本的 Slice 查看器 。当然,我们也可以下载它的源码,然后自己编译,下载的地址为: Slice 查看器源代码

下载slice-viewer.apk之后,我们在所在的目录中运行以下命令将 Slice 查看器安装到您的设备上。

代码语言:txt
复制
adb install -r -t slice-viewer.apk

2.2 运行Slice查看器

我们可以使用 Android Studio 或者使用命令行启动 Slice 查看器。

2.2.1 使用Android Studio 启动Slice

打开Android项目,然后依次选择 【Run】->【Edit Configurations...】,然后点击左上角的绿色加号并选中【Android App】选型,如下图所示。

在这里插入图片描述
在这里插入图片描述

然后,在名称字段中输入“slice”,从 Module 下拉列表中选择应用模块,从 Launch Options 下的 Launch 下拉列表中,选择 URL并在 URL 字段中输入 slice-<your slice URI>,如下所示。

代码语言:txt
复制
slice-content://com.example.your.sliceuri
在这里插入图片描述
在这里插入图片描述

2.2.2 通过 ADB命令行启动 Slice

首先,在Android Studio 的命令行面板中运行您的应用,命令如下。

代码语言:txt
复制
adb install -t -r <yourapp>.apk

然后,通过运行以下命令来查看您的 Slice。

代码语言:txt
复制
adb shell am start -a android.intent.action.VIEW -d slice-<your slice URI>
//例子
 adb shell am start -a android.intent.action.VIEW -d slice-content://com.example.android.slice.demos/wifi 

然后,就可以在设备上看到Wifi的连接情况,如下图所示。

在这里插入图片描述
在这里插入图片描述

2.2.3 在一个位置集中查看所有 Slice

除了启动单个 Slice 外,我们还可以查看 Slice 的持久性列表。例如,使用搜索栏通过 URI(例如,content://com.example.android.app/hello)手动搜索Slice,每次搜索时相应的 Slice 都会添加到列表中。

在这里插入图片描述
在这里插入图片描述

我们可以滑动 Slice 以将其从列表中移除,也可以点按 Slice 的 URI 可查看仅包含该 Slice 的网页。

2.2.4 修改Slice模式

我们可以在呈现 Slice 应用时修改 SliceView#mode,因此我们需要确保 Slice 在每种模式下均按预期显示,选择页面右上方的菜单图标即可更改模式。

在这里插入图片描述
在这里插入图片描述

2.3 构建Slice

首先,在新建的Android项目的在build.gradle添加如下依赖。

代码语言:txt
复制
def slice_version = "1.1.0-alpha01"
implementation "androidx.slice:slice-core:$slice_version"
implementation "androidx.slice:slice-builders:$slice_version"

需要说明的是,Slice需要最低版本为19,所以需要修改Android项目的minSdkVersion版本。然后,打开Android Studio 项目,右键点击 src 软件包,然后依次选择 【New】--> 【Other】 --> 【Slice Provider】,如下图所示。

在这里插入图片描述
在这里插入图片描述

此时回创建一个扩展 SliceProvider 的类,然后在AndroidManifest.xml 添加所需的提供程序条目,并修改您的 build.gradle 以添加所需的 Slice 依赖项,然后打开AndroidManifest.xml 的修改如下所示。

代码语言:txt
复制
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.app">
    ...
    <application>
        ...
        <provider android:name="MySliceProvider"
            android:authorities="com.example.android.app"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.app.slice.category.SLICE" />
            </intent-filter>
        </provider>
        ...
    </application>

</manifest>

需要说明的是,默认情况下,SliceProvider 模板指向的是 AndroidX 库,如果您的Android项目使用旧版支持库,请修改 build.gradle 文件以指向 com.android.support:slices-builders:(latest version),而不是等效的 AndroidX 库。

事实上,每个 Slice 都有一个关联的 URI。当界面想要显示 Slice 时,它会通过该 URI 向您的应用发送绑定请求,然后应用会通过 onBindSlice 方法处理该请求,并动态构建 Slice,界面随后会根据情况显示 Slice。

MySliceProvider继承于ContentProvider,其APP间数据的传递通过

ContentProvider的方式,应用APP向搜索APP对外提供其对应Slice的Uri,封装成Slice对象通过Parcelable序列化的方式实现APP之间的数据传递。新建类继承SliceProvider,并重写onBindSlice()方法,在该方法里可以编写Slice展示模块中的相关逻辑代码。然后,我们打开onBindSlice 方法,代码如下。

代码语言:txt
复制
@Override
public Slice onBindSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    SliceAction activityAction = createActivityAction();
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
    // Create parent ListBuilder.
    if ("/hello".equals(sliceUri.getPath())) {
        listBuilder.addRow(new ListBuilder.RowBuilder()
                .setTitle("Hello World")
                .setPrimaryAction(activityAction)
        );
    } else {
        listBuilder.addRow(new ListBuilder.RowBuilder()
                .setTitle("URI not recognized")
                .setPrimaryAction(activityAction)
        );
    }
    return listBuilder.build();
}

然后,使用您在上述“Slice 查看器”部分中创建的 slice 运行配置,传入 Hello World Slice 的 Slice URI(例如,slice-content://com.android.example.slicesample/hello),以在 Slice 查看器中查看该 Slice,命令如下。

代码语言:txt
复制
adb shell am start -a android.intent.action.VIEW -d slice-content://com.xzh.slice/hello  

运行效果如下图所示。

在这里插入图片描述
在这里插入图片描述

2.4 互动 Slice

与通知类似,如需处理 Slice 中的点按操作,我们可以附加在用户互动时触发的 PendingIntent 对象,比如点击Slice模块打开宿主App,我们打开MySliceProvider,然后在onBindSlice()方法中调用如下代码。

代码语言:txt
复制
public Slice createSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    SliceAction activityAction = createActivityAction();
    return new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .addRow(new ListBuilder.RowBuilder()
                    .setTitle("Perform action in app.")
                    .setPrimaryAction(activityAction)
            ).build();
}

public SliceAction createActivityAction() {
    if (getContext() == null) {
        return null;
    }
    return SliceAction.create(
            PendingIntent.getActivity(
                    getContext(),
                    0,
                    new Intent(getContext(), MainActivity.class),
                    0
            ),
            IconCompat.createWithResource(getContext(), R.drawable.ic_home),
            ListBuilder.ICON_IMAGE,
            "Enter app"
    );
}

完整的代码地址为: 互动 Slice。重新运行Android项目,效果如下图所示。

在这里插入图片描述
在这里插入图片描述

当然,Slice 还支持在发送到应用的 intent 中包含状态的其他输入类型,如切换开关,代码如下。

代码语言:txt
复制
public Slice createBrightnessSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    SliceAction toggleAction = SliceAction.createToggle(
            createToggleIntent(),
            "Toggle adaptive brightness",
            true
    );
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .addRow(new ListBuilder.RowBuilder()
                    .setTitle("Adaptive brightness")
                    .setSubtitle("Optimizes brightness for available light.")
                    .setPrimaryAction(toggleAction)
            ).addInputRange(new ListBuilder.InputRangeBuilder()
                    .setInputAction(brightnessPendingIntent)
                    .setMax(100)
                    .setValue(45)
            );
    return listBuilder.build();
}

public PendingIntent createToggleIntent() {
    Intent intent = new Intent(getContext(), MyBroadcastReceiver.class);
    return PendingIntent.getBroadcast(getContext(), 0, intent, 0);
}

然后,我们在自定义一个BroadcastReceiver广播通知接收器,代码如下。

代码语言:txt
复制
public class MyBroadcastReceiver extends BroadcastReceiver {

    public static String EXTRA_MESSAGE = "message";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.hasExtra(EXTRA_TOGGLE_STATE)) {
            Toast.makeText(context, "Toggled:  " + intent.getBooleanExtra(
                    EXTRA_TOGGLE_STATE, false),
                    Toast.LENGTH_LONG).show();
        }
    }
}

然后,我们还需要在AndroidManifest.xml中注册MyBroadcastReceiver。最后,重新运行Android项目,

在这里插入图片描述
在这里插入图片描述

2.5 动态 Slice

在使用Slice时,还可以包含动态内容。在以下示例中,Slice 的内容中包括接收的广播数量。

代码语言:txt
复制
public Slice createDynamicSlice(Uri sliceUri) {
    if (getContext() == null || sliceUri.getPath() == null) {
        return null;
    }
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
    switch (sliceUri.getPath()) {
        case "/count":
            SliceAction toastAndIncrementAction = SliceAction.create(
                    createToastAndIncrementIntent("Item clicked."),
                    actionIcon,
                    ListBuilder.ICON_IMAGE,
                    "Increment."
            );
            listBuilder.addRow(
                    new ListBuilder.RowBuilder()
                            .setPrimaryAction(toastAndIncrementAction)
                            .setTitle("Count: " + MyBroadcastReceiver.sReceivedCount)
                            .setSubtitle("Click me")
            );
            break;
        default:
            listBuilder.addRow(
                    new ListBuilder.RowBuilder()
                            .setPrimaryAction(createActivityAction())
                            .setTitle("URI not found.")
            );
            break;
    }
    return listBuilder.build();
}

public PendingIntent createToastAndIncrementIntent(String s) {
    Intent intent = new Intent(getContext(), MyBroadcastReceiver.class)
            .putExtra(MyBroadcastReceiver.EXTRA_MESSAGE, s);
    return PendingIntent.getBroadcast(getContext(), 0, intent, 0);
}

在此示例中,虽然显示了计数,但它不会自行更新。我们可以修改广播接收器,以使用 ContentResolver#notifyChange 来通知系统发生了更改,代码如下。

代码语言:txt
复制
public class MyBroadcastReceiver extends BroadcastReceiver {

    public static int sReceivedCount = 0;
    public static String EXTRA_MESSAGE = "message";

    private static Uri sliceUri = Uri.parse("content://com.xzh.slice/count");

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.hasExtra(EXTRA_TOGGLE_STATE)) {
            Toast.makeText(context, "Toggled:  " + intent.getBooleanExtra(
                    EXTRA_TOGGLE_STATE, false),
                    Toast.LENGTH_LONG).show();
            sReceivedCount++;
            context.getContentResolver().notifyChange(sliceUri, null);
        }
    }
}

然后,重新运行Android项目,并在命令行运行如下命令。

代码语言:txt
复制
 adb shell am start -a android.intent.action.VIEW -d slice-content://com.xzh.slice/count
在这里插入图片描述
在这里插入图片描述

本小节涉及的代码Slice源码

三、 Slice模板

3.1 定义 Slice 模板

Slice是通过ListBuilder类来创建的,在ListBuilder中,我们可以添加不同类型的行模块在应用中进行展示。

3.1.1 SliceAction

Slice 模板的最基本元素是 SliceAction,SliceAction 包含一个标签以及一个 PendingIntent,SliceAction可以是以下某一项。

  • 图标按钮
  • 默认切换开关
  • 自定义切换开关

SliceAction 由模板构建器调用,我们可以为 SliceAction 定义一种图片模式,该模式决定了如何为操作呈现图片,图片模式的常量如下。

  • ICON_IMAGE:超小尺寸,可着色
  • SMALL_IMAGE:小尺寸,不可着色
  • LARGE_IMAGE:最大尺寸,不可着色

3.1.2 HeaderBuilder

HeaderBuilder 主要为模板设置标头,标头可以支持以下几项:

  • 标题
  • 副标题
  • 摘要副标题
  • 主要操作

效果如下图。

在这里插入图片描述
在这里插入图片描述

本小节涉及的完整代码为Slice模版

例如,下面是一个包含标头的简单列表 Slice,代码如下。

代码语言:txt
复制
public Slice createSliceWithHeader(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }

    // Construct the parent.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .setAccentColor(0xff0F9D58) // Specify color for tinting icons.
            .setHeader( // Create the header and add to slice.
                    new HeaderBuilder()
                            .setTitle("Get a ride")
                            .setSubtitle("Ride in 4 min.")
                            .setSummary("Work in 1 hour 45 min | Home in 12 min.")
            ).addRow(new RowBuilder() // Add a row.
                    .setPrimaryAction(
                            createActivityAction()) // A slice always needs a SliceAction.
                    .setTitle("Home")
                    .setSubtitle("12 miles | 12 min | $9.00")
                    .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_home),
                            SliceHints.ICON_IMAGE)
            ); // Add more rows if needed...
    return listBuilder.build();
}

然后,在onBindSlice()方法中调用上面的createSliceWithHeader()方法即可,重新运行Android应用,并执行如下的命令。

代码语言:txt
复制
 adb shell am start -a android.intent.action.VIEW -d slice-content://com.xzh.slice/hello

运行效果如下图所示。

在这里插入图片描述
在这里插入图片描述

当然,我们也可以给Slice标头显示 SliceAction,如下所示。

代码语言:txt
复制
public Slice createSliceWithActionInHeader(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Construct our slice actions.
    SliceAction noteAction = SliceAction.create(takeNoteIntent,
            IconCompat.createWithResource(getContext(), R.drawable.ic_pencil),
            ListBuilder.ICON_IMAGE, "Take note");

    SliceAction voiceNoteAction = SliceAction.create(voiceNoteIntent,
            IconCompat.createWithResource(getContext(), R.drawable.ic_mic),
            ListBuilder.ICON_IMAGE,
            "Take voice note");

    SliceAction cameraNoteAction = SliceAction.create(cameraNoteIntent,
            IconCompat.createWithResource(getContext(), R.drawable.ic_camera),
            ListBuilder.ICON_IMAGE,
            "Create photo note");

    // Construct the list.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .setAccentColor(0xfff4b400) // Specify color for tinting icons
            .setHeader(new HeaderBuilder() // Construct the header.
                    .setTitle("Create new note")
                    .setSubtitle("Easily done with this note taking app")
            )
            .addRow(new RowBuilder()
                    .setTitle("Enter app")
                    .setPrimaryAction(createActivityAction())
            )
            // Add the actions to the ListBuilder.
            .addAction(noteAction)
            .addAction(voiceNoteAction)
            .addAction(cameraNoteAction);
    return listBuilder.build();
}
在这里插入图片描述
在这里插入图片描述

3.1.3 RowBuilder

除此之外,我们可以使用 RowBuilder 构造一行内容,行可以支持以下任意一项。

  • 标题
  • 副标题
  • 起始项:SliceAction、图标或时间戳
  • 结束项:SliceAction、图标或时间戳
  • 主要操作

并且,RowBuilder还支持多种方式组合行内容,但须遵守以下限制。

  • 起始项不能显示在 Slice 的第一行中
  • 结束项不能同时包含 SliceAction 对象和 Icon 对象
  • 一行只能包含一个时间戳

例如,下面是一个行包含一项主要操作和一个默认切换开关的例子,代码如下。

代码语言:txt
复制
public Slice createActionWithActionInRow(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Primary action - open wifi settings.
    SliceAction primaryAction = SliceAction.create(wifiSettingsPendingIntent,
            IconCompat.createWithResource(getContext(), R.drawable.ic_wifi),
            ListBuilder.ICON_IMAGE,
            "Wi-Fi Settings"
    );

    // Toggle action - toggle wifi.
    SliceAction toggleAction = SliceAction.createToggle(wifiTogglePendingIntent,
            "Toggle Wi-Fi", isConnected /* isChecked */);

    // Create the parent builder.
    ListBuilder listBuilder = new ListBuilder(getContext(), wifiUri, ListBuilder.INFINITY)
            // Specify color for tinting icons / controls.
            .setAccentColor(0xff4285f4)
            // Create and add a row.
            .addRow(new RowBuilder()
                    .setTitle("Wi-Fi")
                    .setPrimaryAction(primaryAction)
                    .addEndItem(toggleAction));
    // Build the slice.
    return listBuilder.build();
}

运行效果如下。

在这里插入图片描述
在这里插入图片描述

3.1.4 GridBuilder

当然,我们也可以使用 GridBuilder 构造内容网格,网格单元格是使用 CellBuilder 构造的。一个单元格最多可以支持两行文字和一张图片。

代码语言:txt
复制
public Slice createSliceWithGridRow(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Create the parent builder.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .setHeader(
                    // Create the header.
                    new HeaderBuilder()
                            .setTitle("Famous restaurants")
                            .setPrimaryAction(SliceAction
                                    .create(pendingIntent, icon, ListBuilder.ICON_IMAGE,
                                            "Famous restaurants"))
            )
            // Add a grid row to the list.
            .addGridRow(new GridRowBuilder()
                    // Add cells to the grid row.
                    .addCell(new CellBuilder()
                            .addImage(image1, ListBuilder.LARGE_IMAGE)
                            .addTitleText("Top Restaurant")
                            .addText("0.3 mil")
                            .setContentIntent(intent1)
                    ).addCell(new CellBuilder()
                            .addImage(image2, ListBuilder.LARGE_IMAGE)
                            .addTitleText("Fast and Casual")
                            .addText("0.5 mil")
                            .setContentIntent(intent2)
                    )
                    .addCell(new CellBuilder()
                            .addImage(image3, ListBuilder.LARGE_IMAGE)
                            .addTitleText("Casual Diner")
                            .addText("0.9 mi")
                            .setContentIntent(intent3))
                    .addCell(new CellBuilder()
                            .addImage(image4, ListBuilder.LARGE_IMAGE)
                            .addTitleText("Ramen Spot")
                            .addText("1.2 mi")
                            .setContentIntent(intent4))
                    // Every slice needs a primary action.
                    .setPrimaryAction(createActivityAction())
            );
    return listBuilder.build();
}
在这里插入图片描述
在这里插入图片描述

3.1.5 RangeBuilder

RangeBuilder是一个用来创建包含进度条或输入范围(如滑块)的行。例如,以下示例演示了如何使用 InputRangeBuilder 构建包含音量滑块的 Slice。

代码语言:txt
复制
public Slice createSliceWithRange(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Construct the parent.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .addRow(new RowBuilder() // Every slice needs a row.
                    .setTitle("Enter app")
                     // Every slice needs a primary action.
                    .setPrimaryAction(createActivityAction())
            )
            .addInputRange(new InputRangeBuilder() // Create the input row.
                    .setTitle("Ring Volume")
                    .setInputAction(volumeChangedPendingIntent)
                    .setMax(100)
                    .setValue(30)
            );
    return listBuilder.build();
}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 延迟内容

当我们使用 SliceProvider.onBindSlice() 返回 Slice时可能回出现耗时调用问题,出现的现象是闪烁。如果您的 Slice 内容无法快速加载,我们可以使用占位符内容构造 Slice,同时在构建器中注明内容正在加载。一旦内容可供显示,请使用 Slice URI 调用 getContentResolver().notifyChange(sliceUri, null),如果再次调用 SliceProvider.onBindSlice(),那么可以使用新内容重新构造 Slice。

例如,下面是“骑车上班”的例子,上班距离是动态确定的,可能不会立即显示,那么在内容加载时就显示 null ,代码如下。

代码语言:txt
复制
public Slice createSliceShowingLoading(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Construct the parent.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            // Construct the row.
            .addRow(new RowBuilder()
                    .setPrimaryAction(createActivityAction())
                    .setTitle("Ride to work")
                    // We’re waiting to load the time to work so indicate that on the slice by
                    // setting the subtitle with the overloaded method and indicate true.
                    .setSubtitle(null, true)
                    .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_work),
                            ListBuilder.ICON_IMAGE)
            );
    return listBuilder.build();
}

private SliceAction createActivityAction() {
    return SliceAction.create(
            PendingIntent.getActivity(
                    getContext(),
                    0,
                    new Intent(getContext(), MainActivity.class),
                    0
            ),
            IconCompat.createWithResource(getContext(), R.drawable.ic_home),
            ListBuilder.ICON_IMAGE,
            "Enter app"
    );
}
在这里插入图片描述
在这里插入图片描述

3.3 处理 Slice 中停用滚动的情况

Slice 模板的呈现界面可能不支持在模板内滚动。在这种情况下,某些内容可能不会显示,举个例子,假设一个 Slice 中显示了一个 Wi-Fi 网络列表,效果如下。

在这里插入图片描述
在这里插入图片描述

如果这个 Wi-Fi 列表较长,且停用了滚动操作,那么我们可以添加查看更多按钮,以确保用户可以看到列表中的所有项目。

代码语言:txt
复制
public Slice seeMoreActionSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
    // ...
    listBuilder.setSeeMoreAction(seeAllNetworksPendingIntent);
    // ...
    return listBuilder.build();
}

运行效果如下图所示。

在这里插入图片描述
在这里插入图片描述

3.4 组合模板

除此之外,Slice可以将多种行类型组合在一起,创建内容丰富的动态 Slice。例如,Slice 可以包含标头行、带有单张图片的网格以及带有两个文字单元格的网格。

在这里插入图片描述
在这里插入图片描述

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Slices简介
  • 二、使用入门
    • 2.1 下载并安装Slice查看器
      • 2.2 运行Slice查看器
        • 2.2.1 使用Android Studio 启动Slice
        • 2.2.2 通过 ADB命令行启动 Slice
        • 2.2.3 在一个位置集中查看所有 Slice
        • 2.2.4 修改Slice模式
      • 2.3 构建Slice
        • 2.4 互动 Slice
          • 2.5 动态 Slice
          • 三、 Slice模板
            • 3.1 定义 Slice 模板
              • 3.1.1 SliceAction
              • 3.1.2 HeaderBuilder
              • 3.1.3 RowBuilder
              • 3.1.4 GridBuilder
              • 3.1.5 RangeBuilder
            • 3.2 延迟内容
              • 3.3 处理 Slice 中停用滚动的情况
                • 3.4 组合模板
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档