Widget ListView con múltiples intentos pendientes

Estoy usando widget con listview que tiene 3 tipos de elementos. Para cada tipo de artículo debo usar diferentes intenciones pendientes. Actualmente utilizo código siguiente:

public class MyWidgetProvider extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager widgetManager, int[] widgetIds) { for (int widgetId : widgetIds) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_view); bindEmptyView(remoteViews); bindRemoteAdapter(context, widgetId, remoteViews); bindIntentTemplate(context, widgetId, remoteViews); widgetManager.updateAppWidget(widgetId, remoteViews); } } private void bindEmptyView(RemoteViews remoteViews) { remoteViews.setEmptyView(android.R.id.list, android.R.id.empty); } private void bindRemoteAdapter(Context context, int widgetId, RemoteViews remoteViews) { Intent intent = new Intent(context, MyViewService.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); remoteViews.setRemoteAdapter(android.R.id.list, intent); } private void bindIntentTemplate(Context context, int widgetId, RemoteViews remoteViews) { Intent intent = new Intent(context, MyActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); PendingIntent template = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setPendingIntentTemplate(android.R.id.list, template); } } 

A partir de este punto no entiendo cómo puedo invocar la intención específica de los diferentes elementos de la lista.

One Solution collect form web for “Widget ListView con múltiples intentos pendientes”

Espero haber entendido bien su problema, así que trataré de explicar brevemente lo que está sucediendo y cómo manejar los clics en los elementos de la lista en el widget.

Supongo que ya sabes que tienes que implementar una clase que:

 extends BroadcastReceiver implements RemoteViewsService.RemoteViewsFactory 

Esto servirá como el "adaptador" para ListView de su widget (llamémosle MyListRemoteViewFactory). Si desea manejar clics de elementos en la lista de widgets de un widget, haga lo siguiente:

1) establecer un setPendingIntentTemplate en su clase AppWidgetProvider

2) establecer un setOnClickFillInIntent en el método getViewAt(int position) sobrepasado getViewAt(int position)

AHORA: Haciendo el paso 1), quizás quiera hacer algo como:

 final Intent serviceIntent = new Intent(context, MyListRemoteViewFactory.class); serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME))); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { views.setRemoteAdapter(R.id.widget_list_view, serviceIntent); } else { views.setRemoteAdapter(widgetId, R.id.widget_list_view, serviceIntent); } // Individuals items of a collection cannot set up their own pending intents. Instead, the collection as a whole sets up a pending intent template and the individual // items set a fillInIntent to create unique behavior on an item-by-item basis. Intent listItemClickIntent = new Intent(context, MyWidgetProvider.class); // This is the name of your AppWidgetProvider class // Set the action for the intent. When the user touches a particular view, it will have the effect of broadcasting an action listItemClickIntent.setAction(context.getString("com.example.list.item.click")); listItemClickIntent.setData(Uri.parse(listItemClickIntent.toUri(Intent.URI_INTENT_SCHEME))); PendingIntent clickPendingIntent = PendingIntent.getBroadcast(context, 0, listItemClickIntent, PendingIntent.FLAG_UPDATE_CURRENT); views.setPendingIntentTemplate(R.id.widget_list_view, clickPendingIntent); 

Puede colocar el fragmento de código anterior después de donde inicializa su objeto RemoteViews:

 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.layout_widget);) 

Así que ahora mismo tienes tu pendingIntentTemplate listo. Otra cosa a hacer es implementar el método onReceive la clase, para que pueda decidir qué hacer cuando se produce una acción para el caso anterior. Así que harás algo como:

 @Override public void onReceive(Context context, Intent intent) { // Called on every broadcast and before each of the above callback methods. super.onReceive(context, intent); ComponentName name = new ComponentName(context, WidgetProvider.class); int[] appWidgetIds = AppWidgetManager.getInstance(context).getAppWidgetIds(name); if (appWidgetIds == null || appWidgetIds.length == 0) { return; } AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); if (intent.getAction().equals("com.example.list.item.click") { // This is where you have to decide what you'll do depending on which list item was tapped. BUT this depends on the fill Intent set in the MyListRemoteViewFactory class's getViewAt() method // I'll jump straight to the logic here, but once you're done reading this post, get back here to understand the logic because this is the key here. But simple as hell. int simpleDecidingFactor = intent.getIntExtra("SELECTED_ITEM", 0) if (simpleDecidingFactor != 0) { if (simpleDecidingFactor == 1) { // Do something for the first case. Probably open activity2 } else if (simpleDecidingFactor == 2) { // Do something for the second case. Probably open activity2 } else if (simpleDecidingFactor == 3) { // Do something for the second case. Probably open activity3 } } } } 

[Maldita sea esto será largo]

HACIENDO EL PASO 2) (a partir de ahora hablamos de implementaciones en la clase MyListRemoteViewFactory)

