• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

编写您的第一个Android Slice并保持用户参与度

艰苦的工作并没有结束,因为您的应用在 Google Play 商店中获得了大量下载和正面评价。您的典型移动用户在他们的设备上安装了数十个应用程序,并且随着新应用程序的不断发布,您需要努力保持受众的兴趣!

让用户回访您的应用对于创建稳定、忠诚的用户群至关重要。另外,如果你已经通过你的应用获利,那么人们在你的应用中花费的时间会直接影响你赚多少钱——把每一秒想象成另一个展示广告或诱使用户大肆挥霍的机会。 - 应用购买!

在今年的 I/O 上,Google 推出了slices,这是一项新功能,承诺通过在最需要用户的时候将应用的功能和内容呈现在他们面前,从而将用户带回您的应用。 

随着切片逐渐成为留住观众的重要工具,现在正是亲身体验这一新兴 android 功能的最佳时机。在本文结束时,您将创建一系列切片,从在轻按时启动 Activity 的简单切片到由图标、图像、网格和多个SliceActions. 

切片:用户享受您的应用程序的更多方式 

与小部件类似,切片是出现在应用程序上下文之外的内容片段,可提高应用程序的可见性并为您提供更多吸引受众的机会。 

切片有可能大大提高您的应用程序的知名度,谷歌承诺在许多 Android 用户花费大量时间的领域增加对切片的支持,包括谷歌搜索和谷歌助手。由于它们是 Android Jetpack 的一部分,因此切片与 Android 4.4 及更高版本兼容,这意味着您的切片有可能覆盖 95% 的所有 Android 用户。 

所以切片有很多东西可以提供——但是它们是如何工作的呢? 

目前,如果您在 Google 应用程序中执行搜索,那么 Google 可能会建议安装在您设备上的相关应用程序。例如,如果您安装了 Facebook 移动版,则键入facebook 将显示一个指向 Facebook 应用程序的直接链接。

编写您的第一个Android Slice并保持用户参与度  第1张


Slices 通过关注用户可能希望在他们已经安装的应用程序中执行的特定任务,使这个应用程序链接更进一步。

让我们看一个例子:假设您安装了一个 Book A Hotel 应用程序,可以让您搜索酒店并预订房间。当您在 Google 中输入London hotels时,您会看到通常的搜索结果,以及 Book A Hotel 应用程序中的一部分。此切片推荐伦敦的一家酒店,并以按钮的形式显示酒店名称和地址等信息,SliceAction您可以直接从切片的用户界面 (UI) 预订房间。 

对于用户而言,此切片提供了对他们在特定时刻所需的信息和功能的轻松访问。对于开发人员来说,这个片段使他们能够在他们最有可能成功重新吸引他们的时候将他们的应用程序呈现在用户面前。

如何创建我的第一个切片? 

让我们从创建一个简单的切片开始,点击它时将启动我们应用程序的MainActivity.

这种简单的技术可以直接从切片的 UI 启动任何任务。在我们的 Book A Hotel 示例中,我们可以将按钮链接到相关应用程序的BookRoomactivity,这将是一种简单但有效的方法,可以减少用户为完成此特定任务而必须导航的屏幕数量。 

首先,创建一个新的 Android 项目。您可以使用任何您想要的设置,但请确保在出现提示时选中包含 kotlin 支持复选框。 

创建项目后,打开它的 build.gradle 文件并添加slice-core和slice-builder依赖项:

dependencies {

   implementation 'androidx.appcompat:appcompat:1.0.0-alpha3'

   implementation 'androidx.slice:slice-core:1.0.0-alpha3'

   implementation 'androidx.slice:slice-builders:1.0.0-alpha3'

   implementation 'androidx.constraintlayout:constraintlayout:1.1.0'

   implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

}

使用切片提供程序在 Google 搜索中显示您的应用内容

接下来,我们需要创建一个切片提供程序,它是负责在应用程序上下文之外显示应用程序内容的组件。 

