【发布时间】:2014-04-23 19:17:05
【问题描述】:
我正在制作一个 Android 主屏幕小部件,其中填充了来自网络的内容。设置它我从 google 的页面和其他一些 questions regarding the setOnClickFillInIntent() function being used 引用 StackWidget 示例。尽管如此,我还是不知道为什么在没有填充模板的情况下点击意图触发。 extras 不为空。小部件可以很好地加载和显示内容,但如果单击它会崩溃并出现 NullPointerEx。
我注意到,如果项目布局中的点击 ID widget_capsule_content 位于布局的根级别(LinearLayout),则根本不会触发意图。如果它在其子项(FrameLayout)中,它确实会触发,但附加项会被忽略。
widget_capsule.xml 的布局 - 单个集合项: - 这些示例都不是优雅的。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:clickable="true"
android:focusable="true"
android:background="@drawable/capsule_bg5">
<FrameLayout
android:id="@+id/widget_capsule_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<ImageView
android:id="@+id/widget_thumbnail"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/capsule_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="10sp"
android:layout_gravity="bottom"
android:textColor="@color/white_text"
android:background="#80000000"
android:text="title"/>
</FrameLayout>
</LinearLayout>
widget_layout.xml 的布局,集合持有者:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white_text"
android:textSize="18sp" />
<AdapterViewFlipper
android:id="@+id/widget_flipper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:autoStart="true"
android:flipInterval="10000"/>
<ImageView
android:id="@+id/widget_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/widget_loading"/>
</LinearLayout>
</LinearLayout>
来自 WidgetReceiver 的相关代码(扩展 AppWidgetProvider):
@Override
public void onUpdate(Context context, AppWidgetManager wManager, int[] appWidgetIds){
//This method is allowed to handle multiple widgets VIA appWidgetId.
ComponentName thisWidget = new ComponentName(context,
IHWidgetReceiver.class);
int[] allWidgetIds = wManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
//service intent
Intent sIntent = new Intent(context, IHWidgetService.class);
sIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
sIntent.setData(Uri.parse(sIntent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
remoteViews.setRemoteAdapter(R.id.widget_flipper, sIntent);
// The empty view is displayed when the collection has no items. It should be a sibling
// of the collection view.
remoteViews.setEmptyView(R.id.widget_flipper, R.id.widget_loading);
//Pending Intent to prepare individual item clicks
/*Class<? extends Activity> startA = IntentUtil.getActivityClass(context, IHDetail.class);
Intent pI = new Intent(context, startA); //3
pI.setAction(Intent.ACTION_VIEW);
pI.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
pI.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //3
pI.setData(Uri.parse(pI.toUri(Intent.URI_INTENT_SCHEME)));
remoteViews.setPendingIntentTemplate(R.id.widget_flipper,
PendingIntent.getActivity(context, 0, pI, PendingIntent.FLAG_UPDATE_CURRENT));*/
//For sake of breakpointing below, this block is made to match the StackViewWidget sample as much as possible.
//It suffers the same issue as the activity launch behavior above
Intent pI = new Intent(context, IHWidgetReceiver.class);
pI.setAction(ACTION_CLICK);
pI.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
pI.setData(Uri.parse(pI.toUri(Intent.URI_INTENT_SCHEME)));
remoteViews.setPendingIntentTemplate(R.id.widget_flipper,
PendingIntent.getBroadcast(context, 0, pI, PendingIntent.FLAG_UPDATE_CURRENT));
//done
Log.i("Widget", "Widget Updated");
wManager.updateAppWidget(widgetId, remoteViews);
wManager.notifyAppWidgetViewDataChanged(allWidgetIds, widgetId);
}
super.onUpdate(context, wManager, appWidgetIds);
}
@Override
public void onReceive(Context rContext, Intent rIntent) {
Ln.e("RECEIVED THING + ");
AppWidgetManager wManager = AppWidgetManager.getInstance(rContext);
if (rIntent.getAction().equals(ACTION_CLICK)) {
Toast.makeText(rContext, "Touched view ", Toast.LENGTH_SHORT).show();
Bundle eBundle = rIntent.getExtras();
CmsContent content = (CmsContent) eBundle.getSerializable(IHConstants.MS_CONTENT_EXTRA);
String id = eBundle.getString(IHConstants.MS_ID_EXTRA);
//trying again without the bundle
CmsContent content2 = (CmsContent) rIntent.getSerializableExtra(IHConstants.MS_CONTENT_EXTRA);
String id2 = rIntent.getStringExtra(IHConstants.MS_ID_EXTRA);
//breakpointed here. all of the above extras are null. the next line is a NPE
Intent activityIntent = IntentUtil.getDetailIntent(rContext, content2, id2);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
rContext.startActivity(activityIntent);
}
super.onReceive(rContext, rIntent);
}
WidgetViewsFactory 的相关代码(实现 RemoteViewsService.RemoteViewsFactory ):
@Override
public RemoteViews getViewAt(int position) {
//populate view w/ data
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_capsule);
rv.setTextViewText(R.id.capsule_title, getContent(position).getShortTitle());
rv.setImageViewBitmap(R.id.widget_thumbnail, getContent(position).getThumbnail());
//intent junk
Bundle extras = new Bundle();
Intent act = new Intent();
//act.putExtra(IHConstants.MS_ID_EXTRA, capsules.get(position).getId());
//act.putExtra(IHConstants.MS_CONTENT_EXTRA, getContent(position));
extras.putString(IHConstants.MS_ID_EXTRA, capsules.get(position).getId());
extras.putSerializable(IHConstants.MS_CONTENT_EXTRA, getContent(position));
act.putExtras(extras);
Ln.e("content in extras " + capsules.get(position).getId() + " | " + getContent(position).getDetailSection());
//Log indicates that the extras were not null when inserted
rv.setOnClickFillInIntent(R.id.widget_capsule_content, act);
return rv;
}
【问题讨论】:
-
尝试从 widget_capsule.xml 中移除可点击和可聚焦的属性。在我的情况下,它适用于包装到 RelativeLayout 中的单个 ImageView。拥有一个根布局对于 AdapterViewFlipper 传递点击意图似乎至关重要。
标签: android android-layout android-intent android-widget