转载请标明出处:http://blog.csdn.net/sk719887916/article/details/47027263
不少开发项目中都会有widget功能,别小瞧了它,他也是android的七大组件之一,对widget陌生的朋友可以阅读下我的上篇文章< Android Widget工作原理详解(一)>关于内部的介绍,还没掌握的同学不要担心,开发AppWidget套路很简单,今天我们就实现一个可以加入listView滑动的widget,熟悉下一个普通widget的开发步骤。
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// 获取Widget的组件名
ComponentName thisWidget = new ComponentName(context,
MyAppListWidgetProvider.class);
// 创建一个RemoteView
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.my_widget_layout);
// 把这个Widget绑定到RemoteViewsService
Intent intent = new Intent(context, MyRemoteViewsService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[0]);
// 设置适配器
remoteViews.setRemoteAdapter(R.id.widget_list, intent);
// 设置当显示的widget_list为空显示的View
remoteViews.setEmptyView(R.id.widget_list, R.layout.none_data);
// 点击列表触发事件
Intent clickIntent = new Intent(context, MyAppListWidgetProvider.class);
// 设置Action,方便在onReceive中区别点击事件
clickIntent.setAction(clickAction);
clickIntent.setData(Uri.parse(clickIntent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendingIntentTemplate = PendingIntent.getBroadcast(
context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setPendingIntentTemplate(R.id.widget_list,
pendingIntentTemplate);
// 刷新按钮
final Intent refreshIntent = new Intent(context,
MyAppListWidgetProvider.class);
refreshIntent.setAction("refresh");
final PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(
context, 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.button_refresh,
refreshPendingIntent);
// 更新Wdiget
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
/**
* 接收Intent
*/
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
if (action.equals("refresh")) {
// 刷新Widget
final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
final ComponentName cn = new ComponentName(context,
MyAppListWidgetProvider.class);
MyRemoteViewsFactory.mList.add("音乐"+i);
// 这句话会调用RemoteViewSerivce中RemoteViewsFactory的onDataSetChanged()方法。
mgr.notifyAppWidgetViewDataChanged(mgr.getAppWidgetIds(cn),
R.id.widget_list);
} else if (action.equals(clickAction)) {
// 单击Wdiget中ListView的某一项会显示一个Toast提示。
Toast.makeText(context, intent.getStringExtra("content"),
Toast.LENGTH_SHORT).show();
}
i=i+1;
}
@Override
public void onEnabled(Context context) {
// TODO Auto-generated method stub
super.onEnabled(context);
Toast.makeText(context, "用户将widget添加桌面了",
Toast.LENGTH_SHORT).show();
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
// TODO Auto-generated method stub。
Toast.makeText(context, "用户将widget从桌面移除了",
Toast.LENGTH_SHORT).show();
super.onDeleted(context, appWidgetIds);
}
public class MyRemoteViewsFactory implements RemoteViewsFactory {
private final Context mContext;
public static List mList = new ArrayList();
/*
* 构造函数
*/
public MyRemoteViewsFactory(Context context, Intent intent) {
mContext = context;
}
/*
* MyRemoteViewsFactory调用时执行,这个方法执行时间超过20秒回报错。
* 如果耗时长的任务应该在onDataSetChanged或者getViewAt中处理
*/
@Override
public void onCreate() {
// 需要显示的数据
mList.add("");
for (int i = 0; i < 5; i++) {
mList.add("item"+ i);
}
}
/*
* 当调用notifyAppWidgetViewDataChanged方法时,触发这个方法
* 例如:MyRemoteViewsFactory.notifyAppWidgetViewDataChanged();
*/
@Override
public void onDataSetChanged() {
}
/*
* 这个方法不用多说了把,这里写清理资源,释放内存的操作
*/
@Override
public void onDestroy() {
mList.clear();
}
/*
* 返回集合数量
*/
@Override
public int getCount() {
return mList.size();
}
/*
* 创建并且填充,在指定索引位置显示的View,这个和BaseAdapter的getView类似
*/
@Override
public RemoteViews getViewAt(int position) {
if (position < 0 || position >= mList.size())
return null;
String content = mList.get(position);
// 创建在当前索引位置要显示的View
final RemoteViews rv = new RemoteViews(mContext.getPackageName(),
R.layout.my_widget_layout_item);
// 设置要显示的内容
rv.setTextViewText(R.id.widget_list_item_tv, content);
// 填充Intent,填充在AppWdigetProvider中创建的PendingIntent
Intent intent = new Intent();
// 传入点击行的数据
intent.putExtra("content", content);
rv.setOnClickFillInIntent(R.id.widget_list_item_tv, intent);
return rv;
}
/*
* 显示一个"加载"View。返回null的时候将使用默认的View
*/
@Override
public RemoteViews getLoadingView() {
return null;
}
/*
* 不同View定义的数量。默认为1(本人一直在使用默认值)
*/
@Override
public int getViewTypeCount() {
return 1;
}
/*
* 返回当前索引的。
*/
@Override
public long getItemId(int position) {
return position;
}
/*
* 如果每个项提供的ID是稳定的,即她们不会在运行时改变,就返回true(没用过。。。)
*/
@Override
public boolean hasStableIds() {
return true;
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MyRemoteViewsService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new MyRemoteViewsFactory(this.getApplicationContext(), intent);
}
}