您可以使用 Android Studio 的切片提供程序模板创建切片提供程序:

  •  从 Android Studio 工具栏中 选择New > Other > Slice Provider 。

  • 输入名称MySliceProvider。

  • 将源语言设置为Kotlin。

  • 单击完成。

  • 打开MySliceProvider类,您应该会看到以下自动生成的代码: 

  • import android.content.ContentResolver

  • import android.content.Intent

  • import android.net.Uri

  • import androidx.slice.Slice

  • import androidx.slice.SliceProvider

  • import androidx.slice.builders.ListBuilder

  •  

  • class MySliceProvider : SliceProvider() {

  •      

  •   override fun onCreateSliceProvider(): Boolean {

  •       return true

  •   }

  •  

  •   override fun onMapintentToUri(intent: Intent?): Uri {

  •  

  •       var uriBuilder: Uri.Builder = Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)

  •       if (intent == null) return uriBuilder.build()

  •       val data = intent.data

  •       if (data != null && data.path != null) {

  •           val path = data.path.replace("/", "")

  •           uriBuilder = uriBuilder.path(path)

  •       }

  •       val context = context

  •       if (context != null) {

  •           uriBuilder = uriBuilder.authority(context.getPackageName())

  •       }

  •       return uriBuilder.build()

  •   }

  •  

  • //Construct the slice//

  •  

  •   override fun onBindSlice(sliceUri: Uri): Slice? {

  •       val context = getContext() ?: return null

  •       return if (sliceUri.path == "/") {

  •  

  • //Customise the Slice//

  •  

  •           ListBuilder(context, sliceUri)

  •                   .addRow { it.setTitle("URI found.") }

  •                   .build()

  •       } else {

  •            

  •           ListBuilder(context, sliceUri)

  •                   .addRow { it.setTitle("URI not found.") }

  •                   .build()

  •       }

  •   }

  •  

  • //Subscribe to a data source, if necessary//

  •  

  •   override fun onSlicePinned(sliceUri: Uri?) {

  •  

  •   }

  •  

  • //Avoid memory leaks by unsubscribing from the data source and removing any observers//

  •  

  •   override fun onSliceUnpinned(sliceUri: Uri?) {

  •   }

  • }

如果您使用New > Other > Slice Provider创建切片提供程序,那么 Android Studio 也会将必要的提供程序添加到您的清单中: 

<provider

       android:name=".MySliceProvider"

       android:authorities="com.jessicathornsby.kotlinslices"

       android:exported="true">

       <intent-filter>

           <action android:name="android.intent.action.VIEW" />

            

           <category android:name="android.app.slice.category.SLICE" />

 

           <data

               android:host="jessicathornsby.com"

               android:pathPrefix="/"

               android:scheme="http" />

       </intent-filter>

   </provider>

</application>

此条目可确保您的切片可以被其他应用程序发现。  

您的 Gradle 项目同步失败了吗?

到目前为止,我们只使用了 Android Studio 自动生成的代码,但您的项目可能已经拒绝编译! 

错误、缺少的功能和全方位的奇怪行为只是使用早期版本的乐趣的一部分。在撰写本文时,生成切片提供程序有时会莫名其妙地将一组新的依赖项添加到项目的build.gradle文件中。 



implementation 'androidx.slice:slices-core:1.0.0-alpha1'<font></font>

implementation 'androidx.slice:slices-builders:1.0.0-alpha1'

这些依赖不仅是不必要的——它们是错误的。虽然很容易错过,但比较一下: 


implementation 'androidx.slice:slices-core:1.0.0-alpha3'

正确:


implementation 'androidx.slice:slice-core:1.0.0-alpha1'

单个s可能意味着正常运行的应用程序和拒绝编译的项目之间的区别。这个错误可能会在切片正式发布之前得到解决,但如果 Android Studio 开始抱怨未解决的依赖项,请检查您的build.gradle文件以查看您的项目中是否发生了这种情况。 

构建切片:URI SliceActions、 和切片布局

要将切片提供者的样板代码转换为功能切片,我们需要进行一些更改:

1.定义一个URI

每个切片都有一个唯一的 URI,切片提供者的工作是提供此 URI 和相应切片之间的映射。 

能够显示切片的应用程序称为主机应用程序。每次主机需要显示切片时,它都会向切片提供者发送一个绑定请求,其中包含它正在查找的切片的 URI。然后,您的切片提供者将检查 URI 并返回适当的切片。

在以下代码段中,该onBindSlice方法检查/myURI路径并返回显示 Hello World消息的切片。

class MySliceProvider : SliceProvider() {<font></font>

    <font></font>

   override fun onCreateSliceProvider(): Boolean {<font></font>

       return true<font></font>

   }<font></font>

<font></font>

   override fun onBindSlice(sliceUri: Uri): Slice? {<font></font>

       return if (sliceUri.path == "/myURI") {<font></font>

           ListBuilder(context, sliceUri, ListBuilder.INFINITY)<font></font>

                   .addRow { it.setTitle("Hello World") }<font></font>

                   .build()<font></font>

       } else {<font></font>

...<font></font>

...<font></font>

...<font></font>

       }<font></font>

   }<font></font>

}

