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控件入门详解的更多相关文章

  1. Android开发之基本控件和详解四种布局方式

    Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...

  2. android开发之wheel控件使用详解

    出门在外生不起病呀,随便两盒药60多块钱.好吧,不废话了,今天我们来看看wheel控件的使用,这是GitHub上的一个开源控件,用起来十分方便,我们可以用它做许多事情,比如做一个自定义的datepic ...

  3. 【转】【Android UI设计与开发】之详解ActionBar的使用,androidactionbar

    原文网址:http://www.bkjia.com/Androidjc/895966.html [Android UI设计与开发]之详解ActionBar的使用,androidactionbar 详解 ...

  4. WebBrowser控件使用详解

    原文:WebBrowser控件使用详解 方法 说明 GoBack 相当于IE的“后退”按钮,使你在当前历史列表中后退一项 GoForward 相当于IE的“前进”按钮,使你在当前历史列表中前进一项 G ...

  5. 串口通信-MSComm控件使用详解

    串口通信-MSComm控件使用详解 2012年11月13日 09:35:45 他山之石可以攻玉 阅读数:37952更多 个人分类: 控件编程Delphi编程   MSComm 控件通过串行端口传输和接 ...

  6. Flash播放控件属性详解

    Flash 播放控件属性详解 一.属性篇 1.AlignMode(读写)  语法:AlignMode As Long  说明:对齐方式(与SAlign 属性联动).当控件的长宽比例与影片不一致且WMo ...

  7. 让我们创建屏幕- Android UI布局和控件

    下载LifeCycleTest.zip - 278.9 KB 下载ViewAndLayoutLessons_-_Base.zip - 1.2 MB 下载ViewAndLayoutLessons_-_C ...

  8. Android UI学习1:控件和基本事件的响应

    在任何一个 GUI 系统中,控制界面上的控件(通常称为控件)都是一个基本的内容.对于 Android 应用程序,控件称为 View. 在 Android 中,在处理 UI 中的各种元素的时候,两个程序 ...

  9. 安卓开发:UI组件-图片控件ImageView(使用Glide)和ScrollView

    2.7ImageView 2.7.1插入本地图片 一个图片控件,可以用来显示本地和网络图片. 在首页添加按钮ImageView,指向新页面(步骤与前同,不再详写). activity_image_vi ...

随机推荐

  1. Android ViewPager滑动背景渐变

    原理 总 布局为RelativeLayout或者FrameLayout,在这里我们用的是RelativeLayout.先设置背景图片,宽度和高度都 fill_parent,在设置viewpager,v ...

  2. C# DataTable的詳細用法

    转载别人的转载,原作者都不知道了 在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一 ...

  3. Java程序员必须掌握的8大排序算法

    分类: 1)插入排序(直接插入排序.希尔排序)2)交换排序(冒泡排序.快速排序)3)选择排序(直接选择排序.堆排序)4)归并排序5)分配排序(基数排序) 所需辅助空间最多:归并排序所需辅助空间最少:堆 ...

  4. Java--设计模式心得体会

    1.策略模式: 策略模式就是将能够通用的算法,封装成不同的组件,实现同一个接口,使之可以互换. 例子:SpringMVC的9大组件,都采用策略模式.比如HandlerMethodArgumentRes ...

  5. spring入门(三)【事务控制】

    在开发中需要操作数据库,进行增.删.改操作的过程中属于一次操作,如果在一个业务中需要更新多张表,那么任意一张表的更新失败,整个业务的更新就是失败,这时那些更新成功的表必须回滚,否则业务会出错,这时就要 ...

  6. Atitit.atiagent  agent分销系统 代理系统 设计文档

    Atitit.atiagent  agent分销系统 代理系统 设计文档 1. 启动项目1 2. 首也2 3. 登录功能2 4. 用户中心2 5. 充值查询3 6. 授权下级代理4 7. 我的提成5 ...

  7. 浅入浅出dubbo

    1. Dubbo是什么? 只是一个框架 Hibernate是持久层框架,SpringMVC是MVC的框架,而Dubbo是分布式服务框架. 是框架而不是服务 所以不是像Tomcat或Memcached可 ...

  8. jQuery LayDate 日期控件

    她基于原生JavaScript精心雕琢,兼容了包括IE6在内的所有主流浏览器.她具备优雅的内部代码,良好的性能体验,和完善的皮肤体系,并且完全开源,你可以任意获取开发版源代码,一扫某些传统日期控件的封 ...

  9. 滚动变色的文字js特效

    Js实现滚动变色的文字效果,在效果展示页面,可看到文字在交替变色显示,以吸引人的注意,效果真心不错哦,把代码拷贝到你的网站后,修改成想要的文字就OK了. 查看效果:http://keleyi.com/ ...

  10. Microsoft Visual C++ Compiler for Python

    Visual C++ |CPython ------------------------------------------- 14.0(2015) |3.5 10.0(2010) |3.3, 3.4 ...