При щелчке по экрану кнопки мыши теряются на виджетах

У меня очень простое приложение виджета, состоящее из 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_width="140dip"
    android:layout_height="140dip"
    android:scaleType="fitCenter"
    android:orientation="vertical"
    android:background="@drawable/background">
    <ImageButton
        android:id="@+id/change_mode"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="fitCenter"
        android:orientation="vertical"
        android:src="@drawable/none_selected"
        android:background="@null"
        android:clickable="true" />
</LinearLayout>

Спасибо вам за вашу помощь!

Ответы

Ответ 2

Я использовал решение, которое требует службы на widgetapp, потому что оно может обрабатывать изменения ориентации в widgetapp. К сожалению, 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 на самом деле убивает и воссоздает вашу активность каждый раз, когда экран вращается. Yuck, я знаю.

Так или иначе, я подозреваю, что если вы поставили логические операторы во всех обратных вызовах жизненного цикла, вы обнаружите, что обновление вызывается только один раз. Вероятно, вам придется обрабатывать прослушивание кликов в другом обратном вызове. Я не мог сказать вам, какой из них не будет проверять какой-либо справочный материал. Я оставлю это как упражнение для читателя.

Ответ 4

Сено вы используете андроид: configChanges = "keyboardHidden | ориентация"
с вашей деятельностью в файле Androidmanifest.

Ответ 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 вы можете увидеть, если он должен воссоздать событие click, проверив getIntent().getBooleanExtra("Just received click", false) (false ссылается на значение по умолчанию. Если этот код возвращает true, то приведенный выше код сделал это задание, и вы должны воссоздать событие click )

Это должно работать, потому что объект намерения (и его дополнительные) сохраняется, даже если ваше приложение временно убито. Цель будет принимать любые дополнительные Serializable.