2.让你的切片互动 

虽然您可以创建一个仅显示一些信息的切片,但如果您希望切片具有交互性,则需要创建一个或多个SliceActions. 

一个SliceAction可以由标题、图标和PendingIntent. 您还可以标记SliceActions为主要操作,只要用户点击该切片行上的任意位置,就会触发该操作。 

3. 构建 Slice 的 UI  

您可以通过实现 a 来定义切片的布局ListBuilder,添加一行,然后将项目添加到该行。例如,这里我使用ListBuilderandaddRow创建一个包含标题和副标题的切片: 

import android.net.Uri<font></font>

import androidx.slice.Slice<font></font>

import androidx.slice.SliceProvider<font></font>

import androidx.slice.builders.ListBuilder<font></font>

import androidx.slice.builders.ListBuilder.INFINITY<font></font>

<font></font>

class MySliceProvider : SliceProvider() {<font></font>

<font></font>

   override fun onCreateSliceProvider(): Boolean {<font></font>

       <font></font>

       return true<font></font>

   }<font></font>

<font></font>

   override fun onBindSlice(sliceUri: Uri): Slice? {<font></font>

       val path = sliceUri.path<font></font>

       when (path) {<font></font>

           "/launchMainActivity" -> return createSlice(sliceUri)<font></font>

       }<font></font>

       return null<font></font>

   }<font></font>

<font></font>

   fun createSlice(sliceUri: Uri): Slice {<font></font>

       return ListBuilder(context, sliceUri, INFINITY)<font></font>

               .addRow {<font></font>

                   it.apply {<font></font>

                       setTitle("This is a title")<font></font>

                       setSubtitle("This is a subtitle")<font></font>

                       <font></font>

                   }<font></font>

               }.build()<font></font>

   }<font></font>

  <font></font>

}

您可以在同一行中混合显示不同的内容类型,例如文本、操作和图标。

构建您的第一个功能齐全的 Android Slice 

现在让我们将所有这些应用到我们的项目中,并创建一个切片,在点击时启动我们的应用程序MainActivity。 

打开MySliceProvider类,并添加以下内容: 

import android.app.PendingIntent<font></font>

import android.content.Intent<font></font>

import android.net.Uri<font></font>

import androidx.core.graphics.drawable.IconCompat<font></font>

import androidx.slice.Slice<font></font>

import androidx.slice.SliceProvider<font></font>

import androidx.slice.builders.ListBuilder<font></font>

import androidx.slice.builders.SliceAction<font></font>

<font></font>

//Extend from SliceProvider//<font></font>

<font></font>

class MySliceProvider : SliceProvider() {<font></font>

<font></font>

//Initialise your slice provider//<font></font>

<font></font>

  override fun onCreateSliceProvider(): Boolean {<font></font>

      return true<font></font>

  }<font></font>

<font></font>

//Build the slice//<font></font>

<font></font>

  override fun onBindSlice(sliceUri: Uri): Slice? {<font></font>

<font></font>

//Check the URI path//<font></font>

<font></font>

      val path = sliceUri.path<font></font>

      when (path) {<font></font>

<font></font>

//Define the slice’s URI; I’m using ‘launchMainActivity’//<font></font>

<font></font>

          "/launchMainActivity" -> return createSlice(sliceUri)<font></font>

      }<font></font>

      return null<font></font>

  }<font></font>

<font></font>

  fun createSlice(sliceUri: Uri): Slice {<font></font>

      val activityAction = createActivityAction()<font></font>

<font></font>

//Create the ListBuilder, which we’ll use to add rows to our slice//<font></font>

<font></font>

      val listBuilder = ListBuilder(context!!, sliceUri, ListBuilder.INFINITY)<font></font>

<font></font>

//Construct the rows using RowBuilder//<font></font>

<font></font>

      val rowBuilder = ListBuilder.RowBuilder(listBuilder)<font></font>

<font></font>

//Set the title text//<font></font>

<font></font>

              .setTitle("Open MainActivity.")<font></font>

<font></font>

//Set the row’s primary action//<font></font>

<font></font>

              .setPrimaryAction(activityAction)<font></font>

<font></font>

//Add the row to the ListBuilder//<font></font>

<font></font>

      listBuilder.addRow(rowBuilder)<font></font>

<font></font>

//Build the list//<font></font>

<font></font>

      return listBuilder.build()<font></font>

<font></font>

  }<font></font>

<font></font>

