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

从Android 1.5开始,应用程序小部件使用户能够在舒适的主屏幕上获取信息,控制应用程序并执行关键任务。

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

在本系列的最后,您将创建一个小部件,该小部件:

  • 显示多组数据。
  • 当用户与该小部件的布局内的特定View交互时,执行唯一的操作。
  • 在设定的时间段过后会自动更新。
  • 更新新数据以响应用户交互。

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

什么是应用程序小部件?

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

  • 信息小部件。 显示重要信息的不可滚动小部件,例如天气或时钟小部件。
  • 集合小部件。 可滚动的窗口小部件,显示一系列相关元素,例如来自同一出版物的照片画廊或文章画廊。 集合小部件通常由数据源(例如Array或数据库)支持。 集合小部件必须包含ListViewGridViewStackViewAdapterViewFlipper
  • 控制小部件。 一个小部件,可充当您的应用程序的远程控件,使用户无需启动您的应用程序即可触发常用功能。 播放音乐的应用程序通常会提供一个小部件,使用户可以直接从其主屏幕播放,暂停和跳过曲目。
  • 混合小部件。 当您可以从多个类别中挑选元素时,为什么将自己限制在一个类别中? 请注意,混合和匹配会导致混乱的用户体验,因此为了获得最佳效果,您应该在设计widget时考虑单个类别,然后根据需要添加其他类别的元素。 例如,如果您想要创建一个小部件以显示今天的天气预报,但还允许用户查看不同日期和位置的天气预报,则您应该创建一个信息小部件,然后再添加必要的控制元素。

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

尽管有一些第三方App Widget Host,例如流行的Nova LauncherApex Launcher ,但应用Widget必须放置在App Widget Host (最常见的是Android主屏幕)中。

在整个系列中,我将把小部件作为您放置在主屏幕上的方式进行讨论,但是如果您对能够将小部件放置在锁屏上的想法有所含糊,那么这不仅仅是一个美好的梦想! API级别17和20之间,有可能将小部件在主屏幕或锁屏。

由于锁屏窗口小部件在API级别21中已弃用,因此在本系列中,我们将仅为主屏幕创建窗口小部件。

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

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

轻松访问重要信息和功能

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

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

直接访问应用程序所有最重要的屏幕

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

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

建立忠实的用户群

正如整个Pokemon Go爆炸和随后的失败所证明的那样,吸引大量人下载您的应用程序并不能自动保证忠实的用户群仍会在几天,几周甚至几个月内使用您的应用程序。

移动用户非常善变,随着典型Android智能手机或平板电脑上可用内存的不断增加,很容易丢失对设备上已安装应用程序的跟踪。 如果您现在拿起Android智能手机或平板电脑并在应用程序抽屉中滑动,则可能会发现至少一个您完全忘记的应用程序。

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

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

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

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

Android Studio构建完项目后,请从Android Studio工具栏中选择文件>新建>窗口小部件> AppWidget 。 这将启动“ 配置组件”菜单,您可以在其中定义小部件的一些初始设置。

在Android Studio中配置小部件设置

这些选项大多数都是不言自明的,但是有一些值得更详细地探讨。

可调整大小(API 12+)

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

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

如果你想创建一个非可调整大小的小部件,然后打开ResizablË下拉菜单,选择只水平只有垂直 ,或不调整大小

最小宽度和高度

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

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

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

为了增加窗口小部件在各种主屏幕上舒适安装的机会,建议您不要使用大于4乘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会自动将小部件舍入到最接近的单元格大小。

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

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

要测试小部件:

  • 在物理Android设备或AVD(Android虚拟设备)上安装项目。
  • 启动Android的小部件选择器 通过按下主屏幕上的任何空白区域,然后点击出现在屏幕底部的“窗口小部件 ”一词。
  • 滑动小部件选择器,直到发现蓝色的示例小部件。
  • 按下此小部件以将其放到主屏幕上。
  • 按下小部件直到出现一组蓝色手柄,进入调整大小模式 ,然后拖动这些手柄以增加或减少此小部件占用的单元格数量。
在Android虚拟设备上测试您的小部件

探索应用程序小部件文件

这个小部件可能不会很多事情,但是它包含了本系列其余部分将要使用的所有类和资源,因此让我们看一下这些文件及其在交付应用程序小部件中所扮演的角色。

NewAppWidget.java

窗口小部件提供程序是一个便利类,其中包含用于通过广播事件以编程方式与窗口小部件交互的方法。 实际上,小部件实际上只是可以响应各种动作的BroadcastReceiver ,例如用户将新的小部件实例放置在其主屏幕上。

最值得注意的是,您可以在应用程序窗口小部件提供程序中定义窗口小部件的生命周期方法,该方法可以针对窗口小部件的每个实例或仅针对特定实例而调用。

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

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

