android4.0中实现AppWidget集合

1.准备appwidget的初始布局和预览视图等资源

AppWidget集合应用时,需配置两种布局文件:一个用于集合view布局显示,一个用于集合view上条目的的布局显示

注意:要设置empty views,以便匹配集合view的空状态,且该View必须是集合View(一般可为ListView、GridView、StackView或AdapterViewFlipper)的同级View

2.在res/xml中创建AppWidgetProviderInfo文件

根标签为appwiget-provider,其属性要包括initialLayout、previewImage、autoAdvanceViewId
等,具体可参考后面的例子

3.创建AppWidgetProvider的实现子类,并在清单文件里面注册引用的元数据和监听的广播action

清单文件中,需给该子类配置如下信息:

action
android:name="android.appwidget.action.APPWIDGET_UPDATE"

元数据:android:name="android.appwidget.provider"

代码中,onUpdate方法中完成Widget布局到桌面上时的刷新;onReceive方法中完成接收到特定广播后的Widget刷新

(另外,如果配置了Configure
Activity还需要注册action,"android.appwidget.action.APPWIDGET_CONFIGURE")

4.因为是集合Widget,需要创建一个继承了RemoteViewsService的Service子类,并在清单文件中注册权限,阻止其它程序自由访问Widget中的数据

android:permission="android.permission.BIND_REMOTEVIEWS"

代码中通过onGetViewFactory方法返回一个RemoteViewsFactory的实现类,该实现类中的onCreate()用来创建及初始化设置Widget的单个item;getViewAt()方法用来同步数据,进行耗时的更新操作,并返回RemoteView对象。

getViewAt方法中可完成:

<1>将显示独立Widget条目的view
item数据以fill-in
intent方式填充到集合Widget的View集合中

View集合中Chilid
view不允许使用setOnClickPendingIntent的点击事件动态更新,只能通过setOnClickFillInIntent来实现,

即先设置好集合view的pending
intent template点击事件模版,然后,将独立的chilid
view条目的the
fill-in Intent意图事件填充进来。

<2>进行耗时的处理图片和获取网络数据操作,并同步刷新Widget的显示内容。

RemoteViewsFactory的实现类中还有一个onDataSetChanged方法,也可进行耗时的处理图片和获取网络数据操作,但他可以保持Widget的当前状态,直到我们显示调用AppWidgetManager
notifyAppWidgetViewDataChanged才会触发

参考:ExampleStackViewAppWidgets

本例主要参考http://developer.android.com/resources/samples/StackWidget/index.html

在其基础上略有改进

appwidget_providerinfo.xml

<?xml
version="1.0" encoding="utf-8"?>

<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"

android:autoAdvanceViewId="@id/statck_view"

android:initialLayout="@layout/widget_layout"

android:minHeight="74dp"

android:minWidth="290dp"

android:previewImage="@drawable/doraemon"

android:updatePeriodMillis="3600000"

android:resizeMode="vertical">

</appwidget-provider>

StackViewAppWidgetService.java

/**

*
实现了给StackView上ImageView适配背景图片

*
@author wgyang

*

*/

public
class StackViewAppWidgetService extends RemoteViewsService {

@Override

public
RemoteViewsFactory onGetViewFactory(Intent intent) {

return
new ViewFlipperRemoteViewsFactory(this.getApplicationContext(),

intent);

}

}

class
ViewFlipperRemoteViewsFactory implements