  fun createActivityAction(): SliceAction {<font></font>

      val intent = Intent(context, MainActivity::class.java)<font></font>

      return SliceAction(PendingIntent.getActivity(context, 0, intent, 0),<font></font>

              IconCompat.createWithResource(context!!, R.drawable.ic_home),<font></font>

              "Open MainActivity")<font></font>

  }<font></font>

<font></font>

}

测试切片:安装切片查看器 

如果您要对切片进行测试,那么您至少需要一个能够显示切片的应用程序。 

据报道,Slices 将于今年晚些时候在 Google 搜索中首次亮相,但在撰写本文时,该功能尚未推出。目前,测试切片的唯一方法是安装 Google 的切片查看器应用程序,该应用程序旨在模拟切片最终将如何出现在 Google 搜索中。

在 Android 虚拟设备 (AVD) 上安装 Slice Viewer:

  • 下载 Google 的切片查看器应用程序。

  • 确保您的 AVD 已启动并正在运行。

  • 找到 Slice Viewer APK 文件,并将其拖放到您的 AVD 上。

要在物理智能手机或平板电脑上安装 Slice Viewer: 

  • 下载切片查看器。

  • 确保您的智能手机或平板电脑已连接到您的开发机器。

  • 将 Slice Viewer APK 移动到您计算机的Android/sdk/platform-tools文件夹中。

  • 打开命令提示符 (Windows) 或终端 (Mac) 窗口。 

  • 更改目录 ( cd),使命令提示符或终端指向您的 Android/sdk/platform-tools 文件夹——例如,这是我的命令:

1

cd /Users/jessicathornsby/Library/Android/sdk/platform-tools

  • 通过按键盘上的Enter键运行命令。

  • 使用adb install命令将 APK 推送到您的 Android 设备:

1

./adb install slice-viewer.apk

创建 URI 运行配置 

接下来,您需要创建一个运行配置,将切片的唯一 URI 传递给您的 AVD 或 Android 设备。 

  • 从 Android Studio 工具栏中选择Run > Edit Configurations...。

  • 单击+按钮,然后选择Android App。

编写您的第一个Android Slice并保持用户参与度  第2张
  • 为您的运行配置命名。我正在使用sliceConfig。 

  • 打开Module下拉菜单,然后选择app。

  • 打开Launch下拉菜单,然后选择URL。

  • 输入切片的 URL,格式为 slice-content://package-name/slice-URL。例如,我的 slice 的 URL 是:slice-content://com.jessicathornsby.kotlinslices/launchMainActivity。

  • 单击确定。

  • 从 Android Studio 工具栏中选择Run > Run sliceConfig,然后选择您的 Android 设备。

切片查看器第一次尝试显示切片时,它会请求访问切片唯一 URI 的权限。点击允许并导航权限对话框,您的切片应出现在屏幕上。

编写您的第一个Android Slice并保持用户参与度  第3张

要与 交互SliceAction,请单击Open MainActivity按钮,切片将通过启动应用程序的MainActivity. 

从切片中获得更多:添加第二个SliceAction 

SliceAction当您可以拥有多个 时,为什么要将自己限制在一个SliceActions?在本节中,我们将实现两个SliceActions,其中每个动作启动一个不同的Activity. 我还将介绍一些新的 UI 元素,为我们的切片 添加一个字幕和一些最终项目。

创建第二个活动

让我们摆脱设置并创建第二Activity个SliceAction可以链接到的第二个。 

首先,从 Android Studio 工具栏中选择New > Kotlin File / Class 。在新文件对话框中,打开Kind下拉菜单并选择Class。命名这个类SecondActivity,然后单击“确定” 。 

现在打开您的SecondActivity 课程并添加以下内容:

import androidx.appcompat.app.AppCompatActivity<font></font>

import android.os.Bundle<font></font>

<font></font>

class SecondActivity : AppCompatActivity() {<font></font>

   override fun onCreate(savedInstanceState: Bundle?) {<font></font>

       super.onCreate(savedInstanceState)<font></font>

       setContentView(R.layout.activity_second)<font></font>

   }<font></font>

}

接下来,从 Android Studio 工具栏中选择New > Android Resource File 。在随后的窗口中,打开Resource type下拉菜单,然后选择 Layout。命名此文件activity_second,然后单击“确定” 。 

现在打开这个布局文件并添加以下代码:


<?xml version="1.0" encoding="utf-8"?><font></font>

