I am building a collection Widget backed by a ViewFlipper
, and ran into a snag when following the Android docs on adding behavior to individual items.
I want to create two arrows which move the ViewFlipper
to its previous and next views, as shown in this mockup:
In my WidgetService
's getViewAt()
method, I have the following code to create a fill in intent:
final Intent fillInIntent = new Intent();
final Bundle bundle = new Bundle();
bundle.putInt(WidgetProvider.EXTRA_ID, mWidgetItems.get(position));
fillInIntent.putExtras(bundle);
remoteViews.setOnClickFillInIntent(R.id.btn_widget_next, fillInIntent);
remoteViews.setOnClickFillInIntent(R.id.btn_widget_previous, fillInIntent);
And then in my WidgetProvider
I have this:
// Adding collection list item handler
final Intent onItemClick = new Intent(context, WidgetProvider.class);
onItemClick.setAction(NAVIGATE);
onItemClick.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id)
onItemClick.setData(Uri.parse(onItemClick.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent onClickPendingIntent = PendingIntent
.getBroadcast(context, id, onItemClick,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setPendingIntentTemplate(R.id.widget_view_flipper, onClickPendingIntent);
What confuses me about the design here is whether or not I am supposed to be calling setOnClickFillInIntent
on each button. If I do set the intent on each button, I need a way of determining which button was clicked in my WidgetProvider
's onUpdate
method (all I have now is the position of the view in the ViewFlipper
). I wasn't able to find an example of a Widget that uses click listeners for more than one action unfortunately.
The documentation you linked to is a bit misleading with the following sentence:
Your RemoteViewsFactory must set a fill-in intent on each item in the collection.This makes it possible to distinguish the individual on-click action of a given item
Well, you never really know until you try: it is possible after all to set fill-in-intents on individual children of the RemoteViews
item. But you have to use a separate Intent
for each of the buttons. I'll show how for the NEXT-button:
final Intent fillInIntent = new Intent();
final Bundle bundle = new Bundle();
bundle.putInt(WidgetProvider.EXTRA_ID, mWidgetItems.get(position));
bundle.putBoolean("FLIP_TO_NEXT", true);
fillInIntent.putExtras(bundle);
remoteViews.setOnClickFillInIntent(R.id.btn_widget_next, fillInIntent);
Then you have to check the Intent
action (NAVIGATE) as well as the value of intent.getBooleanExtra("FLIP_TO_NEXT", false)
in onReceive()
and update the app widget accordingly. For example if "NEXT" was clicked:
ComponentName me = new ComponentName(this, ViewFlipperWidget.class);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
int appWidgetID = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (appWidgetID != AppWidgetManager.INVALID_APPWIDGET_ID)
{
RemoteViews rv = new RemoteViews(getPackageName(), R.layout.view_flipper_widget);
if (intent.getBooleanExtra("FLIP_TO_NEXT", false))
{
rv.showNext(R.id.viewFlipper);
}
else
{
rv.showPrevious(R.id.viewFlipper);
}
appWidgetManager.updateAppWidget(appWidgetID, rv);
}