Android UI组件----AppWidget控件入门详解
Widget引入
我们可以把Widget理解成放置在桌面上的小组件(挂件),有了Widget,我们可以很方便地直接在桌面上进行各种操作,例如播放音乐。
当我们长按桌面时,可以看到Widget选项,如下图所示:

点击上图中箭头处的widgets图标,会出现如下界面:(都是widget)

长按上图中的任意一个widget,就可以将其放到桌面上。
Widget的使用
Widget的实现思路
(1)在AndroidManifest中声明AppWidget;
(2)在xml目录中定义AppWidget的配置文件;
(3)在layout目录中定义Widget的布局文件;
(4)新建一个类,继承AppWidgetProvider类,实现具体的widget业务逻辑。
我们需要新建一个类,继承AppWidgetProvider。点开AppWidgetProvider,发现AppWidgetProvider竟然是继承自BroadcastReceiver。
为什么Widget是一个广播接收器呢?我们知道,BroadcastReceiver类中有一个onReceive方法,用来接收广播。当我们在桌面挂件上去做操作时,必然引起应用的改变,这就涉及到挂件和应用之间的通信,此时用广播来通信是再好不过了。
Widget的具体使用步骤
(1)新建一个类TestWidget.java,继承AppWidgetProvider:
TestWidget.java:
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
/**
* Created by smyhvae on 2016/9/7.
*/
public class TestWidget extends AppWidgetProvider{
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
}
(2)因为Widget是一个广播接收器,所以我们需要在清单文件中注册:
<!-- 声明widget对应的AppWidgetProvider -->
<receiver android:name=".TestWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@layout/widget_setting"/>
</receiver>
04行:action是过滤条件,用来过滤行为,监测widget的更新。
08行:android:resource指定了widget的配置。我们知道,属性在清单文件中是用来存储数据的。
(3)layout文件夹中新建文件widget_setting.xml:(widget的配置文件)
setting_widget.xml:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:initialLayout="@layout/layout_widget"
android:minHeight="140dp"
android:minWidth="140dp"
android:previewImage="@mipmap/ic_launcher"
android:updatePeriodMillis="20000"
android:widgetCategory="home_screen"
>
</appwidget-provider>
08行: android:initialLayout 指定了widget的布局。
09行:android:updatePeriodMillis 指定更新的时间周期
10行: android:widgetCategory="home_screen" 将widget显示在主屏幕上(也可以显示在锁屏上)
(4)layout文件夹中新建文件layout_widget.xml:(widget的布局)
layout_widget.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="New Button"/>
</LinearLayout>
到此,程序就可以跑起来了。运行程序之后,长按桌面,点开"Widget"按钮,可以看到我们刚刚设计出的widget:

长按上图中的箭头处,就可以将我们设计出的widget拖放到桌面上了:

Widget的点击和更新【重要】
我们知道,TestWidget.java继承自AppWidgetProvider,而AppWidgetProvider在继承BroadcastReceiver之后,重写onReceive方法,然后还自定义了很多方法:

