android API 11 RemoteViews 提供出一些新的方法,让我们可以在桌面widget上添加一些复杂界面元素。
比较有代表性的是 ListView。就此写贴做个记录与分享。
源码
http://download.csdn.net/detail/yarkey09/6513753
效果图
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yarkey.remoteviewstest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.yarkey.remoteviewstest.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="MyWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget" />
</receiver>
<service
android:name="MyWidgetService"
android:exported="false"
android:permission="android.permission.BIND_REMOTEVIEWS" >
</service>
</application>
</manifest>
请注意加入权限:android:permission="android.permission.BIND_REMOTEVIEWS
否则我们定义的Service不会onBind,待会Factory的代码就不会被调用。
AppWidgetProvider.java
package com.yarkey.remoteviewstest;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.widget.RemoteViews;
public class MyWidget extends AppWidgetProvider {
private static final String TAG = "MyWidget";
/** package */
static ComponentName getComponentName(Context context) {
return new ComponentName(context, MyWidget.class);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.d(TAG, "onUpdate");
performUpdate(context, appWidgetManager, appWidgetIds, null);
}
private void performUpdate(Context context, AppWidgetManager awm, int[] appWidgetIds, long[] changedEvents) {
for (int appWidgetId : appWidgetIds) {
Log.d(TAG, "appWidgetId = " + appWidgetId);
Intent intent = new Intent(context, MyWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.layout_widget);
views.setTextViewText(R.id.button1, "已更新");
views.setRemoteAdapter(R.id.listView1, intent);
awm.updateAppWidget(appWidgetId, views);
awm.notifyAppWidgetViewDataChanged(appWidgetId, R.id.listView1);
}
}
}
关键就是:views.setRemoteAdapter( int viewId, Intent intent )
这个方法在API 14才有。API 11相同方法 setRemoteAdapter( int appWidgetId, int viewId, Intent intent )
RemoteViewsService.java
package com.yarkey.remoteviewstest;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
public class MyWidgetService extends RemoteViewsService {
private static final boolean DB = true;
private static final String TAG = "MyWidgetService";
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
log("onGetViewFactory, intent=" + intent);
return new MyWidgetFactory(getApplicationContext(), intent);
}
public static class MyWidgetFactory implements RemoteViewsService.RemoteViewsFactory {
private Context mContext;
private String[] mFoods = new String[] { "Apple", "Banana", "Pear", "Handset", "People", "Bar", "Wind", "Song",
"Source code", "Screen", "Package", "Cup", "Computer" };
// 构造
public MyWidgetFactory(Context context, Intent intent) {
log("MyWidgetFactory");
mContext = context;
}
@Override
public int getCount() {
log("getCount");
return mFoods.length;
}
@Override
public long getItemId(int position) {
log("getItemId");
return position;
}
// 在调用getViewAt的过程中,显示一个LoadingView。
// 如果return null,那么将会有一个默认的loadingView
@Override
public RemoteViews getLoadingView() {
log("getLoadingView");
return null;
}
@Override
public RemoteViews getViewAt(int position) {
log("getViewAt, position=" + position);
if (position < 0 || position >= getCount()) {
return null;
}
RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.layout_item);
views.setTextViewText(R.id.textView1, mFoods[position]);
return views;
}
@Override
public int getViewTypeCount() {
log("getViewTypeCount");
return 1;
}
@Override
public boolean hasStableIds() {
log("hasStableIds");
return true;
}
@Override
public void onCreate() {
log("onCreate");
}
@Override
public void onDataSetChanged() {
log("onDataSetChanged");
}
@Override
public void onDestroy() {
log("onDestroy");
}
}
private static void log(String log) {
if (DB)
Log.d(TAG, log);
}
}
有点类似BaseAdapter, getCount(), getViewAt()
-- end --