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

为Android编写小部件:输入和显示

android 1.5 以来,应用程序小部件使用户能够在舒适的主屏幕上获取信息、控制应用程序和执行关键任务。

在这个由两部分组成的系列中,我将向您展示如何通过将应用程序小部件添加到您的 Android 项目来提供更好的用户体验。

在本系列结束时,您将创建一个小部件:

  • 显示多组数据。

  • View当用户与该小部件布局中的特定对象交互时执行独特的操作。

  • 每当经过设定的时间段时自动更新日期。

  • 更新新数据以响应用户交互。

在第一篇文章中,我们将使用 Android Studio 的内置工具快速轻松地生成交付任何Android 应用程序小部件所需的所有文件。然后,我们将在此基础上扩展创建一个小部件,用于检索和显示数据并响应event。onClick

什么是应用程序小部件?

应用程序小部件是一种轻量级的微型应用程序,通常属于以下类别之一:  

  • 信息小部件。显示重要信息的不可滚动小部件,例如天气或时钟小部件。

  • 集合小部件。显示一系列相关元素的可滚动小部件,例如来自同一出版物的照片库或文章。集合小部件通常由数据源支持,例如Array数据库或数据库。集合小部件必须包含ListView、GridView、StackView或AdapterViewFlipper。

  • 控制小部件。一个充当应用程序遥控器的小部件,允许用户触发常用功能,而不必启动您的应用程序。播放音乐的应用程序通常提供一个小部件,让用户可以直接从他们的主屏幕播放、暂停和跳过曲目。

  • 混合小部件。当您可以从多个类别中挑选元素时,为什么还要将自己限制在一个类别上?请注意,混合和匹配可能会导致混乱的用户体验,因此为了获得最佳效果,您应该在设计小部件时考虑单一类别,然后根据需要添加其他类别的元素。例如,如果您想创建一个显示今天的天气预报但还允许用户查看不同日期和位置的预报的小部件,那么您应该创建一个信息小部件,然后添加必要的控制元素。

除了上述功能外,大多数小部件onClick通过启动其关联的应用程序来响应事件,类似于应用程序快捷方式,但它们也可以提供对该应用程序中特定内容的直接访问。

应用程序小部件必须放置在App Widget Host中,最常见的是库存的 Android 主屏幕,尽管有一些第三方 App Widget Host,例如流行的Nova Launcher和Apex Launcher。

在整个系列中,我将把小部件作为您放置在主屏幕上的东西来讨论,但如果您对能够在锁屏上放置小部件有模糊的回忆,那么这不仅仅是某种美妙的梦想!在api级别 17 和 20 之间,可以将小部件放置在主屏幕或锁屏上。

由于 API 级别 21 中不推荐使用锁屏小部件,因此在本系列中,我们将仅为主屏幕创建一个小部件。

为什么要创建应用程序小部件?

您应该考虑将应用程序小部件添加到最新的 Android 项目有几个原因。

轻松访问重要信息和功能

小部件允许用户直接从他们的主屏幕查看您的应用程序最重要的信息。例如,如果您开发了一个日历应用程序,那么您可能会创建一个小部件来显示有关用户下次约会的详细信息。这比强迫用户启动您的应用程序并可能浏览多个屏幕,只是为了检索相同的信息要方便得多。

如果您开发一个控制小部件(或带有控制元素的混合小部件),那么用户也可以直接从他们的主屏幕完成任务。继续我们的日历示例,您的小部件可能允许用户创建、编辑和取消约会,甚至可能无需启动您的应用程序。这有可能从应用程序的一些最重要任务中删除多个导航步骤,这只会对用户体验产生积极影响!

直接访问您应用中所有最重要的屏幕

点击小部件通常会将用户带到相关应用程序的顶层,类似于应用程序快捷方式。但是,与应用程序快捷方式不同,小部件可以链接到相关应用程序中的特定区域。例如,点击小部件的收到新电子邮件通知可能会启动已选择新消息的应用程序,而点击创建新电子邮件可能会将它们直接带到应用程序的ComposeEmail活动中。

通过在您的小部件布局中嵌入多个链接,您可以方便地一键式访问您应用中所有最重要的活动。

创建忠诚、参与的用户群