上图中,包含了被删除时、被禁用时、被启用时、被更新时等各种方法。尤其重要的是onReceive()方法和onUpDate()方法。
当小部件被改变时(比如被安装到桌面),系统会发送一个更新的广播(上图红框部分所示)。我们在setting_widget.xml中设置了widget的更新频率,这个也会调用更新。
有人可能会问,我开机之后,天气等widget为何不更新了?这是因为进程被杀死了,那我们只能把这个控件先移除,然后再装上,此时应用会发update更新的广播。
当需要做widget的点击和更新时,我们需要在需要重写onUpdate()方法,用来发送广播。当程序初始化的时候,系统就会调用onUpdate()方法。
onUpdate()方法中的代码如下:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//需要构造一个RemoteViews
Intent intent = new Intent();
intent.setClass(context, TestWidget.class); //通过intent把广播发给TestWidget本身,TestWidget接受到广播之后,会调用onReceive()方法进而刷新界面。
intent.setAction(WIDGET_BTN_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.widget_btn, pendingIntent);//控件btn_widget的点击事件:点击按钮时,会发一个带action的广播。
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); //点击完了之后,记得更新一下。
}
代码解释:
首先需要new一个RemoteViews,构造方法里需要传递两个参数,一个是包名(context.getPacakgeName),一个是布局文件(layout_widget)。
然后通过remoteViews.setOnClickPendingIntent()设置按钮的点击事件。setOnClickPendingIntent()中需要传递两个参数:一个是id(比如需要被点击的button),一个是PendingIntent。PendingIntent是未来的意图。
于是我们需要事先构造一个PendingIntent,这个需要通过 PendingIntent.getBroadcast()来构造。getBroadcast()方法中需要传递四个参数,其中有一个是Intent。
于是我们需要构造一个Intent。在intent里发送广播,并设置Action。
按钮点击完了之后,记得调用appWidgetManager.updateAppWidget(int[] appWidgetIds, RemoteViews views)方法更新一下,第一个参数就是onUpdate方法中的参数,代表的是所有的控件。
在onUpdate()方法中通过intent发送按钮点击时间的广播之后,我们需要在onReceive()方法中进行广播的接收。
onReceive()方法中的代码如下:
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent != null && TextUtils.equals(intent.getAction(), WIDGET_BTN_ACTION)) { //当intent不为空,且action匹配成功时,就接收广播,然后点击事件成功
Log.i(WIDGET_BTN_ACTION, "is clicked");
//接下来开始做点击事件里面的内容
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//注意:需要【重新】构造一个RemoteViews
remoteViews.setTextViewText(R.id.widget_tv, "be clicked");
remoteViews.setTextColor(R.id.widget_tv, Color.RED);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);// 单例模式
ComponentName componentName = new ComponentName(context, TestWidget.class);
appWidgetManager.updateAppWidget(componentName, remoteViews);//setText之后,记得更新一下
}
}
代码解释:
当intent的action匹配成功时,开始执行做点击时间之后的setText,不过这里需要重新new 一个 RemoteViews,而不能共用onUpdate()方法中的RemoteViews(这是一个很大的坑)。
执行完点击事件之后的setText之后,记得调用appWidgetManager.updateAppWidget(ComponentName, RemoteViews)方法,第一个参数为组件名,需要我们自己new一下,第二个参数很好解释。
综合来说,TestWidget.java的完整版代码如下:
Testwidget.java:
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;
/**
* Created by smyhvae on 2016/9/7.
*/
public class TestWidget extends AppWidgetProvider {
public static final String WIDGET_BTN_ACTION = "widget_btn_action";
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent != null && TextUtils.equals(intent.getAction(), WIDGET_BTN_ACTION)) { //当intent不为空,且action匹配成功时,就接收广播,然后点击事件成功
Log.i(WIDGET_BTN_ACTION, "is clicked");
//接下来开始做点击事件里面的内容
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//注意:需要【重新】构造一个RemoteViews
remoteViews.setTextViewText(R.id.widget_tv, "be clicked");
remoteViews.setTextColor(R.id.widget_tv, Color.RED);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);// 单例模式
ComponentName componentName = new ComponentName(context, TestWidget.class);
appWidgetManager.updateAppWidget(componentName, remoteViews);//setText之后,记得更新一下
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//需要构造一个RemoteViews
Intent intent = new Intent();
intent.setClass(context, TestWidget.class); //通过intent把广播发给TestWidget本身,TestWidget接受到广播之后,会调用onReceive()方法进而刷新界面。
intent.setAction(WIDGET_BTN_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.widget_btn, pendingIntent);//控件btn_widget的点击事件:点击按钮时,会发一个带action的广播。
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); //点击完了之后,记得更新一下。
}
}
运行之后,把widget拖到桌面上,效果如下:

点击按钮后,效果如下:

