Как получить НОВУЮ ширину / высоту корневого макета в onConfigurationChanged?
Один из наших взглядов имеет ScrollView
как его корневой макет. Когда устройство вращается и onConfigurationChanged()
называется, мы хотели бы иметь возможность получить ScrollView
Новая ширина / высота. Наш код выглядит так:
@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() + "'");
}
Соответствующий раздел нашего AndroidManifest.xml выглядит следующим образом:
<activity android:name=".SomeActivity"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
И, наконец, соответствующая часть нашего макета выглядит следующим образом:
<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"
>
На нашем Droid мы ожидали увидеть ширину ScrollView до 854 при переключении в альбомную ориентацию и до 480 при переключении обратно в портретную (и высота делает эквивалентное переключение, за вычетом строки меню). Однако мы видим обратное. Вот наш 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
Очевидно, что мы получаем портретные размеры, когда мы переключаемся в альбомную, и ландшафтные размеры, когда мы переключаемся в портретную. Есть что-то, что мы делаем не так? Мы могли бы взломать и решить это, но я чувствую, что есть простое решение, которое нам не хватает.
3 ответа
getWidth() возвращает ширину при разметке View, что означает, что вам нужно подождать, пока он будет отображен на экране. onConfigurationChanged
вызывается перед перерисовкой представления для новой конфигурации, и поэтому я не думаю, что вы сможете получить новую ширину позже.
Для тех, кто ищет более подробное описание решения: вы можете использовать ViewTreeObserver
на ваш взгляд и зарегистрировать 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);
}
});
}
Когда вызывается onGlobalLayout, он не уверен, что размер представления был изменен в соответствии с новой ориентацией макета, поэтому для меня правильно работало только следующее решение:
@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);}