90

I have designed an layout in which LinearLayout has 2 children LinearLayout and FrameLayout and in each child I put different views.

I just wanted to measure height and width of FrameLayout so that I could serve my purpose.

In program I am using

int height,width;

FrameLayout fr=(FrameLayout)findviewbyid(R.id.fr);
height=fr.getHeight();
width=fr.getWidth();

returns value as 0 for both

Even I tried with following code int height,width;

FrameLayout fr=(FrameLayout)findviewbyid(R.id.fr);
height=fr.getMeasuredHeight();
width=fr.getMeasuredWidth();

returns same value 0

and finally I tried with following code, int height,width;

FrameLayout fr=(FrameLayout)findviewbyid(R.id.fr);
height=fr.getgetLayoutParams().height();
width=fr.getLayoutParams().width;

returns me -2 and -1

I want the solution to get height and width of any layout programmatically?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Rohit
  • 2,646
  • 6
  • 27
  • 52
  • See this question http://stackoverflow.com/questions/3779173/determining-the-size-of-an-android-view-at-runtime – VinhNT Feb 21 '14 at 06:19
  • Nice article for understanding when and how android views dimensions are set https://cheesecakelabs.com/blog/understanding-android-views-dimensions-set/ – Krešimir Prcela Jun 13 '20 at 11:39

19 Answers19

173

The view itself, has it's own life cycle which is basically as follows:

  • Attached

  • Measured

  • Layout

  • Draw

So, depending on when are you trying to get the width/height you might not see what you expect to see, for example, if you are doing it during onCreate, the view might not even been measured by that time, on the other hand if you do so during onClick method of a button, chances are that by far that view has been attached, measured, layout, and drawn, so, you will see the expected value, you should implement a ViewTreeObserver to make sure you are getting the values at the proper moment.

LinearLayout layout = (LinearLayout)findViewById(R.id.YOUR VIEW ID);
ViewTreeObserver vto = layout.getViewTreeObserver(); 
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
    @Override 
    public void onGlobalLayout() { 
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                this.layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                this.layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } 
        int width  = layout.getMeasuredWidth();
        int height = layout.getMeasuredHeight(); 

    } 
});
Alireza Noorali
  • 3,129
  • 2
  • 33
  • 80
Martin Cazares
  • 13,637
  • 10
  • 47
  • 54
  • 6
    Note that removeGlobalOnLayoutListener is deprecated so you have to write this.layout.getViewTreeObserver().removeOnGlobalLayoutListener(this); in recent android api. – Nicolas Massart Jan 13 '17 at 15:03
  • 1
    In case that code solution above gives you zero height / width, check this answer: https://stackoverflow.com/a/31515283/1735603 – Firzen Jun 12 '19 at 12:29
  • You are not using the var ViewTreeObserver vto, so what's the point on assign it that method call? – Windgate Aug 13 '21 at 14:22
44

Just wanted to add an answer here, since Koltin has some convenience methods to do this, which are a lot less ugly than adding and removing a onGlobalLayoutListener:

view.doOnLayout {
    it.measuredWidth
    it.measuredHeight
}

You can see more of the convinience methods here.

Schadenfreude
  • 1,522
  • 1
  • 20
  • 41
40

As CapDroid say, you are trying to get the size before the view drawn, another possible solution could be to do a Post with a runnable on the View:

