getMeasuredWidth returns totally wrong value
Asked Answered
R

1

28

I have to measure a View for spacing others. I use this code for that:

ViewGroup view = ...;
view.setPadding(10, 0, 10, 0);
int wrapContent = RelativeLayout.LayoutParams.WRAP_CONTENT;
int specWidth = MeasureSpec.makeMeasureSpec(wrapContent, MeasureSpec.AT_MOST);
view.measure(specWidth, specWidth);
int questionWidth = view.getMeasuredWidth();

This works as expected on an Android 4.3 emulator.

However the returned measured width on a Samsung Galaxy XCover 2 (S7710) Android 4.1.2 phone, is 16777214... I tried everything, masking with View.MEASURED_SIZE_MASK, but nothing helped.

Could you provide some help with this? Thanks in advance!

Rectus answered 14/12, 2013 at 18:5 Comment(2)
It would help to know what's inside your viewgroup (provide xml). I just hit this same issue and solved it, I think yours is no different but let's see that layout of yours. // You don't have to mask what's returned by getMeasured*(), these values are already masked.Nad
There is no xml. The children of the ViewGroup is dynamically instantiated and added.Rectus
N
66

Passing WRAP_CONTENT instead of an actual value to makeMeasureSpec() won't do any good, I don't think those were meant to be used together.

Use actual constraint value as first parameter (e.g. size of the parent view or dimensions of the screen) with the MeasureSpec.AT_MOST mode, which is basically Math.min() -- with arguments being the value you put in the spec and the view's desired dimension.

MeasureSpec.EXACTLY will make it use the spec value, MeasureSpec.UNSPECIFIED will make it use the view's desired value. So if you don't have any constraints (like if you put your view into a ScrollView) your option is MeasureSpec.UNSPECIFIED -- and any value as first argument.

So, {gurus, correct me if I'm wrong} you get WRAP_CONTENT behavior with any mode other than MeasureSpec.EXACTLY

That being said, try:

ViewGroup view = ...;
view.setPadding(10, 0, 10, 0);
// Either this
int specWidth = MeasureSpec.makeMeasureSpec(parentWidth, MeasureSpec.AT_MOST);
// Or this
int specWidth = MeasureSpec.makeMeasureSpec(0 /* any */, MeasureSpec.UNSPECIFIED);
view.measure(specWidth, specWidth);
int questionWidth = view.getMeasuredWidth();

PS Funny thing about 16777214, take a look at the number in binary: https://www.google.ru/search?q=16777214+in+binary It's -2 (which is the constant value of LayoutParams.WRAP_CONTENT) but with 8 most significant bits truncated with a logical operation (hence no minus), there's something in call stack of measure() that does this :) I wonder if this is a bug. Maybe it should be checking the argument for being negative and throwing an exception or something.

Nad answered 13/2, 2014 at 17:22 Comment(3)
You deserve more than just an upvote.. Bounty coming your way in 23 hours.. Thanx a lot for a brilliant explanation. I've been scratching my head on this for a best part of 4 hours.Actinomorphic
Great explanation. Really love it when people develop the answers this way. Made it easy to understand and adjust exactly for my needs. Thanks a lot!Deuteragonist
Sir, with this post you have earned your entry to Valhalla.Pipit

© 2022 - 2024 — McMap. All rights reserved.