Как получить размер виджета Android после расчета макета? - PullRequest
11 голосов
/ 19 мая 2010

У меня есть макет, который определяет размеры виджетов в относительном измерении, например:

<LinearLayout ... layout_height="fill_parent">
     <ImageView ... layout_height="wrap_content" />
     <TextView ... layout_height="120dp" />
</LinearLayout>

Сразу после onCreate, я хочу знать, какова высота ImageView. Как это сделать?

Примечание: Если я позвоню getHeight() в onCreate, я получу 0.

Я также пробовал imageView.postDelayed, он работает на эмуляторе 2.1, но не работает на эмуляторе 1.5 (я тоже получил 0).

Наконец, я попытался создать Handler, а затем я звоню handler.postDelayed с задержкой 10 мс. Он работает как в эмуляторе 2.1, так и в 1.5, но потерпел неудачу, когда я запускаю программу в отладчике eclipse (Итак, я пришел к выводу, что использование задержки не гарантирует, что получение высоты произойдет после того, как представление изображения будет размечено).

Ответы [ 2 ]

11 голосов
/ 19 мая 2010

Причина, по которой вы получаете размер 0, заключается в том, что макет не закончен до тех пор, пока не будет полностью создано действие, то есть onCreate (), onStart () и onResume () все прошли. Самый простой способ узнать точный размер, который я знаю, - это вызвать ваш метод после завершения макета, например, с помощью прослушивателя щелчка на кнопке. Поскольку кнопка не отображается до тех пор, пока макет не будет завершен, размер должен быть доступен к моменту запуска прослушивателя щелчков.

Это только предположение, но я представляю, что это трудно сделать именно потому, что они не хотят, чтобы люди вмешивались в размеры компоновки после того, как система только что закончила выкладывать экран. Если бы они предоставили обратный вызов onLayoutFinished (), то вы могли бы застрять в цикле, если изменили макет в этом. Например, представьте: макет завершен; Вызов onLayoutFinished (), и вы измените макет там; существующий макет теперь недействителен; макет переделан; onLayoutFinished () вызывается снова; Ваш код вызывается снова - и так далее.

Еще один способ сделать это - создать пользовательский View и переопределить метод onMeasure(int, int). Система вызывает этот метод, чтобы получить размер каждого просмотра; если вы используете что-то вроде моего примера ниже, вы можете получить рекомендуемый размер до окончания макета:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //getMeasuredHeight() and getMeasuredWidth() now contain the suggested size
}

(я написал, что это рекомендуемый размер, потому что я думаю, что размер можно изменить после этого на основе ограничений макета. Однако, это смутное воспоминание о том, что я читал некоторое время назад, и я никогда не экспериментировал в деталях. ) Как только вы это сделаете, вы можете использовать размер для того, что вы хотите сделать - вы даже можете изменить размер, который он будет использовать, используя setMeasuredDimension(newX, newY).

7 голосов
/ 01 января 2011

Объект View предоставляет метод, называемый onSizeChanged (int w, int h, int oldw, int oldh). Он вызывается, когда макет изменяет размер одного из его компонентов. Если вы переопределите этот метод, то код в вашей версии этого метода будет знать размер самого себя, как показано в следующем фрагменте.

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    bounds = new Rect();
    this.getDrawingRect(bounds);
    // bounds will now contain none zero values
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...