屏幕旋转时,小部件上的按钮单击丢失
Posted
技术标签:
【中文标题】屏幕旋转时,小部件上的按钮单击丢失【英文标题】:Button click lost on widget when screen is rotated 【发布时间】:2011-05-13 23:15:19 【问题描述】:我有一个非常简单的小部件应用程序,它由一个带背景的LinearLayout
和一个ImageButton
组成。
在AppWidgetProvider
onUpdate()
方法中,我注册了按钮的点击来广播一个意图。当小部件第一次加载时,一切都运行良好并且点击被捕获。当屏幕旋转时出现问题,即使屏幕旋转回来也不会再次捕获点击。
屏幕旋转时我需要做什么才能重新注册点击?
下面是我正在使用的一些代码段。
AppWidgetProvider
@Override
public void onReceive(Context context, Intent intent)
super.onReceive(context, intent);
if(intent.getAction().equals("test.CLICK"))
CallTestMethod(context);
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds)
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++)
int appWidgetId = appWidgetIds[i];
RemoteViews views=new RemoteViews(context.getPackageName(), R.layout.widget);
Intent clickintent=new Intent("test.CLICK");
PendingIntent pendingIntentClick=PendingIntent.getBroadcast(context, 0, clickintent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.change_mode, pendingIntentClick);
SetInitialLayout(context);
appWidgetManager.updateAppWidget(appWidgetId, views);
super.onUpdate(context, appWidgetManager, appWidgetIds);
清单
<receiver android:name=".Widget" android:label="@string/widget_name">
<intent-filter>
<action android:name="android.appwidget.action.ACTION_APPWIDGET_CONFIGURE" />
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="test.CLICK" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_mode_switcher" />
</receiver>
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_layout"
android:layout_
android:layout_
android:scaleType="fitCenter"
android:orientation="vertical"
android:background="@drawable/background">
<ImageButton
android:id="@+id/change_mode"
android:layout_
android:layout_
android:scaleType="fitCenter"
android:orientation="vertical"
android:src="@drawable/none_selected"
android:background="@null"
android:clickable="true" />
</LinearLayout>
感谢大家的帮助!
【问题讨论】:
【参考方案1】:这对我有帮助:Android widget ImageButton loses image when screen is rotated
简而言之,您必须在每次调用 awm.updateAppWidget 之前注册点击次数 (views.setOnClickPendingIntent)
【讨论】:
谢谢!我找不到对我有意义的答案,不知何故这是最容易理解的答案。我正在从另一个类更新我的小部件,并且没有从那里包含 setOnClickPendingIntent。现在我做到了,而且效果很好。 谢谢,我必须在一年前找到这个,现在我正在创建一个新的小部件并再次面临同样的问题。在我以相同的答案结束之前,我不记得问题的解决方案。【参考方案2】:我使用的解决方案需要小部件应用上的服务,因为它可以处理小部件应用的方向更改。不幸的是,方向更改不会调用 onReceive 或 onUpdate,但会调用服务的 onConfigurationChanged。您还需要让您的服务不断运行以检测这些方向。当服务检测到方向变化时,您继续更改远程视图。
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds)
context.startService(new Intent(context, MyUpdateService.class));
这是您需要实现的服务类。如果您需要有关该服务的更多信息,可以查看此内容。 http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html
public static class MyUpdateService extends Service
@Override
public void onCreate()
super.onCreate();
@Override
public void onDestroy()
super.onDestroy();
@Override
public void onStart(Intent intent, int startId)
super.onStart(intent, startId);
// Update the widget
RemoteViews remoteView = buildRemoteView(this);
// Push update to homescreen
pushUpdate(remoteView);
public RemoteViews buildRemoteView(Context context)
int layoutID = R.layout.widget;
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
layoutID = R.layout.widget_landscape;
//Here is where you set your onclick listeners again since the remote views need to be refreshed/recreated
RemoteViews updateView = new RemoteViews(context.getPackageName(),layoutID);
// Create an Intent to launch ExampleActivity
Intent intent = new Intent(this, yourAndroidActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, 0);
updateView.setOnClickPendingIntent(R.id.yourClickableViewHere, pendingIntent);
return updateView;
@Override
public void onConfigurationChanged(Configuration newConfig)
RemoteViews remoteView = buildRemoteView(this);
// Push update to home screen
pushUpdate(remoteView);
private void pushUpdate(RemoteViews updateViews)
ComponentName myWidget = new ComponentName(this, YourAppWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
//This is where you can update your remoteViews
updateViews.setTextViewText(R.id.YOUR_TEXTVIEW_ON_WIDGET, "" + "TEXT THAT WILL SHOW UP");
manager.updateAppWidget(myWidget, updateViews);
【讨论】:
【参考方案3】:据我了解,每次屏幕旋转时,Android 实际上都会杀死并重新创建您的活动。糟糕,我知道了。
所以无论如何,我怀疑如果您将日志语句放在所有各种生命周期回调中,您会发现 update 只被调用一次。您可能需要在另一个回调中处理监听点击。如果不检查一些参考资料,我无法告诉你是哪一个。我将把它作为练习留给读者。
【讨论】:
我查看了可用于 AppWidgetProvider 的其他覆盖...启用、禁用、删除、接收、更新。我为它们中的每一个添加了意图过滤器,并在调试时放置了断点,但是当屏幕旋转时,它们都没有到达,所以我无法在小部件生命周期中找到一个位置来注册点击。 糟糕...不是小部件生命周期,是活动生命周期。很抱歉造成混乱。【参考方案4】:干草你用过吗 android:configChanges="keyboardHidden|orientation" 在 Androidmanifest 文件中添加您的 Activity。
【讨论】:
我对 android 开发还是很陌生,所以我还没有尝试过所有的技巧,但我正在研究的是一个小部件。我还需要为小部件执行此操作吗?谢谢【参考方案5】:我是 android 新手,但我相当肯定这种方法会奏效。
@Override
public void onReceive(Context context, Intent intent)
super.onReceive(context, intent);
if(intent.getAction().equals("test.CLICK"))
getIntent().putExtra("Just received click", true);
CallTestMethod(context);
然后在 onCreate 中,您可以通过检查 getIntent().getBooleanExtra("Just received click", false)
来查看它是否应该重新创建点击事件(false 指的是默认值。如果该代码返回 true,那么上面的代码完成了它的工作,您应该重新创建点击事件)
这应该可以工作,因为即使您的应用被暂时终止,intent 对象(及其附加对象)也已保存。意图将接受任何可序列化的额外内容。
【讨论】:
以上是关于屏幕旋转时,小部件上的按钮单击丢失的主要内容,如果未能解决你的问题,请参考以下文章
Live Data Observer On 按钮 屏幕旋转时单击
单击按钮时,在 setRequestedOrientation 后自动旋转不起作用