Warum onLayout und onSizeChanged bekommen zweimal rief eine Orientierung ändern?
Habe ich bemerkt, dass onLayout und onSizeChanged aufgerufen zweimal in unmittelbarer Folge nach einer Orientierung ändern, entweder von Landschafts->portrait oder portrait->Landschaft, bei der Behandlung der änderung der Konfiguration einer Aktivität. Außerdem werden in der ersten onLayout/onSizeChanged enthalten die alten Dimensionen (vor dem drehen), während der 2. onLayout/onSizeChanged enthalten die neue (richtigen) Abmessungen.
Weiß jemand warum und/oder wie dies zu umgehen? Es scheint, dass vielleicht der Bildschirm Größe ändern, passiert einige Zeit nach der änderung der Konfiguration, d.h., die Dimensionen sind nicht korrekt, unmittelbar nachdem Sie die Konfiguration ändern, wenn onConfigurationChanged
genannt wird?
Hier ist die debug-Ausgabe von dem code unten, zeigt sowohl onLayout/onSizeChanged ruft nach einer Drehung von Hochformat auf Querformat (beachten Sie, dass das Gerät 540x960, so dass die Landschaft, die Breite sollte bei 960 während die portrait-Breite 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
Beachten Sie auch, dass die ersten onSizeChanged oldwidth und oldheight sind 0, was darauf hinweist, dass wir nur Hinzugefügt, um die view-Hierarchie - noch mit der falsch Abmessungen für die Landschaft!
Und hier ist der code, der veranschaulicht dieses Verhalten:
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>
Danke für die Anregung kishu27 - die 2 sets von Dimensionen sind sicherlich die alten dann neue Dimensionen; aber die Letzte 2 Parameter des ersten onSizeChanged (oldw, oldh) 0,0, was bedeutet, wir wurden nur Hinzugefügt, um die view-Hierarchie (mit den falschen Maßen!)
InformationsquelleAutor MikeV | 2012-03-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich hab mich schon gewundert, das selbst für eine sehr lange Zeit.
Die Art, wie ich die Frage beantwortet-denn ich glaube, die Antwort ist, es hängt davon ab,--wird durch das hinzufügen einer
try/catch
oder logging-Anweisung in derrequestLayout
Methode. Dies ermöglicht Ihnen zu sehen, wenn die Anforderungen für die Neuvermessung und neu-Verlegung vorgenommen werden, und im Fall dertry/catch,
von wem.Den Weg legen in Android funktioniert, ist, dass Sie einen Blick wie eine schmutzige layout mit
requestLayout
. Ein Android-looper, die läuft immer auf dem UI-thread auf einem Intervall wird nachmessen und re-layout-Ansichten in der Baumstruktur markiert wurden als schmutzig an einigen unbestimmten Zeitpunkt in der Zukunft.Wage ich zu erraten, dass
onConfigurationChanged
bekommen Sie mehrererequestLayout
fordert, und der looper ist der AufrufonMeasure
irgendwo in der Mitte von Ihnen.Dies ist, was die Protokollierung sah aus wie für mich:
Die Android-Dokumentation enthält weitere Informationen auf Messen und auslegen, ist aber leider kurz auf die Besonderheiten, die ich oben beschrieben habe.
InformationsquelleAutor yarian