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> 
Je ne connais pas la réponse exacte mais est-il en pointant vers un événement sortant de l'ancien orientation et un autre événement de la nouvelle orientation? le jeu de données ainsi obtenu ne peut être ce qui suggère l'ancienne et de la nouvelle fenêtre d'affichage metrices à l'événement
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