Pourquoi ne onLayout et onSizeChanged appelée deux fois sur un changement d'orientation?
J'ai remarqué que onLayout et onSizeChanged appelée deux fois en succession immédiate après un changement d'orientation, soit à partir de paysage->portrait ou portrait->paysage, lors de la manipulation de la modification de la configuration à partir d'une Activité. En outre, la première onLayout/onSizeChanged contenir les vieux dimensions (avant rotation), tandis que le 2e onLayout/onSizeChanged contenir les nouveau (correct) dimensions.
Personne ne sait pourquoi et/ou comment contourner ce problème? Il semble que peut-être la taille de l'écran de changement qui arrive peu de temps après le changement de configuration - c'est à dire, les dimensions ne sont pas correcte immédiatement après le changement de configuration lorsque onConfigurationChanged
est appelé?
Voici la sortie de débogage du code ci-dessous, montrant à la fois onLayout/onSizeChanged appels après une rotation à partir du mode Portrait au mode Paysage (à noter que l'appareil est 540x960, de sorte que le paysage de la largeur doit être de 960 tandis que le portrait de la largeur est de 540):
03-13 17:36:21.140: DEBUG/RotateTest(27765): onConfigurationChanged: LANDSCAPE
03-13 17:36:21.169: DEBUG/RotateTest(27765): onSizeChanged:540,884,0,0
03-13 17:36:21.189: DEBUG/RotateTest(27765): onLayout:true-0,0,540,884
03-13 17:36:21.239: DEBUG/RotateTest(27765): onSizeChanged:960,464,540,884
03-13 17:36:21.259: DEBUG/RotateTest(27765): onLayout:true-0,0,960,464
Note également que le premier onSizeChanged oldwidth et oldheight sont 0, indiquant que nous étions juste ajouté à la vue de la hiérarchie, mais avec le mal dimensions pour le paysage!
Et voici le code qui illustre ce problème:
MyActivity.java
package com.example;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
public class MyActivity extends Activity
{
private static String TAG = "RotateTest";
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.d(TAG, "onConfigurationChanged: " + (newConfig.orientation == 1 ? "PORTRAIT" : "LANDSCAPE"));
super.onConfigurationChanged(newConfig);
_setView();
}
@Override
public void onCreate(Bundle savedInstanceState)
{
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
_setView();
}
private void _setView() {
MyHorizontalScrollView scrollView = new MyHorizontalScrollView(this, null);
setContentView(scrollView);
}
}
MyHorizontalScrollView.java
package com.example;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.HorizontalScrollView;
public class MyHorizontalScrollView extends HorizontalScrollView {
private static String TAG = "RotateTest";
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
Log.d(TAG, "onLayout:" + String.format("%s-%d,%d,%d,%d", changed, l, t, r, b));
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.d(TAG, "onSizeChanged:" + String.format("%d,%d,%d,%d", w, h, oldw, oldh));
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example"
android:versionCode="1"
android:versionName="1.0"
>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="9"/>
<application android:label="@string/app_name"
>
<activity android:name="MyActivity"
android:label="@string/app_name"
android:configChanges="orientation"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Merci pour la suggestion kishu27 - les 2 séries de dimensions sont certainement l'ancien puis de nouvelles dimensions; mais les 2 derniers paramètres de la première onSizeChanged (oldw, oldh) sont 0,0, qui indiquent que nous étions juste ajouté à la vue de la hiérarchie (avec le mauvais dimensions!)
OriginalL'auteur MikeV | 2012-03-14
Vous devez vous connecter pour publier un commentaire.
Je me demandais moi-même pour un temps très long.
La façon dont j'ai répondu à la question-parce que je ne crois que la réponse est, c'est selon-est par l'ajout d'un
try/catch
ou l'enregistrement d'instruction dans lerequestLayout
méthode. Cela vous permet de voir lorsque les demandes pour remeasuring et re-pose, et dans le cas de latry/catch,
par qui.La façon la pose dans Android fonctionne est que vous marquez un point de vue comme ayant une sale de mise en page avec
requestLayout
. Android looper qui fonctionne toujours sur le thread d'INTERFACE utilisateur sur certains intervalles de réévaluer et de re-vues de disposition dans l'arbre qui ont été marqués comme sale à un moment indéterminé dans l'avenir.Je me risque à deviner que
onConfigurationChanged
, vous obtenez plusieursrequestLayout
appels et le looper est l'appel deonMeasure
quelque part au milieu d'eux.C'est ce que l'enregistrement ressemblait pour moi:
La Android la documentation a plus d'informations sur la mesure et la pose, mais il est malheureusement court sur les détails que j'ai décrit ci-dessus.
OriginalL'auteur yarian