Si necesitas 3 elementos diferentes en la lista, primero debes añadir este método a MyListRemoteViewFactory (te obligas a anularlo de todos modos, la clave es devolver el número de vistas que tengas):

 @Override public int getViewTypeCount() { return 3; } 

En el método getViewAt() agrega su lógica basada en qué, usted decide qué mostrar según su posición. Algo como:

 @Override public RemoteViews getViewAt(int position) { if (position >= mItems.size()) { return null; } RemoteViews views; if (mItems.get(position).getViewType() == 0) { views = new RemoteViews(mContext.getPackageName(), R.layout.list_item_first); setUpItem(views, mItems.get(position), 1); // !!!! the 3rd parameter is very important here, as you'll expect this number in the MyWidgetProvider class' onReceive method. See the simpleDecidingFactor variable there. } else if (mItems.get(position).getViewType() == 1) { views = new RemoteViews(mContext.getPackageName(), R.layout.list_item_second); setUpItem(views, mItems.get(position), 2); } else { views = new RemoteViews(mContext.getPackageName(), R.layout.list_item_third); setUpItem(views, mItems.get(position), 3); } // Or add whatever logic you have. Here, I supposed I have a field inside my object telling me what type my item is return views; } 

Y el método setUpItem podría parecer algo así:

 private void setUpItem(RemoteViews views, MyObject object, int viewTypeKey) { // This is where you set your clickFillInIntent. Without setting it, nothing'll be functional Bundle extras = new Bundle(); extras.putInt("SELECTED_ITEM", viewTypeKey); //extras.putParcelable("LIST_ITEM_OBJECT", object); // You may send your object as well if you need it Intent fillInIntent = new Intent(); fillInIntent.putExtras(extras); // You have your fillInIntent prepared, you only have to decide on what view to place it. // I assume you have a Button on all 3 of your list item layouts with the id button_click. Let's place the Intent: views.setOnClickFillInIntent(R.id.button_click, fillInIntent); } 

Es posible que desee asegurarse de que declaró todo en el archivo de manifiesto también. Usted tiene que declarar su widgetprovider, su receptor para la lista, y un servicio que maneja su Factoryclass. Usted debe tener algo como:

 <receiver android:name=".MyWidgetProvider" android:enabled="true" android:label="My awesome widget"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_ENABLED" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.appwidget.action.APPWIDGET_DELETED" /> <action android:name="android.appwidget.action.APPWIDGET_DISABLED" /> <!-- You have to declare your used actions here, so the AppWidgetProvider knows what to listen for--> <action android:name="com.example.list.item.click"/> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_provider_info"/> </receiver> <!-- The service serving the RemoteViews to the collection widget --> <service android:name=".WidgetRemoteViewsService" android:exported="false" android:permission="android.permission.BIND_REMOTEVIEWS"/> <receiver android:name=".ui.widget.MyListRemoteViewFactory" android:enabled="true" android:exported="false"> <intent-filter> <category android:name="android.intent.category.DEFAULT"/> <!-- You might want to use an action to notify the appwidget provider from the MyListRemoteViewFactory's onReceive method. This class extends a BroadcastReceiver, so you must implement it's onReceive(Context context, Intent intent) method. If you need help on this, let me know and I'll edit my answer with some example for that too --> <action android:name="com.example.refresh.remote.views"/> </intent-filter> </receiver> 

Ah, BTW la clase WidgetRemoteViewsService debería verse así:

 public class WidgetNewsRemoteViewsService extends RemoteViewsService { @Override public RemoteViewsFactory onGetViewFactory(Intent intent) { return new MyListRemoteViewFactory(); } } 

Supongo que esto es más o menos. Espero no haber omitido nada.

  • Envío de datos a mi widget (pantalla de inicio)
  • La aplicación para Android NO debería lanzarse al recibir Intención
  • RemoteView y setGravity
  • Tamaño del mapa de bits de Android Widget
  • Android: EventHub.removeMessages (int what = 107) no es compatible antes de que se configure WebViewCore
  • Uso de setImageDrawable dinámicamente para configurar la imagen en un ImageView
  • Edición de estilo de Android ListView con fondo mientras se desplaza
  • Animaciones de widget de pantalla de inicio de Android
  • Comando de voz para desbloquear la pantalla de Android
  • Pintura a mano libre no funciona correctamente?
  • Evitar el desencadenamiento de onUpdate de WidgetProvider
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.