正如整个 Pokemon Go 的爆发和随后的下降所证明的那样,让大量的人下载你的应用程序并不能自动保证忠诚的用户群在几天、几周甚至几个月后仍然会使用你的应用程序。

移动用户是一个非常善变的群体,随着典型 Android 智能手机或平板电脑上的可用内存一直在增加,很容易忘记您在设备上安装的应用程序。如果您现在拿起 Android 智能手机或平板电脑并在应用程序抽屉中轻扫,那么您可能会发现至少有一个您完全忘记的应用程序。

通过创建一个展示您的应用程序所有最有价值的信息和功能的小部件,您可以确保每次用户浏览他们的主屏幕时,他们不仅会被提醒您的应用程序存在,而且它有一些很棒的内容。

将应用小部件添加到您的项目

即使是最基本的小部件也需要多个类和资源,但是当您使用 Android Studio 的内置工具创建小部件时,所有这些文件都会为您生成。由于没有必要让 Android 开发变得比需要的更难,我们将使用这些工具来抢先构建我们的小部件。

应用程序小部件必须始终绑定到底层应用程序,因此请使用您选择的设置创建一个新的 Android 项目。

Android Studio 构建项目后,从 Android Studio 工具栏中选择File > New > Widget > AppWidget 。这将启动一个配置组件菜单,您可以在其中定义一些小部件的初始设置

为Android编写小部件:输入和显示  第1张这些选项中的大多数都是不言自明的,但有一些值得更详细地探索。

可调整大小(API 12+)

如果一个小部件是可调整大小的,那么用户可以通过长按小部件然后拖动出现在其轮廓周围的蓝色手柄来增加或减少它在主屏幕上占据的“单元格”的数量。

只要有可能,您应该让您的小部件能够水平和垂直调整大小,因为这将帮助您的小部件适应一系列屏幕配置和主屏幕设置。如果用户的主屏幕非常混乱,那么您的小部件可能甚至无法适应该主屏幕,除非您的小部件可调整大小。

如果您确实想创建一个不可调整大小的小部件,请打开Resizabl e 下拉菜单并选择Only Horizontal 、Only Vertical或Not resizable。

最小宽度和高度

最小宽度和高度指定您的小部件在放置在主屏幕上时最初占用的单元格数。

对于可调整大小的小部件,这是用户可以调整小部件的最小尺寸,因此您可以使用这些值来防止用户将小部件缩小到无法使用的程度。

如果您的小部件不可调整大小,则最小宽度和高度值是您的小部件的永久宽度和高度。

为了增加小部件在一系列主屏幕上的舒适度,建议您永远不要使用大于 4 x 4 的最小宽度和高度值。

虽然主屏幕“单元格”的确切宽度和高度因设备而异,但您可以使用以下公式粗略估计您的小部件将占用多少 DPI(每英寸点数):

70 × number of cells -30

例如,如果您的小部件是 2 x 3 单元格:

70 x 2 - 30 = 110
70 x 3 - 30 = 180

这个小部件将在用户的主屏幕上占据大约 110 x 180 DPI。如果这些值与特定设备单元格的尺寸不一致,Android 会自动将您的小部件四舍五入到最接近的单元格大小。

查看此菜单中的所有选项并进行任何所需的更改(我坚持使用默认值),然后单击Finish。

Android Studio 现在将生成交付基本应用程序小部件所需的所有文件和资源。这个小部件并不令人高兴(它基本上只是一个蓝色块,上面写着“示例”一词),但它是一个可以在您的设备上测试的功能小部件。

要测试小部件:

  • 在物理 Android 设备或 AVD(Android 虚拟设备)上安装您的项目。

  • 按下主屏幕上的任何空白区域,然后点击出现在屏幕底部的单词Widget ,启动 Android 的Widget Picker 。

  • 在 Widget Picker 中滑动,直到找到蓝色的Example小部件。

  • 按下此小部件将其拖放到您的主屏幕上。

  • 通过按住小部件直到出现一组蓝色手柄进入调整大小模式,然后拖动这些手柄以增加或减少此小部件占用的单元格数量。

为Android编写小部件:输入和显示  第2张

探索应用程序小部件文件

这个小部件可能做的不多,但它包含了我们将在本系列的其余部分中使用的所有类和资源,因此让我们看看这些文件以及它们在交付应用程序小部件中所起的作用。

