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 --