工程文件:(Android Studio 2.1)http://download.csdn.net/detail/smyhvae/9624840
当然,widget还有很多其他的用途。比如:
- 与Service进行通信
- widget控件的交互方法。
- 如何做一个桌面播放器Widget
参考链接:
Android 之窗口小部件详解--App Widget:http://www.cnblogs.com/skywang12345/p/3158310.html
Android UI组件----AppWidget控件入门详解的更多相关文章
- Android开发之基本控件和详解四种布局方式
Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...
- android开发之wheel控件使用详解
出门在外生不起病呀,随便两盒药60多块钱.好吧,不废话了,今天我们来看看wheel控件的使用,这是GitHub上的一个开源控件,用起来十分方便,我们可以用它做许多事情,比如做一个自定义的datepic ...
- 【转】【Android UI设计与开发】之详解ActionBar的使用,androidactionbar
原文网址:http://www.bkjia.com/Androidjc/895966.html [Android UI设计与开发]之详解ActionBar的使用,androidactionbar 详解 ...
- WebBrowser控件使用详解
原文:WebBrowser控件使用详解 方法 说明 GoBack 相当于IE的“后退”按钮,使你在当前历史列表中后退一项 GoForward 相当于IE的“前进”按钮,使你在当前历史列表中前进一项 G ...
- 串口通信-MSComm控件使用详解
串口通信-MSComm控件使用详解 2012年11月13日 09:35:45 他山之石可以攻玉 阅读数:37952更多 个人分类: 控件编程Delphi编程 MSComm 控件通过串行端口传输和接 ...
- Flash播放控件属性详解
Flash 播放控件属性详解 一.属性篇 1.AlignMode(读写) 语法:AlignMode As Long 说明:对齐方式(与SAlign 属性联动).当控件的长宽比例与影片不一致且WMo ...
- 让我们创建屏幕- Android UI布局和控件
下载LifeCycleTest.zip - 278.9 KB 下载ViewAndLayoutLessons_-_Base.zip - 1.2 MB 下载ViewAndLayoutLessons_-_C ...
- Android UI学习1:控件和基本事件的响应
在任何一个 GUI 系统中,控制界面上的控件(通常称为控件)都是一个基本的内容.对于 Android 应用程序,控件称为 View. 在 Android 中,在处理 UI 中的各种元素的时候,两个程序 ...
- 安卓开发:UI组件-图片控件ImageView(使用Glide)和ScrollView
2.7ImageView 2.7.1插入本地图片 一个图片控件,可以用来显示本地和网络图片. 在首页添加按钮ImageView,指向新页面(步骤与前同,不再详写). activity_image_vi ...
随机推荐
- Android ViewPager滑动背景渐变
原理 总 布局为RelativeLayout或者FrameLayout,在这里我们用的是RelativeLayout.先设置背景图片,宽度和高度都 fill_parent,在设置viewpager,v ...
- C# DataTable的詳細用法
转载别人的转载,原作者都不知道了 在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一 ...
- Java程序员必须掌握的8大排序算法
分类: 1)插入排序(直接插入排序.希尔排序)2)交换排序(冒泡排序.快速排序)3)选择排序(直接选择排序.堆排序)4)归并排序5)分配排序(基数排序) 所需辅助空间最多:归并排序所需辅助空间最少:堆 ...
- Java--设计模式心得体会
1.策略模式: 策略模式就是将能够通用的算法,封装成不同的组件,实现同一个接口,使之可以互换. 例子:SpringMVC的9大组件,都采用策略模式.比如HandlerMethodArgumentRes ...
- spring入门(三)【事务控制】
在开发中需要操作数据库,进行增.删.改操作的过程中属于一次操作,如果在一个业务中需要更新多张表,那么任意一张表的更新失败,整个业务的更新就是失败,这时那些更新成功的表必须回滚,否则业务会出错,这时就要 ...
- Atitit.atiagent agent分销系统 代理系统 设计文档
Atitit.atiagent agent分销系统 代理系统 设计文档 1. 启动项目1 2. 首也2 3. 登录功能2 4. 用户中心2 5. 充值查询3 6. 授权下级代理4 7. 我的提成5 ...
- 浅入浅出dubbo
1. Dubbo是什么? 只是一个框架 Hibernate是持久层框架,SpringMVC是MVC的框架,而Dubbo是分布式服务框架. 是框架而不是服务 所以不是像Tomcat或Memcached可 ...
- jQuery LayDate 日期控件
她基于原生JavaScript精心雕琢,兼容了包括IE6在内的所有主流浏览器.她具备优雅的内部代码,良好的性能体验,和完善的皮肤体系,并且完全开源,你可以任意获取开发版源代码,一扫某些传统日期控件的封 ...
- 滚动变色的文字js特效
Js实现滚动变色的文字效果,在效果展示页面,可看到文字在交替变色显示,以吸引人的注意,效果真心不错哦,把代码拷贝到你的网站后,修改成想要的文字就OK了. 查看效果:http://keleyi.com/ ...
- Microsoft Visual C++ Compiler for Python
Visual C++ |CPython ------------------------------------------- 14.0(2015) |3.5 10.0(2010) |3.3, 3.4 ...