NewAppWidget.java

小部件提供程序是一个便利类,包含用于通过广播事件与小部件进行编程接口的方法。在底层,小部件本质上只是一个BroadcastReceiver可以响应各种操作的工具,例如用户在他们的主屏幕上放置一个新的小部件实例。

最值得注意的是,应用小部件提供程序是您定义小部件生命周期方法的地方,这些方法要么为小部件的每个实例调用,要么只为特定实例调用。

尽管我们倾向于将小部件视为用户放置在其主屏幕上一次的单个实体,但没有什么可以阻止他们创建同一个小部件的多个实例。也许您的小部件是可定制的,以至于不同的实例可以具有显着不同的功能,或者用户可能只是非常喜欢您的小部件以至于他们想将它贴在他们的主屏幕上!  

让我们看一下您可以在小部件提供程序类中实现的不同生命周期方法:

onReceive事件_

每当指定事件发生时,Android 都会调用onReceive()注册的方法。BroadcastReceiver

您通常不需要手动实现此方法,因为AppWidgetProvider类会自动过滤所有小部件广播并将操作委托给适当的方法。

onEnabled事件_

调用生命onEnabled()周期方法以响应ACTION_APPWIDGET_ENABLED,当用户将您的小部件的第一个实例添加到他们的主屏幕时广播。如果用户创建了您的小部件的两个实例,onEnabled()则为第一个实例调用 then,但不为第二个实例调用。

在此生命周期方法中,您可以执行任何只需要为所有小部件实例发生一次的设置,例如创建数据库或设置服务。

请注意,如果用户从他们的设备中删除了您的小部件的所有实例,然后创建了一个新实例,那么这将被归类为第一个实例,因此onEnabled() 将再次调用该方法。

onAppWidgetOptionsChanged事件_

调用此生命周期方法以响应ACTION_APPWIDGET_OPTIONS_CHANGED,在创建小部件实例以及每次调整小部件大小时广播该方法。您可以使用此方法根据用户对小部件的大小来显示或隐藏内容,尽管此回调仅在 Android 4.1 及更高版本中受支持。

onUpdate事件_

onUpdate()每次都会调用生命周期方法:

  • 更新间隔已过。

  • 用户执行触发该onUpdate()方法的动作。

  • 用户在他们的主屏幕上放置一个新的小部件实例(除非您的小部件包含配置活动,我们将在第二部分中介绍)。

onUpdate()生命周期方法也被调用以响应ACTION_APPWIDGET_restORED,每当从备份中恢复小部件时都会广播该方法。

对于大多数项目,该onUpdate()方法将包含大部分小部件提供程序代码,特别是因为它也是您注册小部件事件处理程序的地方。

onDeleted事件_

onDeleted()每次从 App Widget Host 中删除您的小部件实例时都会调用该方法,这会触发系统的ACTION_APPWIDGET_DELETED广播。

onDisabled事件_

调用此方法以响应ACTION_APPWIDGET_DISABLED广播,当您的小部件的最后一个实例从应用小部件主机中删除时发送。例如,如果用户创建了您的小部件的三个实例,则onDisabled()只有当用户从主屏幕中删除第三个也是最后一个实例时才会调用该方法。  

生命onDisabled()周期方法是您应该清理您在 中创建的任何资源的地方onEnabled(),因此如果您在 中设置数据库,onEnabled()那么您将在 中删除它onDisabled()。

onRestored事件_

调用该onRestored()方法以响应ACTION_APPWIDGET_RESTORED,每当从备份中恢复应用程序小部件的实例时都会广播该方法。如果要维护任何持久数据,则需要重写此方法并将以前的方法重新映射AppWidgetIds到新值,例如:

public void onRestored(Context context, int[] oldWidgetIds,
           int[] newWidgetIds) {
   }
}

如果你打开 Android Studio 自动生成的NewAppWidget.java文件,你会看到它已经包含了一些小部件生命周期方法的实现:

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.widget.RemoteViews;

//All widgets extend the AppWidgetProvider class//

public class NewAppWidget extends AppWidgetProvider {

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                              int appWidgetId) {

      CharSequence widgetText = context.getString(R.string.appwidget_text);

    //Load the layout resource file into a RemoteViews object//

      RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
      views.setTextViewText(R.id.appwidget_text, widgetText);

 //Tell the AppWidgetManager about the updated RemoteViews object//

      appWidgetManager.updateAppWidget(appWidgetId, views);
  }

