ANDROID APP WIDGET WITH LISTVIEW
Thân bài Để làm một widget với một listview bao gồm các thành phần: 1: AppWidgetProvider Được extend từ BroadcastReceiver được dùng đến như một controlled . Bao gồm 3 method +Widget Update :được gọi khi update widget +Widget Delete :được gọi khi xóa một widget +Widget enabled/disabled ...
Thân bài
Để làm một widget với một listview bao gồm các thành phần:
1: AppWidgetProvider
Được extend từ BroadcastReceiver được dùng đến như một controlled .
Bao gồm 3 method
+Widget Update :được gọi khi update widget
+Widget Delete :được gọi khi xóa một widget
+Widget enabled/disabled :được gọi khi tất cả widget bị xóa hay mở
Tiếp theo cần một file config xml
Mỗi một widget cần phải có một file widgetinfo.xml được đặt trong res/xml
widgetinfo.xml <?xml version="1.0" encoding="utf-8"?> android:configure="com.tienbm.ConfigActivity" android:initialLayout="@layout/widget_layout" android:minHeight="110dip" android:minWidth="250dip" android:previewImage="@drawable/widget_preview" android:resizeMode="vertical|horizontal" android:updatePeriodMillis="1800000"/>
Tiếp theo cần thêm một khai báo trên AndroidManifest.xml
<receiver android:name=".WidgetProvider" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widgetinfo" /> </receiver>
Tao layout cho widget
widget_layout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_awidth="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@android:color/black" > <ListView android:id="@+id/listViewWidget" android:layout_awidth="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/empty_view" android:layout_awidth="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="@string/empty_string" android:textColor="#ffffff" android:textSize="20sp" android:visibility="gone" /> </LinearLayout>
Ngay bây giờ để listview có thể hoạt động thì phải cần data và adapter
2:RemoteViewsService:
Để gọi một adapter bắt buộc phải thông qua một service.Ở đây bạn cũng có thể get data từ một nguồn nào đó rồi truyền vào adapter
public class WidgetService extends RemoteViewsService { /* * So pretty simple just defining the Adapter of the listview * here Adapter is ListProvider * */ @Override public RemoteViewsFactory onGetViewFactory(Intent intent) { int appWidgetId = intent.getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); return (new ListProvider(this.getApplicationContext(), intent)); } }
Tạo xog service mở file AndroidManifest.xml và thêm khai báo
<service android:name=".WidgetService" android:permission="android.permission.BIND_REMOTEVIEWS" /
3:RemoteViewsFactory:
Cũng giống như adapter của listview
/** * If you are familiar with Adapter of ListView,this is the same as adapter * with few changes * */ public class ListProvider implements RemoteViewsFactory { private ArrayList listItemList = new ArrayList(); private Context context = null; private int appWidgetId; public ListProvider(Context context, Intent intent) { this.context = context; appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); populateListItem(); } private void populateListItem() { for (int i = 0; i < 10; i++) { ListItem listItem = new ListItem(); listItem.heading = "Heading" + i; listItem.content = i + " This is the content of the app widget listview."; listItemList.add(listItem); } } @Override public int getCount() { return listItemList.size(); } @Override public long getItemId(int position) { return position; } /* *Similar to getView of Adapter where instead of View *we return RemoteViews * */ @Override public RemoteViews getViewAt(int position) { final RemoteViews remoteView = new RemoteViews( context.getPackageName(), R.layout.list_row); ListItem listItem = listItemList.get(position); remoteView.setTextViewText(R.id.heading, listItem.heading); remoteView.setTextViewText(R.id.content, listItem.content); return remoteView; } }
Cuối cùng là AppWidgetProvider
WidgetProvider.java public class WidgetProvider extends AppWidgetProvider { /** * this method is called every 30 mins as specified on widgetinfo.xml * this method is also called on every phone reboot **/ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) { /*int[] appWidgetIds holds ids of multiple instance * of your widget * meaning you are placing more than one widgets on * your homescreen*/ for (int i = 0; i <appWidgetIds.length; ++i) { RemoteViews remoteViews = updateWidgetListView(context, appWidgetIds[i]); appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews); } super.onUpdate(context, appWidgetManager, appWidgetIds); } private RemoteViews updateWidgetListView(Context context, int appWidgetId) { //which layout to show on widget RemoteViews remoteViews = new RemoteViews( context.getPackageName(),R.layout.widget_layout); //RemoteViews Service needed to provide adapter for ListView Intent svcIntent = new Intent(context, WidgetService.class); //passing app widget id to that RemoteViews Service svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); //setting a unique Uri to the intent //don't know its purpose to me right now svcIntent.setData(Uri.parse( svcIntent.toUri(Intent.URI_INTENT_SCHEME))); //setting adapter to listview of the widget remoteViews.setRemoteAdapter(appWidgetId, R.id.listViewWidget, svcIntent); //setting an empty view in case of no data remoteViews.setEmptyView(R.id.listViewWidget, R.id.empty_view); return remoteViews; } }
Tiếp theo để refesh từ một button widget ta sử dụng một intent được thêm vào updateWidgetListView như sau
Intent intent = new Intent(context, WidgetProvider .class); intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0, intent, PendingIntent.FLAG_UPDATE_CURRENT); //R.id.actionButton:id của button remoteViews.setOnClickPendingIntent(R.id.actionButton, pendingIntent);
Chú ý
Dùng để update cho toàn bộ widget intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
Chỉ update widget hiện tại intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
Refesh từ một activity
Intent intent = new Intent(this, WidgetProvider.class); intent.setAction("android.appwidget.action.APPWIDGET_UPDATE"); int ids[] = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), WidgetProvider.class)); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,ids); sendBroadcast(intent);
Kết bài
Vậy là đã hoàn thành một widget.