https://schemas.android.com/apk/res/android"<font></font>

   xmlns:app="http://schemas.android.com/apk/res-auto"<font></font>

   xmlns:tools="http://schemas.android.com/tools"<font></font>

   android:layout_width="match_parent"<font></font>

   android:layout_height="match_parent"<font></font>

   tools:context=".MainActivity"><font></font>

<font></font>

   <TextView<font></font>

       android:layout_width="wrap_content"<font></font>

       android:layout_height="wrap_content"<font></font>

       android:text="Second Activity"<font></font>

       app:layout_constraintBottom_toBottomOf="parent"<font></font>

       app:layout_constraintLeft_toLeftOf="parent"<font></font>

       app:layout_constraintRight_toRightOf="parent"<font></font>

       app:layout_constraintTop_toTopOf="parent" /><font></font>

<font></font>

</androidx.constraintlayout.widget.ConstraintLayout>

打开项目的清单,并声明 SecondActivity:


<activity android:name=".SecondActivity">

构建更复杂的 UI:分割最终项目 

结束项可以是时间戳、图像或SliceAction,但顾名思义,它们总是出现在一行的末尾。您可以将多个最终项目添加到单行,但根据可用空间的不同,不能保证所有最终项目都会显示给用户。 

我们将创建我们的SliceActionsas 图标,因此您需要在项目中添加两个新的可绘制对象:

  • 从 Android Studio 工具栏中选择New > Image Asset 。

  • 单击小剪贴画按钮(默认情况下会显示 Android 的图片)。

  • 选择要用于Launch MainActivity最终项目的图标。我正在使用主页图标。

  • 将此图标命名为ic_home,然后单击Next。

  • 阅读屏幕上的信息,如果您愿意继续,请单击完成。

重复上述步骤,为您的Launch SecondActivity切片操作创建一个图标。对于我的第二个最终项目,我使用了通话图标并将其命名为ic_call。

创建第二个 SliceAction

我们现在准备SliceAction在MySliceProvider类中添加第二个: 

import android.app.PendingIntent<font></font>

import android.content.Intent<font></font>

import android.net.Uri<font></font>

import androidx.core.graphics.drawable.IconCompat<font></font>

import androidx.slice.Slice<font></font>

import androidx.slice.SliceProvider<font></font>

import androidx.slice.builders.ListBuilder<font></font>

import androidx.slice.builders.SliceAction<font></font>

<font></font>

class MySliceProvider : SliceProvider() {<font></font>

    <font></font>

  override fun onCreateSliceProvider(): Boolean {<font></font>

      return true<font></font>

  }<font></font>

<font></font>

  override fun onBindSlice(sliceUri: Uri): Slice? {<font></font>

      val path = sliceUri.path<font></font>

      when (path) {<font></font>

          "/launchMainActivity" -> return createSlice(sliceUri)<font></font>

      }<font></font>

      return null<font></font>

  }<font></font>

<font></font>

  fun createSlice(sliceUri: Uri): Slice {<font></font>

      val activityAction = createActivityAction()<font></font>

      IconCompat.createWithResource(context!!, R.drawable.ic_home).toIcon()<font></font>

      val activityAction2 = createSecondActivityAction()<font></font>

      IconCompat.createWithResource(context!!, R.drawable.ic_call).toIcon()<font></font>

<font></font>

//Construct the parent builder//<font></font>

<font></font>

          val listBuilder = ListBuilder(context!!, sliceUri)<font></font>

<font></font>

//Construct the builder for the row//<font></font>

<font></font>

          val myRow = ListBuilder.RowBuilder(listBuilder)<font></font>

                  .setTitle("Launch MainActivity.")<font></font>

                  .setSubtitle("This is a subtitle")<font></font>

<font></font>

//Add the actions that we'll be using as end items//<font></font>

<font></font>

          myRow.addEndItem(activityAction)<font></font>

          myRow.addEndItem(activityAction2)<font></font>

<font></font>

 //Add the row to the parent builder//<font></font>

<font></font>

          listBuilder.addRow(myRow)<font></font>

<font></font>

//Build the slice//<font></font>

<font></font>

          return listBuilder.build()<font></font>

      }<font></font>

<font></font>

  fun createActivityAction(): SliceAction {<font></font>

      val intent = Intent(context, MainActivity::class.java)<font></font>

              return SliceAction(PendingIntent.getActivity(context, 0, intent, 0),<font></font>

                      IconCompat.createWithResource(context!!, R.drawable.ic_home).toIcon(),<font></font>

                      "Launch MainActivity")<font></font>

  }<font></font>

<font></font>