mView.post(new Runnable() {
        @Override
        public void run() {
            int width = mView.getWidth();
            int height = mView.getHeight();
        }
}
Ali Khaki
  • 1,184
  • 1
  • 13
  • 24
Julian
  • 2,490
  • 24
  • 20
15

I think you are getting Height and Width in OnCreate() method that's why you getting always 0 values because at that time your view still not created.

Try to get height and width on some button click or else..

Niranj Patel
  • 32,980
  • 10
  • 97
  • 133
  • I have almost the same problem. I'm beginner in android. What is the best/way place to do the things then? Currently i'm creating few buttons in onCreate and want to position them. Where is best place to do it? – void Jun 24 '17 at 07:44
13

just give your height and You will get height or even width if wanted.

/** * Get the view height before the view will render * @param view the view to measure * @return the height of the view */

public static int getViewHeight(View view) {
    WindowManager wm =
            (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();

    int deviceWidth;

    if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2){
        Point size = new Point();
        display.getSize(size);
        deviceWidth = size.x;
    } else {
        deviceWidth = display.getWidth();
    }

    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    view.measure(widthMeasureSpec, heightMeasureSpec);
    return view.getMeasuredHeight(); //        view.getMeasuredWidth();
}
Siddhesh Shirodkar
  • 891
  • 13
  • 16
11

In Kotlin you can simply do this:

fr.post {
    height=fr.height
    width=fr.width
}
valerybodak
  • 4,195
  • 2
  • 42
  • 53
Dan Bray
  • 7,242
  • 3
  • 52
  • 70
7

If you get -1 or -2 it could also be the numeric value of LayoutParams.WRAP_CONTENT (-2) or LayoutParams.MATCH_PARENT (-1).

7

I had same issue but didn't want to draw on screen before measuring so I used this method of measuring the view before trying to get the height and width.

Example of use:

layoutView(view);
int height = view.getHeight();

//...

void layoutView(View view) {
    view.setDrawingCacheEnabled(true);
    int wrapContentSpec = 
        MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
    view.measure(wrapContentSpec, wrapContentSpec);
    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
}
Zoe
  • 27,060
  • 21
  • 118
  • 148
Asaf
  • 381
  • 4
  • 4
5

Most easiest way is to use ViewTreeObserver, if you directly use .height or .width you get values as 0, due to views are not have size until they draw on our screen. Following example will show how to use ViewTreeObserver

ViewTreeObserver viewTreeObserver = YOUR_VIEW_TO_MEASURE.getViewTreeObserver();
        if (viewTreeObserver.isAlive()) {
            viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {

                    YOUR_VIEW_TO_MEASURE.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    int viewHeight = YOUR_VIEW_TO_MEASURE.getHeight();
                    int viewWeight = YOUR_VIEW_TO_MEASURE.getWidth();

                }
            });
        }

if you need to use this on method, use like this and to save the values you can use globle variables.

3

try with this metods:

int width = mView.getMeasuredWidth();

int height = mView.getMeasuredHeight();

Or

int width = mTextView.getMeasuredWidth();

int height = mTextView.getMeasuredHeight();
jmorales
  • 53
  • 3
2

try something like this code from this link

ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
 viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
  view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
  viewWidth = view.getWidth();
  viewHeight = view.getHeight();
}
 });
}

hope this helps.

Community
  • 1
  • 1
i.n.e.f
  • 1,773
  • 13
  • 22
2

As I just ran into this problem thought I would write it for kotlin,

my_view.viewTreeObserver.addOnGlobalLayoutListener {
       // here your view is measured
       // get height using my_view.height
       // get width using my_view.width
    }

or

my_view.post {
       // here your view is measured
       // get height using my_view.height
       // get width using my_view.width
    }
Aziz
  • 1,976
  • 20
  • 23
2

If you code in Kotlin use this nice extension function :

inline fun View.getDimensions(crossinline onDimensionsReady: (Int, Int) -> Unit) {
    lateinit var layoutListener: ViewTreeObserver.OnGlobalLayoutListener
    layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
        viewTreeObserver.removeOnGlobalLayoutListener(layoutListener)
        onDimensionsReady(width, height)
    }
    viewTreeObserver.addOnGlobalLayoutListener(layoutListener)
}

Usage :

view.getDimensions { width, height ->
    println("width = $width")
    println("height = $height")
}
Reza Mohammadi
  • 106
  • 1
  • 1
  • 6
1

The first snippet is correct, but you need to call it after onMeasure() gets executed. Otherwise the size is not yet measured for the view.

sergej shafarenka
  • 20,071
  • 7
  • 67
  • 86
1

For frame:

height=fr.getHeight();
width=fr.getWidth();

For screen:

width = getWindowManager().getDefaultDisplay().getWidth();
height = getWindowManager().getDefaultDisplay().getHeight();
Vamshi
  • 1,495
  • 1
  • 15
  • 31
1

I used DisplayMetrics to get the screen size and then i can assign the width/height to an element in %age

It will be like this

DisplayMetrics dmetrics = new DisplayMetrics();
int widthPixels=dmetrics.widthPixels;
int heightPixels=dmetrics.heightPixels;       

//setting the height of the button 
button_nextPuzzle.setMinHeight((int) ((heightPixels/3)*.30));

Worked for me very well!!!

Yaron
  • 10,166
  • 9
  • 45
  • 65
chetan
  • 411
  • 1
  • 5
  • 8
0

Check behavior Very Simple Solution

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(LOG, "MainActivity - onCreate() called")

        fragments_frame.post {
            Log.d(LOG, " fragments_frame.height:${fragments_frame.width}")
            Log.d(LOG, " fragments_frame.height:${fragments_frame.measuredWidth}")
        }
}
-1

getDefaultDisplay().getHeight is deprecated. So better to use

getResources().getDisplayMetrics().heightPixels;

Amal
  • 261
  • 4
  • 9
-4

you can use coroutines as well, like this one :

CoroutineScope(Dispatchers.Main).launch {
        delay(10)
        val width = view.width()
        val height= view.height()
        // do your job ....
    }