Как вы можете сказать, когда макет был нарисован? - PullRequest
186 голосов
/ 12 октября 2011

У меня есть собственное представление, которое рисует прокручиваемое растровое изображение на экране. Чтобы инициализировать его, мне нужно передать размер в пикселях родительского объекта макета. Но во время функций onCreate и onResume макет еще не отрисован, поэтому layout.getMeasuredHeight () возвращает 0.

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

Что я хочу знать, так это как я могу определить, когда макет рисуется? Есть ли событие или обратный звонок?

Ответы [ 7 ]

371 голосов
/ 12 октября 2011

Вы можете добавить наблюдателя дерева в макет.Это должно вернуть правильную ширину и высоту.onCreate() вызывается перед созданием дочерних представлений.Так что ширина и высота еще не рассчитаны.Чтобы получить высоту и ширину, поместите это в метод onCreate():

final LinearLayout layout = (LinearLayout) findViewById(R.id.YOUR_VIEW_ID);
ViewTreeObserver vto = layout.getViewTreeObserver(); 
vto.addOnGlobalLayoutListener (new OnGlobalLayoutListener() { 
    @Override 
    public void onGlobalLayout() {
        layout.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
        int width  = layout.getMeasuredWidth();
        int height = layout.getMeasuredHeight(); 

    } 
});
55 голосов
/ 13 мая 2016

Очень простой способ - просто набрать post() на вашем макете.Это запустит ваш код на следующем шаге, после того как ваше представление уже будет создано.

YOUR_LAYOUT.post( new Runnable() {
    @Override
    public void run() {
        int width  = YOUR_LAYOUT.getMeasuredWidth();
        int height = YOUR_LAYOUT.getMeasuredHeight(); 
    }
});
21 голосов
/ 21 ноября 2014

Чтобы избежать устаревшего кода и предупреждений, вы можете использовать:

view.getViewTreeObserver().addOnGlobalLayoutListener(
        new ViewTreeObserver.OnGlobalLayoutListener() {
            @SuppressWarnings("deprecation")
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    view.getViewTreeObserver()
                            .removeOnGlobalLayoutListener(this);
                } else {
                    view.getViewTreeObserver()
                            .removeGlobalOnLayoutListener(this);
                }
                yourFunctionHere();
            }
        });
3 голосов
/ 09 апреля 2018

Альтернативой обычным методам является подключение к чертежу вида.

OnPreDrawListener вызывается много раз при отображении вида, поэтому не существует конкретной итерации, в которой ваш вид имеет допустимые измеренные ширину или высоту. Для этого требуется, чтобы вы постоянно проверяли (view.getMeasuredWidth() <= 0) или устанавливали ограничение на количество проверок на measuredWidth больше нуля.

Существует также вероятность того, что представление никогда не будет отображено, что может указывать на другие проблемы с вашим кодом.

final View view = [ACQUIRE REFERENCE]; // Must be declared final for inner class
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
    @Override
    public boolean onPreDraw() {
        if (view.getMeasuredWidth() > 0) {     
            view.getViewTreeObserver().removeOnPreDrawListener(this);
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
            //Do something with width and height here!
        }
        return true; // Continue with the draw pass, as not to stop it
    }
});
3 голосов
/ 20 июня 2013

Другой ответ:
Попробуйте проверить размеры вида в onWindowFocusChanged.

2 голосов
/ 07 марта 2019

Просто проверьте это, вызвав метод post на вашем макете или просмотре

 view.post( new Runnable() {
 @Override
 public void run() {
    // your layout is now drawn completely , use it here.
  }
});
1 голос
/ 12 октября 2011

Когда вызывается onMeasure, представление получает измеренную ширину / высоту. После этого вы можете позвонить layout.getMeasuredHeight().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...