  fun createSecondActivityAction(): SliceAction {<font></font>

      val intent = Intent(context, SecondActivity::class.java)<font></font>

      return SliceAction(PendingIntent.getActivity(context, 0, intent, 0),<font></font>

              IconCompat.createWithResource(context!!, R.drawable.ic_call).toIcon(),<font></font>

              "Launch SecondActivity")<font></font>

  }<font></font>

<font></font>

}

由于我们没有更改 URI,我们不需要创建新的运行配置,这意味着测试这个切片就像从 Android Studio 工具栏中 选择Run > sliceConfig一样简单。

编写您的第一个Android Slice并保持用户参与度  第4张

您可以从教程 GitHub 存储库下载此项目 。 

多媒体切片:创建网格布局

到目前为止,我们只使用行构建了所有切片,但您也可以使用网格行和单元格构建切片。 

在最后一节中,我们将创建一个由标题、副标题和分为三个单元格的单行组成的切片。每个单元格都有自己的标题、一些正文和一张图片,每个单元格在点击时都会执行一个独特的操作。 

编写您的第一个Android Slice并保持用户参与度  第5张

要在网格中布置切片,您需要: 

  • 实施一个ListBuilder.

  • ListBuilder使用向 中添加网格行addGridRow。 

  • 使用 将单元格添加到行中addCell。每行最多可以显示五个单元格。

然后,您可以向每个单元格添加内容,例如: 

  • 使用 . 添加的标题addTitleText。

  • 正文,使用addText.

  • 图像,您使用addImage. 每个单元格图像必须具有以下属性之一:LARGE_IMAGE、SMALL_IMAGE或ICON_IMAGE。 

  • 内容意图,大致相当于SliceAction. 为了帮助保持这个示例简单明了,点击每个单元格只会在设备的默认浏览器中加载一篇文章,但如果您希望获得更真实的切片体验,那么您可以更改setContentIntent代码。 

我将在我的网格中包含一些图像,因此您需要为您的项目添加至少一个可绘制对象。我使用的是 Kotlin 徽标,但您可以抓取任何图像并将其放入项目的Drawable文件夹中。 

现在,您已准备好打开MySliceProvider课程并构建您的网格: 

import android.app.PendingIntent<font></font>

import android.content.Context<font></font>

import android.content.Intent<font></font>

import android.net.Uri<font></font>

import androidx.core.graphics.drawable.IconCompat<font></font>

import androidx.slice.Slice<font></font>

import androidx.slice.SliceProvider<font></font>

import androidx.slice.builders.ListBuilder<font></font>

<font></font>

class MySliceProvider : SliceProvider() {<font></font>

<font></font>

    override fun onCreateSliceProvider(): Boolean {<font></font>

        return true<font></font>

    }<font></font>

<font></font>

    override fun onBindSlice(sliceUri: Uri): Slice? {<font></font>

        val path = sliceUri.path<font></font>

        when (path) {<font></font>

            "/launchMainActivity" -> return createSliceWithGridRow(sliceUri)<font></font>

        }<font></font>

        return null<font></font>

    }<font></font>

<font></font>

