Если я вызываю getMeasuredWidth() или getWidth() для макета в onResume, они возвращают 0

Если я вызываю getMeasuredWidth() или getWidth() для макета в onResume, они возвращают 0. Я думаю, что в данный момент это представление еще не нарисовано.

Также я думаю, что мне нужно поместить getMeasuredWidth() или getWidth() в метод обратного вызова, вызываемый после того, как макет отрисован и известны измерения вида. Какой метод обратного вызова Android следует использовать?


person mobiledev Alex    schedule 04.08.2011    source источник


Ответы (7)


Вы не можете использовать width/height/getMeasuredWidth/getMeasuredHeight на View до того, как система отобразит его (обычно из onCreate/onResume).

Простое решение для этого — опубликовать Runnable в макете. Runnable будет выполнен после того, как будет выложен View.

BoxesLayout = (RelativeLayout) findViewById(R.id.BoxesLinearLayout);
BoxesLayout.post(new Runnable() {
    @Override
    public void run() {
        int w = BoxesLayout.getMeasuredWidth();
        int h = BoxesLayout.getMeasuredHeight();

        ...
    }
});
person Adorjan Princz    schedule 20.01.2013
comment
Я всегда использовал подход ViewTreeObserver, но он намного проще! - person JohnnyLambada; 30.03.2015
comment
Намного лучше, чем метод ViewTreeObserver - person Ron; 09.05.2015
comment
Большое спасибо. Работает отлично. - person bashan; 01.08.2015
comment
ViewTreeObserver — лучший метод, потому что вы можете получить меру ширины/высоты ДО того, как ваша иерархия представлений будет отображена на экране. Если вы используете .post() таким образом, представление может сначала нарисовать кадр, а затем будет вызван ваш обратный вызов. Если вы изменяете ширину/высоту некоторых ваших представлений внутри Runnable, вы можете увидеть быстрое мерцание происходящих изменений. С ViewTreeObserver вы гарантированно сможете изменить все, что захотите, ДО ТОГО, как ваш экран отобразит первый кадр. Однако, если вы не изменяли какие-либо представления внутри Runnable, оба метода должны работать нормально. - person Bitcoin Cash - ADA enthusiast; 10.03.2016
comment
Действительно полезно для меня. Спасибо :) - person sharma_kunal; 08.08.2016
comment
Я пробовал с ViewTreeObserver, а также с .post, но не повезло... Ширина reccyclerView по-прежнему равна 0, есть идеи, почему? Я использую привязку данных, и мне нужна ширина для некоторых вычислений, но она всегда равна 0, что бы я ни пытался, но она правильно отображается с полной шириной - person jaumard; 07.11.2017
comment
В Kotlin есть функции расширения, которые могут помочь вам получить ширину/высоту View: doOnLayout() или doOnNextLayout(). Также есть doOnPreDraw() :) - person Oleksandr Nos; 08.11.2018

В этом ответе говорится:

Используйте ViewTreeObserver на View, чтобы дождаться первого макета. Только после первого макета будет работать getWidth()/getHeight()/getMeasuredWidth()/getMeasuredHeight().

ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
  viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
      view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      viewWidth = mediaGallery.getWidth();
      viewHeight = mediaGallery.getHeight();
    }
  });
}
person Jeff Axelrod    schedule 29.07.2012
comment
Я удивлен, что подключение к любому из обратных вызовов жизненного цикла не работает с получением ширины. Я попробовал все из них, onCreate(), onStart(), onResume(), и ни в одном из них не была установлена ​​ширина макета. Это решение было первым, что сработало для меня. Спасибо за публикацию. - person John Kroetch; 14.05.2013
comment
О, и removeGlobalOnLayoutListener теперь устарел. Вместо этого API предлагает использовать removeOnGlobalLayoutListener (developer.android.com/reference/android/ view/) для целевых API 16 и новее - person John Kroetch; 14.05.2013

вы можете переопределить onLayout() в вашем представлении; это используется Android для позиционирования каждого из дочерних элементов представления, поэтому вы можете делать то, что хотите, после вызова super(..).

person MrJre    schedule 04.08.2011

Действительно, оказывается, что если макет не отображается на экране, метод getWidth() возвращает 0. Мне кажется, что работает для меня вызов метода Measure() перед вызовом getMeasuredWidth() или getMesuredHeight(). Для метода измерения я использовал аргументы Layout.WRAP_CONTENT, чтобы получить измерение того, что содержит макет.

Надеюсь, это поможет, Михай

person r1k0    schedule 13.02.2012

Более простой способ:

view.post(new Runnable() {
    public void run() {
        view.getWidth();
    }
}
);

http://developer.android.com/reference/android/view/View.html#post(java.lang.Runnable)

person Wonson    schedule 28.07.2015

Решение №1. Чтобы сделать это динамически, вам нужен тег. Тег — это, по сути, способ сохранения воспоминаний для представлений. Поэтому сохраните convertView в другом классе (MyTag). Итак, внутри вашего java-файла:

private LayoutInflater layoutInflater;

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    MyTag holder = null;
    View row = convertView;
    if (row == null) {
      //Inflate the view however u can  
String strInflater = Context.LAYOUT_INFLATER_SERVICE;
        layoutInflater = (LayoutInflater) context.getSystemService(strInflater);
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        row = inflater.inflate(layoutResID, parent, false);
               holder = new MyTag();

            holder.itemName = (TextView) row.findViewById(R.id.example_itemname);
            holder.icon = (ImageView) row.findViewById(R.id.example_image);
            holder.button1 = (Button) row.findViewById(R.id.swipe_button1);
            holder.button2 = (Button) row.findViewById(R.id.swipe_button2);
            holder.button3 = (Button) row.findViewById(R.id.swipe_button3);
            row.setTag(holder);
        } else {
            holder = (MyTag) row.getTag();
        }

        holder.itemName.setText(itemdata.getItemName());
        System.out.println("holder.button3.getMeasuredWidth()= "+ holder.button3.getMeasuredWidth());
        System.out.println("holder.button3.getWidth()= "+ holder.button3.getWidth());

return row;
} //End of getView()


static class MyTag {  //It also works if not static

        TextView itemName;
        ImageView icon;
        Button button1;
        Button button2;
        Button button3;
    }

Решение № 2. Жестко запрограммируйте его. Заранее установите ширину. Внутри вашего файла res/values/dimens.xml включите

<dimen name="your_button_width">50dp</dimen>

Затем в вашем файле res/layout/your_layout.xml включите

        <Button  
         android:layout_width="@dimen/your_button_width"  />

Затем внутри вашего java-файла:

int buttonSize= (int) (context.getResources().getDimension(R.dimen.your_button_width));
person Gene    schedule 12.12.2014

Используйте приведенный ниже код:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
   super.onWindowFocusChanged(hasFocus);
   Log.e("WIDTH",""+view.getWidth());
   Log.e("HEIGHT",""+view.getHeight());
}
person Asif Patel    schedule 10.02.2017