//Define the onUpdate lifecycle method//

  @Override
  public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

//appWidgetIds is an array of IDs that identifies every instance of your widget, so this 
//particular onUpdate() method will update all instances of our application widget//

      for (int appWidgetId : appWidgetIds) {
          updateAppWidget(context, appWidgetManager, appWidgetId);
      }
  }

  @Override

//Define the onEnabled lifecycle method//

  public void onEnabled(Context context) {
      
      //To do//
  }

  @Override

//Define the onDisabled method//

  public void onDisabled(Context context) {
      
//To do//

  }
}

小部件布局文件

res/layout/new_app_widget.xml文件 定义了我们小部件的布局,目前它只是一个蓝色背景,上面写着  “示例”一词。

为 Activity 创建布局和为小部件创建布局之间的主要区别在于小部件布局必须基于RemoteViews,因为这允许 Android 在应用程序之外的进程中显示布局(即在用户的主屏幕上)。

RemoteViews不支持所有类型的布局或View,因此在构建小部件布局时,您仅限于以下类型:

  • AnalogClock

  • Button

  • Chromometer

  • FrameLayout

  • GridLayout

  • ImageButton

  • ImageView

  • LinearLayout

  • ProgressBar

  • RelativeLayout

  • TextView

  • ViewStub

如果您正在创建一个集合小部件,那么当您的应用程序安装在 Android 3.0 及更高版本上时,您还可以使用以下类型:

  • AdapterViewFlipper

  • GridView

  • ListView

  • StackView

  • ViewFlipper

Views不支持上述和类的子类和后代。

点击和滑动

为确保用户在浏览主屏幕时不会意外与小部件交互,小部件onClick仅响应事件。

例外情况是当用户通过将小部件拖向主屏幕的卸载操作来移除小部件时,因为在这种情况下,您的小部件将响应垂直滑动手势。但是,由于此交互由 Android 系统管理,因此您无需担心在应用程序中实现垂直滑动支持。

小部件信息文件

res/xml/new_app_widget_info.xml文件 (也称为 AppWidgetProviderInfo 文件)定义了许多小部件属性,包括您在 Android Studio 的配置组件菜单中选择的许多设置,例如小部件的最小尺寸以及是否可以放置在锁屏上。

配置文件还指定小部件从 App Widget 更新服务请求新信息的频率。决定这个频率需要你做出一个棘手的平衡:更长的更新间隔将有助于节省设备的电池,但间隔太远,你的小部件可能会显示明显过时的信息。

您还应该知道,系统会唤醒处于睡眠状态的设备以检索新信息,因此尽管每半小时更新一次您的小部件听起来并不过分,但它可能会导致您的小部件每 30 分钟唤醒一次设备,即会影响电池消耗。

如果您打开项目的new_app_widget_info.xml文件,您会看到它已经定义了许多小部件属性,包括更新间隔。

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="https://schemas.android.com/apk/res/android"

//The layout your widget should use when it’s placed on the lockscreen on supported devices//

  android:initialKeyguardLayout="@layout/new_app_widget"

//The layout your widget should use when it’s placed on the homescreen//

  android:initialLayout="@layout/new_app_widget"

//The minimum space your widget consumes, which is also its initial size//

  android:minHeight="40dp"
  android:minWidth="40dp"

//The drawable that represents your widget in the Widget Picker//

  android:previewImage="@drawable/example_appwidget_preview"

//Whether the widget can be resized horizontally, vertically, or along both axes, on Android 3.1 and higher//  

  android:resizeMode="horizontal|vertical"

//How frequently your widget should request new information from the app widget provider//

  android:updatePeriodMillis="86400000"

//Whether the widget can be placed on the homescreen, lockscreen (“keyguard”) or both.//
//On Android 5.0 and higher, home_screen is the only valid option//

  android:widgetCategory="home_screen"></appwidget-provider>

如果您确实让您的用户可以选择将您的小部件放在锁屏上,那么请记住,只要瞥一眼锁屏,任何人都可以看到小部件的内容。如果您的“默认”布局包含任何个人信息或潜在的敏感信息,那么您应该为您的小部件提供替代布局,以便在将其放置在锁定屏幕上时使用。

