В какое время в жизненном цикле приложения можно/нужно использовать макетные измерения?

Там много вопросов по этой проблеме, но большинство из них слишком специализированы, чтобы ответить на мой вопрос.

У меня есть GoogleMap, который я скажу, чтобы соответствовать его камере в определенных пределах. Возможно, не очень удивительно, что я получаю сообщение об ошибке:

java.lang.IllegalStateException: Map size should not be 0. Most likely, layout has not yet occured for the map view.

Итак, пусть абстрактная проблема для любого View.

Когда происходит это событие "layout"? onMeasure(), например, не отображается в жизненном цикле деятельности. Когда безопасно вызывать мой макет-метод?

4 ответа

EDIT:

Чтобы решить эту проблему в обновленном API Карт, вы должны использовать

map.moveCamera(CameraUpdateFactory.newLatLngBounds(Builder.build(), 50));

Для любого другого вида и более старого API карт

Используйте ViewTreeObserver.OnGlobalLayoutListener, как в ответе Саймона.

Вы также можете использовать View.post(), чтобы добавить что-то в очередь сообщений View, но я не знаю, гарантировано ли, что макет произошел в конце его (некоторые говорят, что это не так, но затем даже Groupon + Google делает это неправильно).

Для фрагмента карты:

MapFragment.getView().post(new Runnable(){
 run() {
 ...Use the layout params...
 }
}


Как говорится в документации, вы должны использовать этот

mapa.moveCamera(CameraUpdateFactory.newLatLngBounds(Builder.build(), 
 this.getResources().getDisplayMetrics().widthPixels, 
 this.getResources().getDisplayMetrics().heightPixels, 
 50));

Если это действие, Вместо этого

mapa.moveCamera(CameraUpdateFactory.newLatLngBounds(Builder.build(), 
 50));

Это работает для меня.

Документация

Примечание. Используйте только более простой метод newLatLngBounds (граница, дополнение) для создания CameraUpdate, если он будет использоваться для перемещения камера после того, как карта претерпела макет. Во время компоновки API вычисляет границы отображения карты, которые необходимы для правильно спроектируйте ограничивающий прямоугольник. Для сравнения вы можете использовать CameraUpdate возвращается более сложным методом newLatLngBounds (граница, ширина, высота, отступы) в любое время, даже до того, как карта претерпела макет, поскольку API вычисляет отображать границы из аргументов, которые вы передаете.


Я думаю, вы хотите что-то сделать после отображения пользовательского интерфейса.

Использование глобального приемника макетов всегда хорошо работало для меня. Это также имеет преимущество в том, что можно изменить ситуацию, если макет изменен, например. если что-то установлено в View.GONE или дочерние представления добавлены/удалены.

public void onCreate(Bundle savedInstanceState)
{
 super.onCreate(savedInstanceState);
 // inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
 LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.main, null); 
 // set a global layout listener which will be called when the layout pass is completed and the view is drawn
 mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
 new ViewTreeObserver.OnGlobalLayoutListener() {
 public void onGlobalLayout() {
 // at this point, the UI is fully displayed
 }
 }
 );
 setContentView(mainLayout);

http://developer.android.com/reference/android/view/ViewTreeObserver.OnGlobalLayoutListener.html


Я бы использовал onWindowFocusChanged (boolean). Просто проверьте, только ли окно активности просто получило фокус.

@Override
public void onWindowFocusChanged(boolean hasFocus)
{
 super.onWindowFocusChanged(hasFocus);
 if( hasFocus )
 {
 // Ask for any view size here
 }
}

licensed under cc by-sa 3.0 with attribution.