RemoteViewsService.RemoteViewsFactory
{

int[]
images = { R.drawable.doraemon, R.drawable.baidu, R.drawable.bing,

R.drawable.google
};

//int[]
colors = { Color.BLUE, Color.RED, Color.GRAY, Color.GREEN };

private
static final int mCount = 4;

private
List<ImageView> mImageViews = new ArrayList<ImageView>();

private
Context mContext;

private
static ImageView mImageView;

public
ViewFlipperRemoteViewsFactory(Context context, Intent intent) {

mContext
= context;

}

public
void onCreate() {

//
In onCreate() you setup any connections / cursors to your data
source. Heavy lifting,

//
for example downloading or creating content etc, should be deferred
to onDataSetChanged()

//
or getViewAt(). Taking more than 20 seconds in this call will result
in an ANR.

//
因不是很耗时,可放在这里

//在循环里控制显示独立Widget条目的界面信息

for
(int i = 0; i < mCount; ++i) {

mImageView
= new ImageView(mContext);

//mImageView.setBackgroundColor(colors[i]);

//mImageView.setImageResource(images[i]);

mImageViews.add(mImageView);

}

// We sleep for 3 seconds here to show how the empty view appears
in the interim.

//
The empty view is set in the StackWidgetProvider and should be a
sibling of the

//
collection view.

}

public
RemoteViews getViewAt(int position) {

// position will always range from 0 to getCount() - 1.

//
We construct a remote views item based on our widget item xml file,
and set the

//
text based on the position.

//通过Remoteview给view
item上设置要显示内容

RemoteViews
rv = new RemoteViews(mContext.getPackageName(),

R.layout.widget_item);

//
rv.setTextViewText(R.id.widget_item,

//
mWidgetItems.get(position).text);

//rv.setImageViewResource(R.id.widget_item,
mImageViews.get(position)

// .getBackground().getLevel());

//注意要将单个的widget条目信息设置进rv中,不然刷新界面不成功的

rv.setImageViewBitmap(R.id.widget_item,
BitmapFactory.decodeResource(

mContext.getResources(),
images[position]));

// Next, we set a fill-intent which will be used to fill-in the
pending intent template

//
which is set on the collection view in StackWidgetProvider.

//item的位置信息设置到fillintent中

Bundle
extras = new Bundle();

extras.putInt(StackViewAppWidgetProvider.EXTRA_ITEM,
position);

//设置fill-intent以填充Pending
intent 模版

Intent
fillInIntent = new Intent();

fillInIntent.putExtras(extras);

rv.setOnClickFillInIntent(R.id.widget_item,
fillInIntent);

// You can do heaving lifting in here, synchronously. For example,
if you need to

//
process an image, fetch something from the network, etc., it is ok to
do it here,

//
synchronously. A loading view will show up in lieu of the actual
contents in the

//
interim.

//其它耗时操作可在这里完成

return
rv;

}

public
int getCount() {

return
mCount;

}

public
RemoteViews getLoadingView() {

// You can create a custom loading view (for instance when
getViewAt() is slow.) If you

//
return null here, you will get the default loading view.

return
null;

}

public
int getViewTypeCount() {

return
1;//注意下,初始是0,改变与否不影响

}

public
long getItemId(int position) {

return
position;

}

public
boolean hasStableIds() {

return
true;//注意下,原来是false,改变与否不影响

}

public
void onDataSetChanged() {

// This is triggered when you call AppWidgetManager
notifyAppWidgetViewDataChanged

//
on the collection view corresponding to this factory. You can do
heaving lifting in

//
here, synchronously. For example, if you need to process an image,
fetch something

//
from the network, etc., it is ok to do it here, synchronously. The
widget will remain

//
in its current state while work is being done here, so you don‘t need
to worry about

//
locking up the widget.

//耗时操作可放在这里,可显式触发

}

public
void onDestroy() {

//
In onDestroy() you should tear down anything that was setup for your
data source,

//
eg. cursors, connections, etc.

mImageViews.clear();

}

}

StackViewAppWidgetProvider.java

/**

*
StackView更新图片

*
定时接收广播,自动刷新view,另外监听点击事件,弹土司消息反馈点击的是哪一个条目

*
@author wgyang

*

*/