onReceive事件

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

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

onEnabled事件

onEnabled()生命周期方法被调用响应ACTION_APPWIDGET_ENABLED ,当用户添加小工具的第一个实例,以他们的主屏幕被播出。 如果用户创建了窗口小部件的两个实例,则将为第一个实例调用onEnabled() ,而不是第二个实例。

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

请注意,如果用户从其设备上删除窗口小部件的所有实例,然后创建一个新实例,则该实例将被分类为第一个实例,因此将再次调用onEnabled()方法。

onAppWidgetOptionsChanged事件

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

onUpdate事件

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

  • 更新间隔已经过去。
  • 用户执行触发onUpdate()方法的操作。
  • 用户在其主屏幕上放置一个小部件的新实例(除非小部件包含配置活动,我们将在第二部分中介绍)。

还响应于ACTION_APPWIDGET_RESTORED调用onUpdate()生命周期方法,每当从备份中恢复窗口小部件时都会广播该方法。

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

onDeleted事件

onDeleted()您的小部件实例从“应用小部件主机”中删除时,都会调用onDeleted()方法,这会触发系统的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文件定义了小部件的布局,当前它只是一个蓝色背景,上面写有示例

为活动创建布局和为小部件创建布局之间的主要区别在于,小部件布局必须基于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窗口小部件更新服务请求新信息的频率。 确定此频率要求您达到一个棘手的平衡:较长的更新间隔将有助于节省设备的电池电量,但是将间隔间隔太远,则小部件可能会显示明显过时的信息。

您还应该知道,系统将唤醒睡眠中的设备以检索新信息,因此尽管每半小时更新一次小部件听起来可能不算过多,但它可能会导致小部件每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 4.0之前版本的设备上运行,则您的小部件需要自己提供填充。

使用“ 文件”>“新建”>“窗口小部件”>“ 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)来创建9-patch。

项目清单

在项目的AndroidManifest.xml文件中,您需要将小部件注册为BroadcastReceiver并指定该小部件应使用的小部件提供程序和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文件是可绘制资源,它表示“小部件选择器”中的小部件。

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

使用文件>新建>窗口小部件> AppWidget菜单创建窗口小部件时 ,Android Studio会自动生成一个可绘制的预览图( example_appwidget_preview.png )。

在第二部分中,我将向您展示如何通过使用Android Studio的内置工具生成您自己的预览图像,来快速轻松地替换此库存可绘制对象。

建立布局

现在,我们对这些文件如何组合在一起以创建应用程序窗口小部件进行了概述,让我们在此基础上进行扩展并创建一个窗口小部件,其功能不仅仅是在蓝色背景上显示示例字!

我们将在小部件中添加以下功能:

  • 显示应用程序小部件ID标签的TextView
  • 一个TextView ,它检索并显示此特定窗口小部件实例的ID。
  • 通过启动用户的默认浏览器并加载URL来响应onClick事件的TextView

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

创建小部件的背景

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

  • 右键单击项目的drawable文件夹,然后选择New> Drawable资源文件
  • 将此文件命名为widget_background ,然后单击“ 确定”
  • 输入以下代码:
<?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的背景:

  • 右键单击项目的drawable文件夹,然后选择New> Drawable资源文件
  • 将此文件命名为tvbackground ,然后单击“ 确定”
  • 输入以下代码:
<?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不提供专用的窗口小部件外观,因此默认情况下,您的窗口小部件的布局就像常规的活动一样呈现,而无法提供对窗口小部件在用户主屏幕上的外观的最佳了解。

一种可能的解决方法是使用Android Wear(方形)外观渲染布局,该外观可与Android应用程序小部件的大小和形状相媲美:

  • 确保选择了Android Studio的“ 设备”标签。
  • 打开设备下拉菜单。
  • 从下拉菜单中选择280 x 280,hdpi(平方)
尝试使用Android Wear Square外观渲染小部件布局

创建小部件功能

现在我们的小部件看起来很重要,现在该给它一些功能了:

  • 检索并显示数据。 在将小部件的每个实例添加到App Widget Host时,都会为其分配一个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块中,我们现在需要使用小部件的唯一ID更新R.id.id_value占位符:

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

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

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://code.tutsplus.com/"));
      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://code.tutsplus.com/"));
      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应用程序小部件进行测试
  • 通过选择点击以启动URL TextView ,检查小部件是否响应用户输入事件。 应用程序小部件应通过启动默认浏览器并加载URL进行响应。

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

结论

在本文中,我们在构建可检索并显示一些唯一数据并对用户输入事件做出响应的小部件之前,检查了交付Android应用小部件所需的所有文件。

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

翻译自: https://code.tutsplus.com/tutorials/code-a-widget-for-android-input-and-display--cms-30396

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值