Android 创建桌面组件Widget——构建应用微件(二)

2024-03-14 05:10

本文主要是介绍Android 创建桌面组件Widget——构建应用微件(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android 创建桌面组件Widget——构建应用微件(二)

  • Android 创建桌面组件Widget——构建应用微件(二)
    • 概览
        • 使用 AppWidgetProvider 类
          • 接收应用微件广播 Intent
        • 固定应用微件
        • 设置预览图片
    • 完整代码

Android 创建桌面组件Widget——构建应用微件(一)

Android 创建桌面组件Widget——构建应用微件(二)

效果图:
创建一个可以改变大小的widget,包含一个Button和一个TextView,点击按钮跳转到指定的Activity。
请添加图片描述

概览

微件是自定义主屏幕的一个重要方面。您可以将微件想象成“一目了然”的视图,它们让最重要的应用数据和功能一览无余,从用户的主屏幕即可进行访问。用户可以在其主屏幕面板间移动微件,如果系统支持,用户还可以调整微件的大小,按照他们的偏好量身定制微件中的信息量。

使用 AppWidgetProvider 类

AppWidgetProvider类扩展了BroadcastReceiver作为一个辅助类来处理应用微件广播。AppWidgetProvider仅接收与应用微件有关的事件广播,例如当更新、删除、启用和停用应用微件时发出的广播。当发生这些广播事件时,AppWidgetProvider会接收以下方法调用:

  • onUpdate()
    调用此方法可以按AppWidgetProviderInfo中的updatePeriodMillis属性定义的时间间隔来更新应用微件。当用户添加应用微件时也会调用此方法,所以它应执行基本设置,如定义视图的事件处理脚本以及根据需要启动临时的 Service。不过,如果您已声明配置Activity,则当用户添加应用微件时不会调用此方法,但会调用它来执行后续更新。由配置Activity负责在配置完成后执行首次更新。
  • onAppWidgetOptionsChanged()
    当首次放置微件时以及每当调整微件的大小时,会调用此方法。您可以使用此回调来根据微件的大小范围显示或隐藏内容。您可以通过调用 getAppWidgetOptions() 来获取大小范围,该方法会返回包含以下各项的 Bundle
    • OPTION_APPWIDGET_MIN_WIDTH : 包含微件实例的当前宽度的下限(以 dp 为单位)。
    • OPTION_APPWIDGET_MIN_HEIGHT: 包含微件实例的当前高度的下限(以 dp 为单位)
    • OPTION_APPWIDGET_MAX_WIDTH: 包含微件实例的当前宽度的上限(以 dp 为单位)
    • OPTION_APPWIDGET_MAX_HEIGHT: 包含微件实例的当前高度的上限(以 dp 为单位)。
    • 此回调是在 API 级别 16 (Android 4.1) 中引入的。如果您实现此回调,请确保您的应用不依赖于它,因为在旧款设备上不会调用它。
  • onDeleted(Context, int[])
    每次从应用微件托管应用中删除应用微件时,都会调用此方法。
  • onEnabled(Context)
    首次创建应用微件的实例时,会调用此方法。例如,如果用户添加应用微件的两个实例,只有首次添加时会调用此方法。如果您需要打开一个新的数据库或执行只需要对所有应用微件实例执行一次的其他设置,则此方法非常合适。
  • onDisabled(Context)
    从应用微件托管应用中删除了应用微件的最后一个实例时,会调用此方法。您应使用此方法来清理在 onEnabled(Context)中完成的所有工作,如删除临时数据库。
  • ``
    针对每个广播调用此方法,并且是在上述各个回调方法之前调用。您通常不需要实现此方法,因为默认的 AppWidgetProvider 实现会过滤所有应用微件广播并视情况调用上述方法。

最重要的 AppWidgetProvider 回调是 onUpdate(),因为向托管应用添加每个应用微件时都会调用它(除非您使用配置 Activity)。如果应用微件接受任何用户交互事件,则您需要在此回调中注册事件处理脚本。如果应用微件未创建临时文件或数据库,或者未执行其他需要清理的工作,则 onUpdate() 可能是您需要定义的唯一一个回调方法。例如,如果您希望应用微件具有一个在用户点击时会启动 Activity 的按钮,则可以使用以下 AppWidgetProvider 实现:

public class ExampleAppWidgetProvider extends AppWidgetProvider {public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {final int N = appWidgetIds.length;// Perform this loop procedure for each App Widget that belongs to this providerfor (int i=0; i<N; i++) {int appWidgetId = appWidgetIds[i];// Create an Intent to launch ExampleActivityIntent intent = new Intent(context, ExampleActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);// Get the layout for the App Widget and attach an on-click listener// to the buttonRemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);views.setOnClickPendingIntent(R.id.button, pendingIntent);// Tell the AppWidgetManager to perform an update on the current app widgetappWidgetManager.updateAppWidget(appWidgetId, views);}}
}
接收应用微件广播 Intent

AppWidgetProvider 只是一个辅助类。如果您希望直接接收应用微件广播,您可以实现自己的 BroadcastReceiver 或替换 onReceive(Context, Intent) 回调。您需要关注的 Intent 如下所示:

ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
ACTION_APPWIDGET_OPTIONS_CHANGED

固定应用微件

在搭载 Android 8.0(API 级别 26)及更高版本的设备上,允许您创建固定的快捷方式的启动器也允许您将应用微件固定到启动器上。与固定的快捷方式类似,这些固定的微件也能让用户访问应用中的特定任务。

在您的应用中,您可以创建一个请求,让系统将微件固定到支持的启动器上,只需完成下面一系列步骤即可:

  1. 在应用的清单文件中创建微件,如以下代码段所示:
    <manifest>...<application>...<receiver android:name="MyAppWidgetProvider"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /></intent-filter><meta-data android:name="android.appwidget.provider"android:resource="@xml/my_appwidget_info" /></receiver></application></manifest>
  1. 调用 requestPinAppWidget() 方法,如以下代码段所示:
    AppWidgetManager appWidgetManager =context.getSystemService(AppWidgetManager.class);ComponentName myProvider =new ComponentName(context, MyAppWidgetProvider.class);if (appWidgetManager.isRequestPinAppWidgetSupported()) {// Create the PendingIntent object only if your app needs to be notified// that the user allowed the widget to be pinned. Note that, if the pinning// operation fails, your app isn't notified.Intent pinnedWidgetCallbackIntent = new Intent( ... );// Configure the intent so that your app's broadcast receiver gets// the callback successfully. This callback receives the ID of the// newly-pinned widget (EXTRA_APPWIDGET_ID).PendingIntent successCallback = PendingIntent.getBroadcast(context, 0,pinnedWidgetCallbackIntent, PendingIntent.FLAG_UPDATE_CURRENT);appWidgetManager.requestPinAppWidget(myProvider, null, successCallback);}

注意:如果无需通知您的应用系统是否已成功地将微件固定到受支持的启动器上,则您可以将 null 作为 requestPinAppWidget() 的第三个参数传入。

设置预览图片

Android 3.0 引入了 previewImage 字段,用于指定预览来描绘应用微件是什么样子的。此预览通过微件选择器显示给用户。如果未提供此字段,则应用微件的图标将用于预览。

在 XML 中指定此设置的方式如下:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"...android:previewImage="@drawable/preview"></appwidget-provider>

为了帮助创建应用微件的预览图片(在previewImage字段中指定),Android 模拟器包含一个名为“微件预览”的应用。要创建预览图片,请启动此应用,为您的应用选择应用微件并设置您希望如何显示预览图片,然后将其保存并放在您的应用的可绘制资源中。

完整代码

  1. ExampleAppWidgetProvider.java 文件
public class ExampleAppWidgetProvider extends AppWidgetProvider {private static final String TAG = "ExampleAppWidgetProvider";@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {Log.i(TAG, "onUpdate: ");for (int appWidgetId : appWidgetIds) {updateAppWidget(context, appWidgetManager, appWidgetId);}time = System.currentTimeMillis();}private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {RemoteViews view = new RemoteViews(context.getPackageName(), R.layout.widget_content);// 点击桌面组件中的按钮,跳转到主界面Intent i = new Intent(context, MainActivity.class);PendingIntent intent = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);view.setOnClickPendingIntent(R.id.btn_click, intent);
//        view.setTextViewText(R.id.tv_info, "clicked");appWidgetManager.updateAppWidget(appWidgetId, view);}
}
  1. layout/widget_content.xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn_click"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="click me"/><TextViewandroid:id="@+id/tv_info"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="hello, this is appwidget"android:layout_centerHorizontal="true"android:layout_alignParentBottom="true"/></RelativeLayout>
  1. xml/example_appwidget_info.xml文件
<?xml version="1.0" encoding="utf-8"?>
<appwidget-providerxmlns:android="http://schemas.android.com/apk/res/android"android:initialKeyguardLayout="@layout/widget_content"android:initialLayout="@layout/widget_content"android:minHeight="110dp"android:minWidth="180dp"android:previewImage="@drawable/ic_launcher_foreground"android:resizeMode="vertical|horizontal"android:updatePeriodMillis="600000"android:widgetCategory="home_screen"></appwidget-provider>
  1. AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.csu.mywidget"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.MyExample"><receiverandroid:name=".ExampleAppWidgetProvider"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE"/></intent-filter><meta-data android:name="android.appwidget.provider"android:resource="@xml/example_appwidget_info"/></receiver><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

参考:
https://developer.android.google.cn/guide/practices/ui_guidelines/widget_design
https://developer.android.google.cn/guide/topics/appwidgets#collection_sample
https://blog.csdn.net/tracydragonlxy/article/details/127231654?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127231654%22%2C%22source%22%3A%22tracydragonlxy%22%7D

这篇关于Android 创建桌面组件Widget——构建应用微件(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/807293

相关文章

使用Python在Excel中创建和取消数据分组

《使用Python在Excel中创建和取消数据分组》Excel中的分组是一种通过添加层级结构将相邻行或列组织在一起的功能,当分组完成后,用户可以通过折叠或展开数据组来简化数据视图,这篇博客将介绍如何使... 目录引言使用工具python在Excel中创建行和列分组Python在Excel中创建嵌套分组Pyt

nginx-rtmp-module构建流媒体直播服务器实战指南

《nginx-rtmp-module构建流媒体直播服务器实战指南》本文主要介绍了nginx-rtmp-module构建流媒体直播服务器实战指南,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. RTMP协议介绍与应用RTMP协议的原理RTMP协议的应用RTMP与现代流媒体技术的关系2

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

5分钟获取deepseek api并搭建简易问答应用

《5分钟获取deepseekapi并搭建简易问答应用》本文主要介绍了5分钟获取deepseekapi并搭建简易问答应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1、获取api2、获取base_url和chat_model3、配置模型参数方法一:终端中临时将加

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

MySQL分表自动化创建的实现方案

《MySQL分表自动化创建的实现方案》在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低,分表是一种有效的优化策略,它将数据分散存储在... 目录一、项目目的二、实现过程(一)mysql 事件调度器结合存储过程方式1. 开启事件调度器2. 创

四种Flutter子页面向父组件传递数据的方法介绍

《四种Flutter子页面向父组件传递数据的方法介绍》在Flutter中,如果父组件需要调用子组件的方法,可以通过常用的四种方式实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录方法 1:使用 GlobalKey 和 State 调用子组件方法方法 2:通过回调函数(Callb

mysql外键创建不成功/失效如何处理

《mysql外键创建不成功/失效如何处理》文章介绍了在MySQL5.5.40版本中,创建带有外键约束的`stu`和`grade`表时遇到的问题,发现`grade`表的`id`字段没有随着`studen... 当前mysql版本:SELECT VERSION();结果为:5.5.40。在复习mysql外键约

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element