public
class StackViewAppWidgetProvider extends AppWidgetProvider {

public
static final String TOAST_ACTION =
"com.lenove.widgetcollection.TOAST_ACTION";

public
static final String EXTRA_ITEM =
"com.lenove.widgetcollection.EXTRA_ITEM";

@Override

public
void onReceive(Context context, Intent intent) {

if (intent.getAction().equals(TOAST_ACTION)) {

int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);

Toast.makeText(context, "Touched view " +
viewIndex, Toast.LENGTH_SHORT).show();

}

super.onReceive(context,
intent);

}

//
完成Widget布局到桌面上时的刷新

@Override

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

// update each of the widgets with the remote adapter

//遍历每个appWidgetId

for (int i = 0; i < appWidgetIds.length; ++i) {

//
Here we setup the intent which points to the StackViewService which
will

//
provide the views for this collection.

//指定启动到RemoteViewstService的Intent

Intent
intent = new Intent(context, StackViewAppWidgetService.class);

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetIds[i]);

//
When intents are compared, the extras are ignored, so we need to
embed the extras

//
into the data so that the extras will not be ignored.

//
嵌入数据到intent,以避免intent中的数据被忽略掉

intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

//借助RemoteView传递信息

RemoteViews
rv = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);

//注意,设置适配器

rv.setRemoteAdapter(appWidgetIds[i],
R.id.statck_view, intent);

//
The empty view is displayed when the collection has no items. It
should be a sibling

//
of the collection view.

//注意,设置空状态

rv.setEmptyView(R.id.statck_view,
R.id.empty_view);

//
Here we setup the a pending intent template. Individuals items of a
collection

//
cannot setup their own pending intents, instead, the collection as a
whole can

//
setup a pending intent template, and the individual items can set a
fillInIntent

//
to create unique before on an item to item basis.

//设置封装了操作信息的intnent--最终放到pendingIntentTemplate中

Intent
toastIntent = new Intent(context, StackViewAppWidgetProvider.class);

toastIntent.setAction(StackViewAppWidgetProvider.TOAST_ACTION);

toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetIds[i]);

intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

//设置延迟意图模版PendingIntentTemplete,加载到RemoteViews,最后由AppWidgetManager更新

PendingIntent
toastPendingIntent = PendingIntent.getBroadcast(context, 0,
toastIntent,

PendingIntent.FLAG_UPDATE_CURRENT);

rv.setPendingIntentTemplate(R.id.statck_view,
toastPendingIntent);

//如果有耗时的操作应该启动应该服务Service去完成

appWidgetManager.updateAppWidget(appWidgetIds[i],
rv);

}

super.onUpdate(context,
appWidgetManager, appWidgetIds);

}

}

摘自:http://wenku.baidu.com/view/aab74fa4b0717fd5360cdc4a.html

android4.0中实现AppWidget集合

时间: 2024-10-04 11:09:40

android4.0中实现AppWidget集合的相关文章

Android4.0中AppWidget的一些新玩意体验---RemoteViewsService

最近要把之前做的2.3上面的一些程序移植到4.0上面来,  几乎所有的AppWidget都是我一手操办, 所以这个玩意都是我弄. 我把Android2.3的代码直接拷到4.0的环境下面, 编译然后Push,  直接可以跑, 这是木有问题的.  但是我发现4.0上面有一些新东东是之前2.3上面没有的, 我也读了下官方的文档, 做了些demo, 这里总结给大家, 在以后需要做AppWidget的时候可以得心应手. 1: 应用列表中的预览图 如果你不想你的Widget在应用列表里面显示成那个丑机器人图

Android4.0中Alertdialog对话框点击边缘外部消失问题解决

在开发的时候遇到一个问题,就是一触摸对话框边缘外部,对话框会自动消失.这个问题很纠结啊,查找了一下发现从Android 4.0开始,AlertDialog有了变化,就是在触摸对话框边缘外部,对话框会自动消失,查了源码,找到解决办法: 研究其父类时候发现,可以设置这么一条属性,在AlertDialog.Builder.create()之后才能调用这两个方法 方法一: setCanceledOnTouchOutside(false);调用这个方法时,按对话框以外的地方不起作用.按返回键还起作用 方法