res/values/dimens.xml 文件

当小部件相互挤压时,或者当它们延伸到主屏幕的最边缘时,它们看起来并不是最好的。

每当您的小部件在 Android 4.0 或更高版本上显示时,Android 操作系统会自动在小部件框架和边界框之间插入一些填充。

为Android编写小部件:输入和显示  第3张

如果您的应用最终在运行早于 Android 4.0 的设备上运行,那么您的小部件需要自己提供此填充。

当您使用File > New > Widget > AppWidget菜单创建小部件时,Android Studio 会生成两个dimens.xml文件,以确保您的小部件始终具有正确的填充,无论它安装在哪个 Android 版本上。

您将在项目的 res 文件夹中找到这两个文件:

res/values/d imens.xml

该文件定义了小部件在 API 级别 13 或更早版本上安装时需要提供的 8dpi 填充。

<dimen name="widget_margin">8dp</dimen>

res/values-v14/dimens.xml

由于 Android 4.0 及更高版本会自动将填充应用于每个小部件,因此您的小部件提供的任何填充都将是此默认填充的补充。

为了确保您的小部件与用户放置在其主屏幕上的任何应用程序图标或其他小部件对齐,此dimens.xml文件指定您的小部件不应为 Android 4.0 及更高版本提供额外的边距:

<dimen name="widget_margin">0dp</dimen>

此默认边距有助于在视觉上平衡主屏幕,因此您应该避免修改它 - 毕竟,您不希望您的小部件成为奇怪的小部件!

您的小部件布局已引用此尺寸值(android:padding="@dimen/widget_margin"),因此在处理小部件布局时请注意不要更改此行。

尽管这些dimens.xml文件是确保您的小部件始终具有正确填充的最简单方法,但如果此技术不适合您的特定项目,那么另一种方法是为 API 级别 14 创建多个具有不同边距的九个补丁背景和更高,API 级别 13 和更低。您可以使用 Android Studio 的 Draw 9-patch 工具或使用adobe photoshop 等专用图形编辑程序创建九个补丁。

项目清单

在项目的AndroidManifest.xml文件中,您需要将小部件注册为 aBroadcastReceiver并指定小部件提供程序和该小部件应使用的AppWidgetProviderInfo文件。

如果您打开清单,您会看到 Android Studio 已经为您添加了所有这些信息。

//The widget’s AppWidgetProvider; in this instance that’s NewAppWidget.java//

<receiver android:name=".NewAppWidget">
      <intent-filter>

//An intent filter for the android.appwidget.action.APPWIDGET_UPDATE action//

          <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
      </intent-filter>

      <meta-data
          android:name="android.appwidget.provider"

//The widget’s AppWidgetProviderInfo object//

          android:resource="@xml/new_app_widget_info" />

  </receiver>
</application>

小部件选择器资源

res/drawable/example_appwidget_preview.png 文件是在 Widget Picker 中代表您的小部件的可绘制资源。

为了鼓励用户从所有可用选项中选择您的小部件,此可绘制对象应显示您的小部件,在主屏幕上正确配置并显示许多有用的内容。

当您使用File > New > Widget > AppWidget菜单创建小部件时,Android Studio 会自动生成一个预览可绘制对象 ( example_appwidget_preview.png )。

在第二部分中,我将向您展示如何使用 Android Studio 的内置工具生成您自己的预览图像,从而快速轻松地替换这个 stock drawable。

建立你的布局

现在我们大致了解了这些文件是如何组合在一起创建应用程序小部件的,让我们在此基础上进行扩展,并创建一个不仅仅在蓝色背景上显示单词Example的小部件!

我们将为我们的小部件添加以下功能:

  • TextView显示应用程序小部件 ID标签的A。

  • TextView 检索并显示此特定小部件实例的 ID 的A。

  • A通过启动用户的默认浏览器并加载 URLTextView来响应事件。onClick

TextViews虽然我们可以简单地从 Android Studio 调色板中拖动三个并将它们放到画布上,但如果您的小部件看起来不错,那么用户将更有可能将其放置在他们的主屏幕上,所以让我们创建一些资源,让我们的小部件具有额外的视觉吸引力.

