如何将 onClick 侦听器附加到应用小部件上的列表视图项
how to attach a onClick Listener to a listview item on an app widget
我想为我的列表视图的每个项目添加一个 onClick 监听器,但我尝试过的方法都不起作用。
这是我的 RemoteViewsFactory:
public class MyRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
[...]
public RemoteViews getViewAt(int position) {
final RemoteViews remoteView = new RemoteViews(
context.getPackageName(), R.layout.widget_item);
[...]
final Intent activityIntent = new Intent(context, ListActivity.class);
activityIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
activityIntent.putExtra(AppWidgetManager.ACTION_APPWIDGET_PICK, position);
PendingIntent pI = PendingIntent.getActivity(
context, appWidgetId, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setOnClickPendingIntent(R.id.item_frame, pI);
return remoteView;
}
}
列表-widget.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" >
<include layout="@layout/picture_frame" />
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/picframe"
android:layout_margin="5dp"
android:gravity="center"
android:loopViews="true" />
</RelativeLayout>
列表-item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:layout_centerVertical="true" >
<TextView
android:id="@+id/date"
style="@style/WidgetItemText" />
<TextView
android:id="@+id/name"
style="@style/WidgetItemText" />
</LinearLayout>
如果我点击一个项目,什么也没有发生。
如果我将其直接挂在列表视图的提供程序中,则 Intent 工作正常,但我无法再滚动并且无法响应单个项目。
您可以尝试类似的操作,其中 position 是您的项目在列表视图中的索引
ListView lv = getListView();
setContentView(lv);
lv.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,int position, long arg3)
{
Toast.makeText(SuggestionActivity.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
Adding behavior to individual items 在 official doc 中的部分说:
As described in Using the AppWidgetProvider Class, you normally use setOnClickPendingIntent() to set an object's click behavior—such as to cause a button to launch an Activity. But this approach is not allowed for child views in an individual collection item (to clarify, you could use setOnClickPendingIntent() to set up a global button in the Gmail app widget that launches the app, for example, but not on the individual list items). Instead, to add click behavior to individual items in a collection, you use setOnClickFillInIntent(). This entails setting up up a pending intent template for your collection view, and then setting a fill-in intent on each item in the collection via your RemoteViewsFactory.
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. The fill-in intent is then combined with the PendingIntent template in order to determine the final intent that will be executed when the item is clicked.
您需要调用 setOnClickFillInIntent
来区分项目 on-click 行为。像这样:
public RemoteViews getViewAt(int position) {
final RemoteViews remoteView = new RemoteViews(
context.getPackageName(), R.layout.widget_item);
[...]
// Next, set a fill-intent, which will be used to fill in the pending intent template
// that is set on the collection view in StackWidgetProvider.
Bundle extras = new Bundle();
extras.putInt(YouWidgetProvider.EXTRA_ITEM, position);
Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
// Make it possible to distinguish the individual on-click
// action of a given item
remoteView.setOnClickFillInIntent(R.id.item_frame, fillInIntent);
return remoteView;
}
还应该使用 setPendingIntentTemplate
而不是 setOnClickPendingIntent
来在集合上设置单个 PendingIntent
模板。在对应于 AppWidgetProvider
子类的 onUpdate
方法中设置未决意图,如下所示:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// update each of the app widgets with the remote adapter
for (int i = 0; i < appWidgetIds.length; ++i) {
...
RemoteViews remoteView = new RemoteViews(context.getPackageName(),
R.layout.widget_item);
...
// This section makes it possible for items to have individualized behavior.
// It does this by setting up a pending intent template. 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 activityIntent = new Intent(context, ListActivity.class);
// Set the action for the intent.
// When the user touches a particular view.
activityIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
activityIntent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i],
activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setPendingIntentTemplate(R.id.stack_view, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteView);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
With this Code
you can add onClick for every ListView item in Widget and can pass data from widget item to start new Activity
with this data.
在小部件中,您无法为列表或堆栈中的每个项目创建一个单独的 Intent
。为此,我们必须为我们创建的每个列表项创建 Intent
,并在 WidgetService
中包含数据。
这是WidgetService.java
。我用我想发送的额外数据创建了一个 new Intent
。
然后我选择哪个 UI 元素将成为此函数中的触发器 views.setOnClickFillInIntent
。
@Override
public RemoteViews getViewAt(int position) {
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_item);
//Open Post
Intent fillIntent = new Intent();
fillIntent.putExtra(
"keyData", position);
views.setOnClickFillInIntent(R.id.tvTitle, fillIntent);
.....
}
这是ExampleWidgetProvider.java
public static final String ACTION_POST = "actionPost";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// update each of the app widgets with the remote adapter
for (int i = 0; i < appWidgetIds.length; ++i) {
...
RemoteViews remoteView = new RemoteViews(context.getPackageName(),
R.layout.listview);
...
Intent postIntent = new Intent(context, ExampleWidgetProvider.class);
postIntent.setAction(ACTION_POST);
PendingIntent postPendingIntent = PendingIntent.getBroadcast(context,
0, postIntent, 0);
...
activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setPendingIntentTemplate(R.id.listview, postPendingIntent );
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteView);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
我们已经为每个 ListView
项目创建了 OnClick,它将向自身发送意图给这个 ExampleWidgetProvider.java
。现在我们必须读取 Intent
在 WidgetService.java
中为每个列表项发送的信息。
为此,我们必须在 ExampleWidgetProvider.java
.
中创建另一个函数
@Override
public void onReceive(Context context, Intent intent) {
if(ACTION_POST.equals(intent.getAction())){
//Passed info from WidgetService.java
String data= intent.getStringExtra("keyData");
// If you want to open new activity with this data you can do it
Intent intentPOST = new Intent(context,
MainActivity.class).putExtra(
"keyData", data);
intentPOST.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity (intentPOST);
//Show information
Toast.makeText(context,
data,
Toast.LENGTH_LONG).show();
}
super.onReceive(context, intent);
}
我想为我的列表视图的每个项目添加一个 onClick 监听器,但我尝试过的方法都不起作用。
这是我的 RemoteViewsFactory:
public class MyRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
[...]
public RemoteViews getViewAt(int position) {
final RemoteViews remoteView = new RemoteViews(
context.getPackageName(), R.layout.widget_item);
[...]
final Intent activityIntent = new Intent(context, ListActivity.class);
activityIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
activityIntent.putExtra(AppWidgetManager.ACTION_APPWIDGET_PICK, position);
PendingIntent pI = PendingIntent.getActivity(
context, appWidgetId, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setOnClickPendingIntent(R.id.item_frame, pI);
return remoteView;
}
}
列表-widget.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" >
<include layout="@layout/picture_frame" />
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/picframe"
android:layout_margin="5dp"
android:gravity="center"
android:loopViews="true" />
</RelativeLayout>
列表-item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:layout_centerVertical="true" >
<TextView
android:id="@+id/date"
style="@style/WidgetItemText" />
<TextView
android:id="@+id/name"
style="@style/WidgetItemText" />
</LinearLayout>
如果我点击一个项目,什么也没有发生。
如果我将其直接挂在列表视图的提供程序中,则 Intent 工作正常,但我无法再滚动并且无法响应单个项目。
您可以尝试类似的操作,其中 position 是您的项目在列表视图中的索引
ListView lv = getListView();
setContentView(lv);
lv.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,int position, long arg3)
{
Toast.makeText(SuggestionActivity.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
Adding behavior to individual items 在 official doc 中的部分说:
As described in Using the AppWidgetProvider Class, you normally use setOnClickPendingIntent() to set an object's click behavior—such as to cause a button to launch an Activity. But this approach is not allowed for child views in an individual collection item (to clarify, you could use setOnClickPendingIntent() to set up a global button in the Gmail app widget that launches the app, for example, but not on the individual list items). Instead, to add click behavior to individual items in a collection, you use setOnClickFillInIntent(). This entails setting up up a pending intent template for your collection view, and then setting a fill-in intent on each item in the collection via your RemoteViewsFactory.
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. The fill-in intent is then combined with the PendingIntent template in order to determine the final intent that will be executed when the item is clicked.
您需要调用 setOnClickFillInIntent
来区分项目 on-click 行为。像这样:
public RemoteViews getViewAt(int position) {
final RemoteViews remoteView = new RemoteViews(
context.getPackageName(), R.layout.widget_item);
[...]
// Next, set a fill-intent, which will be used to fill in the pending intent template
// that is set on the collection view in StackWidgetProvider.
Bundle extras = new Bundle();
extras.putInt(YouWidgetProvider.EXTRA_ITEM, position);
Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
// Make it possible to distinguish the individual on-click
// action of a given item
remoteView.setOnClickFillInIntent(R.id.item_frame, fillInIntent);
return remoteView;
}
还应该使用 setPendingIntentTemplate
而不是 setOnClickPendingIntent
来在集合上设置单个 PendingIntent
模板。在对应于 AppWidgetProvider
子类的 onUpdate
方法中设置未决意图,如下所示:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// update each of the app widgets with the remote adapter
for (int i = 0; i < appWidgetIds.length; ++i) {
...
RemoteViews remoteView = new RemoteViews(context.getPackageName(),
R.layout.widget_item);
...
// This section makes it possible for items to have individualized behavior.
// It does this by setting up a pending intent template. 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 activityIntent = new Intent(context, ListActivity.class);
// Set the action for the intent.
// When the user touches a particular view.
activityIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
activityIntent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i],
activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setPendingIntentTemplate(R.id.stack_view, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteView);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
With this
Code
you can add onClick for every ListView item in Widget and can pass data from widget item to start newActivity
with this data.
在小部件中,您无法为列表或堆栈中的每个项目创建一个单独的 Intent
。为此,我们必须为我们创建的每个列表项创建 Intent
,并在 WidgetService
中包含数据。
这是WidgetService.java
。我用我想发送的额外数据创建了一个 new Intent
。
然后我选择哪个 UI 元素将成为此函数中的触发器 views.setOnClickFillInIntent
。
@Override
public RemoteViews getViewAt(int position) {
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_item);
//Open Post
Intent fillIntent = new Intent();
fillIntent.putExtra(
"keyData", position);
views.setOnClickFillInIntent(R.id.tvTitle, fillIntent);
.....
}
这是ExampleWidgetProvider.java
public static final String ACTION_POST = "actionPost";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// update each of the app widgets with the remote adapter
for (int i = 0; i < appWidgetIds.length; ++i) {
...
RemoteViews remoteView = new RemoteViews(context.getPackageName(),
R.layout.listview);
...
Intent postIntent = new Intent(context, ExampleWidgetProvider.class);
postIntent.setAction(ACTION_POST);
PendingIntent postPendingIntent = PendingIntent.getBroadcast(context,
0, postIntent, 0);
...
activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setPendingIntentTemplate(R.id.listview, postPendingIntent );
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteView);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
我们已经为每个 ListView
项目创建了 OnClick,它将向自身发送意图给这个 ExampleWidgetProvider.java
。现在我们必须读取 Intent
在 WidgetService.java
中为每个列表项发送的信息。
为此,我们必须在 ExampleWidgetProvider.java
.
@Override
public void onReceive(Context context, Intent intent) {
if(ACTION_POST.equals(intent.getAction())){
//Passed info from WidgetService.java
String data= intent.getStringExtra("keyData");
// If you want to open new activity with this data you can do it
Intent intentPOST = new Intent(context,
MainActivity.class).putExtra(
"keyData", data);
intentPOST.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity (intentPOST);
//Show information
Toast.makeText(context,
data,
Toast.LENGTH_LONG).show();
}
super.onReceive(context, intent);
}