    fun createSliceWithGridRow(sliceUri: Uri): Slice {<font></font>

        return ListBuilder(context, sliceUri, ListBuilder.INFINITY)<font></font>

                .setHeader {<font></font>

                    it.apply {<font></font>

                        setTitle("Want to start learning Kotlin for Android?")<font></font>

                        setSubtitle("Check out these articles!")<font></font>

                    }<font></font>

                }<font></font>

<font></font>

//Add a grid row to the list builder//<font></font>

<font></font>

                .addGridRow {<font></font>

                    it.apply {<font></font>

<font></font>

//Add a cell to the row//<font></font>

<font></font>

                        addCell {<font></font>

                            it.apply {<font></font>

<font></font>

//Add content to your cell//<font></font>

<font></font>

                                addTitleText("Java vs. Kotlin")<font></font>

                                addText("Part 1")<font></font>

                                addImage(IconCompat.createWithResource(context, R.drawable.kotlin), ListBuilder.LARGE_IMAGE)<font></font>

<font></font>

//Specify the intent that should trigger whenever the user interacts with this cell//  <font></font>

<font></font>

<font></font>

                                        .setContentIntent(<font></font>

                                                loadArticlePendingIntent(<font></font>

                                                        context,<font></font>

                                                        "https://code.tutsplus.  com/articles/java-vs-kotlin-should-you-be-using-kotlin-for-android-development...)<font></font>

                            }<font></font>

                        }<font></font>

                        addCell {<font></font>

                            it.apply {<font></font>

                                addTitleText("Coding in Kotlin")<font></font>

                                addText("Part 2")<font></font>

                                addImage(IconCompat.createWithResource(context, R.drawable.kotlin), ListBuilder.LARGE_IMAGE)<font></font>

                                        .setContentIntent(<font></font>

                                                loadArticlePendingIntent(<font></font>

                                                        context,<font></font>

                                                        "https://code.tutsplus.  com/tutorials/start-developing-android-apps-with-kotlin-part-1--cms-27827?_ga=...)<font></font>

                            }<font></font>

                        }<font></font>

<font></font>

                        addCell {<font></font>

                            it.apply {<font></font>

                                addTitleText("Lambdas & NPE")<font></font>

                                addText("Part 3")<font></font>

                                addImage(IconCompat.createWithResource(context, R.drawable.kotlin), ListBuilder.LARGE_IMAGE)<font></font>

                                        .setContentIntent(<font></font>

                                                loadArticlePendingIntent(<font></font>

                                                        context,<font></font>

                                                        "https://code.tutsplus.  com/articles/coding-functional-android-apps-in-kotlin-lambdas-null-safety-more...)<font></font>

                            }<font></font>

                        }<font></font>

                    }<font></font>

                }<font></font>

                .build()<font></font>

    }<font></font>

    private fun loadArticlePendingIntent(context: Context, url: String) =<font></font>

            PendingIntent.getActivity(<font></font>

                    context,<font></font>

                    0,<font></font>

                    Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url) },<font></font>

                    0<font></font>

            )<font></font>

}

您可以在我们的 GitHub 存储库中找到该项目的完整代码。

在您的 AVD 或物理 Android 设备中运行此应用程序,并尝试与网格中的每个项目进行交互。每个单元格应链接到不同的文章。

确保您的切片看起来不错,无论主机应用程序如何 

切片内容的显示方式可能会有所不同,具体取决于主机应用程序配置的模式。为了确保无论托管应用程序如何,您的切片看起来都很好并且可以正常工作,您需要在所有不同的切片模式下测试您的切片。

由于我们的网格切片比之前的切片具有更多的内容,因此它是说明这些不同切片模式之间差异的最佳候选者。 

要对切片进行测试,请单击切片查看器右上角的小图标,然后循环浏览以下模式:

1. 大

在这种格式中,Android 会在可用空间中显示尽可能多的行。这是切片查看器默认使用的模式。 

2.捷径

在此模式下,您的切片由图标和标签表示。

编写您的第一个Android Slice并保持用户参与度  第6张

如果有一个与您相关联的主标题SliceAction,那么这将用作您切片的图标。如果没有可用的图标,那么 Android 将改为显示与切片的第一行关联的主要操作,在本例中是我们的 Kotlin 可绘制对象。 

要更改在快捷模式下显示的图标,请在项目中添加第二个可绘制对象,然后更新切片提供程序的以下部分:  

               .addGridRow {<font></font>

                   it.apply {<font></font>

                       addCell {<font></font>

                           it.apply {<font></font>

                               addTitleText("Java vs. Kotlin")<font></font>

                               addText("Part 1")<font></font>

<font></font>

//Reference the new drawable//<font></font>

<font></font>

                               addImage(IconCompat.createWithResource(context, R.drawable.androidlogo), ListBuilder.LARGE_IMAGE)

3.小

小模式的高度有限,并且会将单个SliceItem或有限的项目集合显示为单行内容。如果您的切片有一个标题,那么这将被显示,这正是我们的切片正在发生的事情。 

编写您的第一个Android Slice并保持用户参与度  第7张

更改标题或副标题都会影响小模式下显示的内容。

fun createSliceWithGridRow(sliceUri: Uri): Slice {<font></font>

   return ListBuilder(context, sliceUri, ListBuilder.INFINITY)<font></font>

           .setHeader {<font></font>

               it.apply {<font></font>

               setTitle("This is the title")<font></font>

               setSubtitle("This is the subtitle")<font></font>

               <font></font>

           }<font></font>

       }

如果您的切片不包含标题,则将显示切片的第一行。  

使用 Slice Builders KTX 减少代码

一旦你学会了如何实现一个新特性,下一步就是学习如何用更少的代码提供相同的结果!  

Android KTX是一组模块,由为 Kotlin 优化 Android 平台的扩展组成。Android KTX 的 Slice Builders KTX 模块将构建器模式包装在对 Kotlin 友好的 DSL 中,可帮助您以更简洁、更易读的方式创建切片。要开始使用 Slice Builders KTX,请替换以下依赖项:


implementation 'androidx.slice:slice-builders:1.0.0-alpha3'

和:


implementation 'androidx.slice:slice-builders-ktx:1.0.0-alpha3'

然后,您可以修改您的createSlice方法以使用此 DSL。例如,这是一个显示标题和副标题的简单切片:

import android.net.Uri<font></font>

import androidx.slice.Slice<font></font>

import androidx.slice.SliceProvider<font></font>

import androidx.slice.builders.ListBuilder<font></font>

import androidx.slice.builders.ListBuilder.INFINITY<font></font>

<font></font>

class MySliceProvider : SliceProvider() {<font></font>

<font></font>

   override fun onCreateSliceProvider(): Boolean {<font></font>

       return true<font></font>

   }<font></font>

<font></font>

   override fun onBindSlice(sliceUri: Uri): Slice? {<font></font>

       val path = sliceUri.path<font></font>

       when (path) {<font></font>

           "/launchMainActivity" -> return createSlice(sliceUri)<font></font>

       }<font></font>

       return null<font></font>

   }<font></font>

<font></font>

   fun createSlice(sliceUri: Uri): Slice {<font></font>

       return ListBuilder(context, sliceUri, INFINITY)<font></font>

               .addRow {<font></font>

                   it.apply {<font></font>

                       setTitle("This is a title")<font></font>

                       setSubtitle("This is a subtitle")<font></font>

<font></font>

                   }<font></font>

               }.build()<font></font>

   }<font></font>

<font></font>

}

使用 DSL,这变成: 

import android.net.Uri<font></font>

import androidx.slice.Slice<font></font>

import androidx.slice.SliceProvider<font></font>

import androidx.slice.builders.ListBuilder<font></font>

import androidx.slice.builders.list<font></font>

import androidx.slice.builders.row<font></font>

<font></font>

class MySliceProvider : SliceProvider() {<font></font>

<font></font>

   override fun onCreateSliceProvider(): Boolean {<font></font>

       return true<font></font>

   }<font></font>

<font></font>

   override fun onBindSlice(sliceUri: Uri): Slice? {<font></font>

       val path = sliceUri.path<font></font>

       when (path) {<font></font>

           "/launchMainActivity" -> return createSlice(sliceUri)<font></font>

       }<font></font>

       return null<font></font>

   }<font></font>

<font></font>

   fun createSlice(sliceUri: Uri): Slice {<font></font>

<font></font>

//Instantiate a ListBuilder and call build when the lambda has finished running//<font></font>

<font></font>

       return list(context, sliceUri, ListBuilder.INFINITY) {<font></font>

<font></font>

//Instantiate row and add it to the ListBuilder//<font></font>

<font></font>

           row {<font></font>

<font></font>

//setTitle and setSubtitle are both inside the row lambda//<font></font>

<font></font>

               setTitle("This is a title")<font></font>

               setSubtitle("This is a subtitle")<font></font>

<font></font>

           }<font></font>

<font></font>

       }<font></font>

   }<font></font>

}

结论 

在本文中,我们亲身体验了 Android 的新兴切片功能。我们了解了如何创建一个可以直接访问应用程序任何部分的简单切片,然后继续创建更复杂的切片,包括最终项目、图像、附加文本和多个SliceActions. 


文章目录
  • 切片:用户享受您的应用程序的更多方式
  • 如何创建我的第一个切片?
    • 使用切片提供程序在 Google 搜索中显示您的应用内容
      • 您的 Gradle 项目同步失败了吗?
    • 构建切片:URI SliceActions、 和切片布局
      • 1.定义一个URI
      • 2.让你的切片互动
      • 3. 构建 Slice 的 UI
    • 构建您的第一个功能齐全的 Android Slice
      • 测试切片:安装切片查看器
      • 创建 URI 运行配置
  • 从切片中获得更多:添加第二个SliceAction
    • 创建第二个活动
    • 构建更复杂的 UI:分割最终项目
  • 创建第二个 SliceAction
  • 多媒体切片:创建网格布局
  • 确保您的切片看起来不错,无论主机应用程序如何
    • 1. 大
    • 2.捷径
    • 3.小
  • 使用 Slice Builders KTX 减少代码
  • 结论