创建小部件的背景

我将创建一个带有圆角、渐变背景和边框的矩形,我将把它用作我的小部件的背景:

  • 按住 Control 并单击项目的drawable文件夹,然后选择New > Drawable resource file。

  • 将此文件命名为 widget_background并单击OK。

  • 输入以下代码:

<?xml version="1.0" encoding="UTF-8"?>
http://schemas.android.com/apk/res/android"
  android:shape="rectangle">

  <stroke
      android:width="1dp"
      android:color="#ffffff" />

  <gradient
      android:angle="225"
      android:endColor="#00FFFFFF"
      android:startColor="#DD000000" />

  <corners
      android:topRightRadius="10dp"
      android:topLeftRadius="10dp"
      android:bottomRightRadius="10dp"
      android:bottomLeftRadius="10dp" />
</shape>

2.创建TextView 背景

接下来,创建一个形状用作我们的背景TextViews:

  • 按住 Control 并单击项目的drawable文件夹,然后选择New > Drawable resource file。

  • 将此文件命名为 tvbackground,然后单击OK。

  • 输入以下代码:

<?xml version="1.0" encoding="utf-8"?>
http://schemas.android.com/apk/res/android"
  android:shape="rectangle" >

  <stroke
      android:width="1dp"
      android:color="#000000" />

  <solid android:color="#FFFFFFFF" />

  <corners
      android:topRightRadius="15dp"
      android:topLeftRadius="15dp"
      android:bottomRightRadius="15dp"
      android:bottomLeftRadius="15dp" />
</shape>

3.创建一些样式

我还将使用以下样式:

  • widget_text. 我将应用于小部件文本的粗体效果。

  • widget_views. 我将应用于我的TextViews.

打开项目的styles.xml文件并添加以下内容:

<style name="widget_views" parent="@android:style/Widget">
      <item name="android:padding">8dp</item>
      <item name="android:layout_marginTop">12dp</item>
      <item name="android:layout_marginLeft">12dp</item>
      <item name="android:layout_marginRight">12dp</item>
      <item name="android:textStyle">bold</item>
  </style>

<style name="widget_text" parent="@android:style/Widget">
  <item name="android:textStyle">bold</item>
</style>

4. 建立你的布局!

现在我们所有的资源都准备好了,我们可以创建小部件的布局。打开new_app_widget.xml文件并添加以下内容:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:padding="@dimen/widget_margin"
  android:background="@drawable/widget_background"
  android:orientation="vertical" >

  <LinearLayout
      android:background="@drawable/tvbackground"
      style="@style/widget_views"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal">

      <TextView
          android:id="@+id/id_label"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/widget_id"
          style="@style/widget_text" />

      <TextView
          android:id="@+id/id_value"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="."
          style="@style/widget_text" />
  </LinearLayout>

  <TextView
      android:id="@+id/launch_url"
      style="@style/widget_views"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="@string/URL"
      android:background="@drawable/tvbackground"/>
</LinearLayout>

最后,打开strings.xml文件并定义我们在布局中引用的字符串资源:

<resources>
  <string name="app_name">Widget</string>
  <string name="widget_id">App Widget ID\u0020</string>
  <string name="URL">Tap to launch URL</string>
</resources>

Android Studio 的“设计”选项卡通过预览您的布局将如何在各种设备上呈现,帮助您更高效地工作。每次更改布局时,切换到“设计”选项卡比在 Android 设备上运行项目要容易得多。

令人沮丧的是,Android Studio 不提供专用的小部件皮肤,因此默认情况下,您的小部件布局就像常规 Activity 一样呈现,这并不能提供您的小部件在用户主屏幕上的外观的最佳洞察力。

一种可能的解决方法是使用Android Wear (Square)皮肤呈现您的布局,它与 Android 应用程序小部件的大小和形状相当:

  • 确保选中 Android Studio 的设备选项卡。

  • 打开设备下拉菜单。

  • 从下拉菜单中选择280 x 280、hdpi(方形) 。

为Android编写小部件:输入和显示  第4张

创建小部件功能