android4.0中在onCreate方法中findViewById()返回null

问题描述 我用findViewById为什么取不到控件,我是android初学者,还请各位前辈指点 解决方案1 大侠,你自己不是写在了Fragment里面么.......你在onResume里面写应该可以了 解决方案2 你加载的布局是activity_main,所以activity_main.xml需要有对应的id,你在fragment_main里找没用的. 解决方案3 引用 2 楼 svenwang 的回复: 你加载的布局是activity_main,所以activity_main.xml需要

android4.0蓝牙使能的详细解析

此博客是转载过来的哦... 给自己博客定几个部分: (1)写在前面的话:一些写博客时的废话. (2)内容简介:把文章的主要内容或者核心部分作一个框架性的概括,以方便大家阅读. (3)正文:这个不需要解释了.   写在前面的话:这是csdn上的第一篇博客,希望自己能够坚持写下去,也希望能够得到大家的支持.本文可能会涉及大量的源码注释,在文字方面可能不够尽如人意,希望真正想理解该过程的同学们能够耐心看下去. 内容简介:本文详细分析了android4.0中蓝牙使能的过程,相比较android2.3,4

Android4.0 Design之设计规范的十大革新

在拜读和翻译了Android design设计指导后,对比Android 4.0,4.1,4.4版本与Android2.3及之前版本的app设计指导,总结了Android 4.0版本后设计规范的10大改变之处,在此也感谢博友对我所写文章的支持,之前重要设计理念系列的文章阅读量最近一直在暴涨,也鼓动着我继续写该系列的文章. 一.导航栏 由之前的物理按键导航(返回.菜单.搜索.主页)变成了嵌入屏幕的虚拟按键(返回.主页.最近任务). 把菜单项和搜索项从导航栏去掉,把之前通过长按主页键才出现的历史打开

android4.0蓝牙使能的详细解析 (转载)

此博客是转载过来的哦... 给自己博客定几个部分: (1)写在前面的话:一些写博客时的废话. (2)内容简介:把文章的主要内容或者核心部分作一个框架性的概括,以方便大家阅读. (3)正文:这个不需要解释了.   写在前面的话:这是csdn上的第一篇博客,希望自己能够坚持写下去,也希望能够得到大家的支持.本文可能会涉及大量的源码注释,在文字方面可能不够尽如人意,希望真正想理解该过程的同学们能够耐心看下去. 内容简介:本文详细分析了android4.0中蓝牙使能的过程,相比较android2.3,4

一个Activity掌握Android4.0新控件 (转)

原文地址:http://blog.csdn.net/lavor_zl/article/details/51261380 谷歌在推出Android4.0的同时推出了一些新控件,Android4.0中最常用的新控件有下面5种. 1. Switch的使用 Switch顾名思义,就是开关的意思,有开和关两种状态. 当Switch处于关闭状态时: 当Switch处于打开状态时: 怎么在定义xml中定义Switch <Switch android:id="@+id/_switch" andr

android4.0蓝牙使能的详细解析(转)

源:http://www.cnblogs.com/xiaochao1234/p/3818193.html 本文详细分析了android4.0 中蓝牙使能的过程,相比较android2.3,4.0中的蓝牙最大的差别在于UI上on/off的伪开关.在android4.0中加入了 adapter的状态机.所谓的状态机就类似于状态转换图,在一个状态收到某个特定的命令会变成另外一个状态,不同的命令可以跳转到不同的状态(当然也有 可能到同一状态).adapter的初始状态为poweroff,在android

Android4.0新控件

谷歌在推出Android4.0的同时推出了一些新控件,Android4.0中最常用的新控件有下面5种.  1. Switch的使用 Switch顾名思义,就是开关的意思,有开和关两种状态. 当Switch处于关闭状态时:  当Switch处于打开状态时:  怎么在定义xml中定义Switch <Switch android:id="@+id/_switch" android:layout_width="match_parent" android:layout_