屏幕旋转时,小部件上的按钮单击丢失

Posted

技术标签:

【中文标题】屏幕旋转时,小部件上的按钮单击丢失【英文标题】:Button click lost on widget when screen is rotated 【发布时间】:2011-05-13 23:15:19 【问题描述】:

我有一个非常简单的小部件应用程序,它由一个带背景的LinearLayout 和一个ImageButton 组成。

AppWidgetProvideronUpdate()方法中,我注册了按钮的点击来广播一个意图。当小部件第一次加载时,一切都运行良好并且点击被捕获。当屏幕旋转时出现问题,即使屏幕旋转回来也不会再次捕获点击。

屏幕旋转时我需要做什么才能重新注册点击?

下面是我正在使用的一些代码段。

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 后自动旋转不起作用

ActionItem 在屏幕旋转时丢失

屏幕旋转后按钮消失

在主屏幕小部件的列表视图上方添加一个按钮 - 如何捕获单击此按钮?

单击时将图像添加到屏幕并允许其可拖动/可旋转