Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get NEW width/height of root layout in onConfigurationChanged?

One of our views has a ScrollView as its root layout. When the device is rotated and onConfigurationChanged() is called, we'd like to be able to get the ScrollView's new width/height. Our code looks like this:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    Log.d(TAG, "Width: '" + findViewById(R.id.scrollview).getWidth() + "'");
    Log.d(TAG, "Height: '" + findViewById(R.id.scrollview).getHeight() + "'");

    super.onConfigurationChanged(newConfig);

    Log.d(TAG, "Width: '" + findViewById(R.id.scrollview).getWidth() + "'");
    Log.d(TAG, "Height: '" + findViewById(R.id.scrollview).getHeight() + "'");
}

The relevant section of our AndroidManifest.xml looks like this:

<activity android:name=".SomeActivity"
    android:configChanges="keyboardHidden|orientation">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
    </intent-filter>
</activity>

And finally, the relevant portion of our layout looks like this:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scrollview"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    >
    <LinearLayout android:id="@+id/container"
        android:orientation="vertical"
        android:layout_height="fill_parent"
        android:minHeight="200dip"
        android:layout_width="fill_parent"
        >

On our Droid, we expected to see the ScrollView's width go to 854 when switched into landscape, and to 480 when switched back to portrait (and the height do the equivalent switch, minus the menu bar). However, we're seeing the opposite. Here's our LogCat:

// Switching to landscape:
03-26 11:26:16.490: DEBUG/ourtag(17245): Width: '480'  // Before super
03-26 11:26:16.490: DEBUG/ourtag(17245): Height: '778' // Before super
03-26 11:26:16.529: DEBUG/ourtag(17245): Width: '480'  // After super
03-26 11:26:16.536: DEBUG/ourtag(17245): Height: '778' // After super

// Switching to portrait:
03-26 11:26:28.724: DEBUG/ourtag(17245): Width: '854'  // Before super
03-26 11:26:28.740: DEBUG/ourtag(17245): Height: '404' // Before super
03-26 11:26:28.740: DEBUG/ourtag(17245): Width: '854'  // After super
03-26 11:26:28.740: DEBUG/ourtag(17245): Height: '404' // After super

Clearly, we're getting the portrait dimensions when we switch to landscape, and the landscape dimensions when we switch to portrait. Is there something we're doing wrong? We could get hacky and solve this, but I feel like there's a simple solution that we're missing.

like image 667
jakeboxer Avatar asked Mar 26 '10 16:03

jakeboxer


3 Answers

For those looking for a more detailed solution description: You can use the ViewTreeObserver of your view and register an OnGlobalLayoutListener.

@Override public void onConfigurationChanged(Configuration newConfiguration) {     super.onConfigurationChanged(newConfiguration);     final View view = findViewById(R.id.scrollview);      ViewTreeObserver observer = view.getViewTreeObserver();     observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {          @Override         public void onGlobalLayout() {             Log.v(TAG,                     String.format("new width=%d; new height=%d", view.getWidth(),                             view.getHeight()));             view.getViewTreeObserver().removeOnGlobalLayoutListener(this);         }     }); } 
like image 61
Andreas Klöber Avatar answered Sep 21 '22 11:09

Andreas Klöber


When onGlobalLayout called it's not sure that the view has been resized accordingly to the new layout orientation, so for me only the below solution worked properly:

@Override public void onConfigurationChanged(Configuration newConfig) { final int oldHeight = mView.getHeight(); final int oldWidth = mView.getWidth();  mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {         @Override         public void onGlobalLayout() {             if (mView.getHeight() != oldHeight && mView.getWidth() != oldWidth) {                 mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);                 //mView now has the correct dimensions, continue with your stuff             }         }     });     super.onConfigurationChanged(newConfig);} 
like image 26
Antonis Lat Avatar answered Sep 21 '22 11:09

Antonis Lat


getWidth() returns the width as the View is laid out, meaning you need to wait until it is drawn to the screen. onConfigurationChanged is called before redrawing the view for the new configuration and so I don't think you'll be able to get your new width until later.

like image 32
jqpubliq Avatar answered Sep 20 '22 11:09

jqpubliq