我正在使用包含3种类型项目的listview的小部件。对于每种类型的项目,我应该使用不同的待定意图。目前我正在使用以下代码:
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);
}
}
从这一点来说,我不明白如何调用不同列表项的特定意图。
答案 0 :(得分:11)
希望我能很好地理解你的问题,所以我会尝试详细解释发生了什么以及如何处理小部件上列表项的点击。
我假设你已经知道你必须实现一个类:
extends BroadcastReceiver implements RemoteViewsService.RemoteViewsFactory
这将作为窗口小部件ListView的“适配器”(让我们称之为MyListRemoteViewFactory)。 如果要在窗口小部件的listView上处理项目点击,请执行以下操作:
1)在AppWidgetProvider类中设置setPendingIntentTemplate
2)在MyListRemoteViewFactory覆盖setOnClickFillInIntent
方法中设置getViewAt(int position)
现在: 做第1步),你可能想做类似的事情:
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);
您可以将以上代码段放在初始化RemoteViews对象的位置之后:
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.layout_widget);)
现在,您已准备好pendingIntentTemplate。另一件事是实现类'onReceive
方法,因此您可以决定在发生上述情况的操作时要执行的操作。所以你会做类似的事情:
@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
}
}
}
}
[该死的很长]
执行第2步)(从现在起我们讨论MyListRemoteViewFactory类中的实现)
如果列表中需要3个不同的项目,首先必须将此方法添加到MyListRemoteViewFactory(无论如何都要强制覆盖它,关键是返回您拥有的视图数量):
@Override
public int getViewTypeCount() {
return 3;
}
在getViewAt()
方法中,根据内容添加逻辑,根据您的位置决定要显示的内容。类似的东西:
@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;
}
setUpItem
方法可能类似于:
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);
}
您可能希望确保在Manifest文件中声明了所有内容。您必须声明您的widgetprovider,列表的接收者以及处理Factoryclass的服务。你应该有类似的东西:
<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>
啊,BTW WidgetRemoteViewsService类应如下所示:
public class WidgetNewsRemoteViewsService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new MyListRemoteViewFactory();
}
}
我想这就是它。我希望我没有跳过任何东西。