Basically, you need to use two components:
- RemoteViewsFactory: This is the especial adapter.
- RemoteViewsService: This is to return the first one.
Let's create the RemoteViewsFactory class:
public class MyWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private Context mContext;
private Cursor mCursor;
public MyWidgetRemoteViewsFactory(Context applicationContext, Intent intent) {
mContext = applicationContext;
}
@Override
public void onCreate() {
}
@Override
public void onDataSetChanged() {
if (mCursor != null) {
mCursor.close();
}
final long identityToken = Binder.clearCallingIdentity();
Uri uri = Contract.PATH_TODOS_URI;
mCursor = mContext.getContentResolver().query(uri,
null,
null,
null,
Contract._ID + " DESC");
Binder.restoreCallingIdentity(identityToken);
}
@Override
public void onDestroy() {
if (mCursor != null) {
mCursor.close();
}
}
@Override
public int getCount() {
return mCursor == null ? 0 : mCursor.getCount();
}
@Override
public RemoteViews getViewAt(int position) {
if (position == AdapterView.INVALID_POSITION ||
mCursor == null || !mCursor.moveToPosition(position)) {
return null;
}
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.collection_widget_list_item);
rv.setTextViewText(R.id.widgetItemTaskNameLabel, mCursor.getString(1));
return rv;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public long getItemId(int position) {
return mCursor.moveToPosition(position) ? mCursor.getLong(0) : position;
}
@Override
public boolean hasStableIds() {
return true;
}
}
Now it's time for the RemoteViewsService (the easy one):
public class MyWidgetRemoteViewsService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new MyWidgetRemoteViewsFactory(this.getApplicationContext(), intent);
}
}
Also you must register this service in the androidManifest.xml:
<service android:name=".AppWidget.MyWidgetRemoteViewsService"
android:permission="android.permission.BIND_REMOTEVIEWS"></service>
And now in your Widget class which extends AppWidgetProvider, you can manage the layouts:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
RemoteViews views = new RemoteViews(
context.getPackageName(),
R.layout.collection_widget
);
Intent intent = new Intent(context, MyWidgetRemoteViewsService.class);
views.setRemoteAdapter(R.id.widgetListView, intent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
Now create a new resource file in res/xml and name it collection_widget.xml:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:updatePeriodMillis="864000"
android:previewImage="@drawable/simple_widget_preview"
android:initialLayout="@layout/collection_widget"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen">
</appwidget-provider>
We need to create two more files in res/layout to define the layout of the list and the layout of each list item.
collection_widget.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorWhite"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<FrameLayout android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="match_parent"
android:id="@+id/widgetTitleLabel"
android:text="@string/title_collection_widget"
android:textColor="@color/colorWhite"
android:background="@color/colorPrimary"
android:textSize="18dp"
android:gravity="center"
android:textAllCaps="true"
android:layout_height="@dimen/widget_title_min_height"></TextView>
</FrameLayout>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView android:id="@+id/widgetListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWhite"
android:dividerHeight="1dp"
android:divider="#eeeeee"
tools:listitem="@layout/collection_widget_list_item"></ListView>
</LinearLayout>
</LinearLayout>
collection_widget_list_item.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:paddingLeft="@dimen/widget_listview_padding_x"
android:paddingRight="@dimen/widget_listview_padding_x"
android:paddingStart="@dimen/widget_listview_padding_x"
android:paddingEnd="@dimen/widget_listview_padding_x"
android:minHeight="@dimen/widget_listview_item_height"
android:weightSum="2"
android:id="@+id/widgetItemContainer"
android:layout_height="wrap_content">
<TextView android:id="@+id/widgetItemTaskNameLabel"
android:layout_width="wrap_content"
android:gravity="start"
android:layout_weight="1"
android:textColor="@color/text"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"></TextView>
</LinearLayout>
I use this article like example and works like a charm for me!!
https://www.sitepoint.com/killer-way-to-show-a-list-of-items-in-android-collection-widget/
Now a days, this is not that rare. Hope to help someone.