现在我们的小部件看起来像部件,是时候给它一些功能了:

  • 检索和显示数据。小部件的每个实例在添加到应用小部件主机时都会分配一个 ID。此 ID 在小部件的生命周期中持续存在,并且对于该小部件实例来说是完全唯一的,即使用户将同一小部件的多个实例添加到他们的主屏幕也是如此。

  • 添加一个动作。我们将创建一个OnClickListener启动用户的默认浏览器并加载 URL。

打开小部件提供程序文件 ( NewAppWidget.java ) 并删除检索appwidget_text字符串资源的行:

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                          int appWidgetId) {

//Delete the following line//

  CharSequence widgetText = context.getString(R.string.appwidget_text);
  RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
  views.setTextViewText(R.id.appwidget_text, widgetText);

  appWidgetManager.updateAppWidget(appWidgetId, views);

}

在该updateAppWidget块中,我们现在需要R.id.id_value使用小部件的唯一 ID 更新占位符:

  RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
      views.setTextViewText(R.id.id_value, String.valueOf(appWidgetId));

我们还需要创建一个 Intent 对象,其中包含用户与 this 交互时应加载的 URL TextView。

      Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.weixiaolive.com/en/"));
      PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

//Attach an OnClickListener to our “launch_url” button, using setOnClickPendingIntent//

      views.setOnClickPendingIntent(R.id.launch_url, pendingIntent);

这是完整的小部件提供程序文件:

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.widget.RemoteViews;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;

public class NewAppWidget extends AppWidgetProvider {

  static void updateAppWidget(Context context,

                              AppWidgetManager appWidgetManager,

                              int appWidgetId) {

//Instantiate the RemoteViews object//

      RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);

//Update your app’s text, using the setTextViewText method of the RemoteViews class//

      views.setTextViewText(R.id.id_value, String.valueOf(appWidgetId));

//Register the OnClickListener//

      Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.weixiaolive.com/en/"));
      PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
      views.setOnClickPendingIntent(R.id.launch_url, pendingIntent);
      appWidgetManager.updateAppWidget(appWidgetId, views);

  }

  @Override
  public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

      //Update all instances of this widget//

      for (int appWidgetId : appWidgetIds) {
          updateAppWidget(context, appWidgetManager, appWidgetId);
      }
  }
}

测试小部件

是时候测试这个小部件了!

  • 在您的 Android 设备上安装更新的项目。

  • 为确保您看到此小部件的最新版本,请从您的主屏幕中删除所有现有的小部件实例。

  • 按主屏幕的任何空白部分,然后从小部件选择器中选择您的小部件。

  • 根据需要重新定位和调整小部件的大小。

为Android编写小部件:输入和显示  第5张

  • 通过选择Tap to launch URL 检查小部件是否响应用户输入事件TextView。应用程序小部件应通过启动默认浏览器并加载 URL 来响应。

如果您一直在学习本教程,那么此时您已经拥有了一个功能齐全的小部件,它展示了 Android 应用小部件的许多核心概念。您还可以从我们的 GitHub 存储库下载完成的项目。

结论

在这篇文章中,我们检查了交付 Android 应用程序小部件所需的所有文件,然后构建一个小部件来检索和显示一些独特的数据并响应用户输入事件。

目前,我们的小部件还缺少一项主要功能:它永远不会显示任何新信息!在下一篇文章中,我们将让这个小部件能够根据设定的时间表自动检索和显示新数据,并直接响应用户输入事件。


文章目录
  • 什么是应用程序小部件?
    • 为什么要创建应用程序小部件?
      • 轻松访问重要信息和功能
      • 直接访问您应用中所有最重要的屏幕
      • 创建忠诚、参与的用户群
  • 将应用小部件添加到您的项目
    • 可调整大小(API 12+)
    • 最小宽度和高度
  • 探索应用程序小部件文件
    • NewAppWidget.java
      • onReceive事件_
      • onEnabled事件_
      • onAppWidgetOptionsChanged事件_
      • onUpdate事件_
      • onDeleted事件_
      • onDisabled事件_
      • onRestored事件_
      • 小部件布局文件
      • 小部件信息文件
      • res/values/dimens.xml 文件
    • 项目清单
    • 小部件选择器资源
  • 建立你的布局
    • 创建小部件的背景
    • 2.创建TextView 背景
    • 3.创建一些样式
    • 4. 建立你的布局!
    • 创建小部件功能
    • 测试小部件
  • 结论