I konw the difference between getWidth() and getMeasuredWidth(),
but I can not understand the difference between MeasureSpec.getSize(widthMeasureSpec) and getWidth(),
which width does MeasureSpec.getSize(widthMeasureSpec) get?
thx~~
MeasureSpec.getSize(widthMeasureSpec) returns the preferred width or the specified witdth of a view you want to create. This may or may not be the same as getWidth() after the view has been created, as views may change size based on the width of other views, screen orientation etc.
Ok lets see.
getMeasuredWidth() returns the width measurement set in onMeasure() via setMeasuredDimension().
getWidth() returns the final width of the view. The Parent view may accept the measurements set in onMeasure (set via setMeasuredDimension()). In which case getWidth and getMeasuredWidth will return the same value. If the Parent view decides that the measurements you set cannot be used, either because it's too big or too small then it will set the final width to something more appropiate. In which case getWidth will have the final valid width and will be different from getMeasuredWidth(). Always use getWidth() in onDraw(). only use getMeasuredWidth() if you want to know if the parent changed the width you previously set in onMeasure().
Finally to explain MeasureSpec.getSize(widthMeasureSpec) you need to understand the following from the official documentation:
If you need finer control over your view's layout parameters,
implement onMeasure(). This method's parameters are View.MeasureSpec
values that tell you how big your view's parent wants your view to be,
and whether that size is a hard maximum or just a suggestion. As an
optimization, these values are stored as packed integers, and you use
the static methods of View.MeasureSpec to unpack the information
stored in each integer. Custom View Components
As you can read from the snippet. WidthMeasureSpec and WeightMeasureSpec are not pixel measurments. To get the actual pixel value use MeasureSpec.getSize():
int width = MeasureSpec.getSize(widthMeasureSpec)
PD:This all applies to the height as well
For more Infomation see my answer here(its not marked as the answer):
MeasureSpec returns a 0 value
Related
I have custom view with child items, which are configureable via xml. However they are can be configurable in runtime via something like a Configuration class. After that I just notify parent view about changes and all is ok.BTW. My question in fact touches measurement: I can change child items size in runtime, but for the first launch I want to set to all of them size (width and height) accordingly to layout params defined in xml.
Maybe some code will add more clarification to you.
protected int getItemWidth() {
if (cell != null) {
int width = cell.getWidth();
return width == 0 ? <layout_width_defined_in_xml> : ScreenUtils.convertToDp(context, width);
} else {
return canvasWidth;
}
}
So, I want to know. Is possible to get layout params before measurement? And how to that?
The size defined in XML isn't always the right size the view should have when it's actually laid out. For example, a child of a LinearLayout may have android:layout_width="0", but might have nonzero width because of android:layout_weight. (There are other examples as well with other kinds of layouts.) Additionally, the values match_parent and wrap_content map to negative integer values in java code, which I don't think is helpful to you here.
If your custom view is interested in measuring and positioning child views, you should be overriding onMeasure() and onLayout(). If you aren't doing that or if you don't need to do that, getWidth() and getHeight() will tell you a view's actual size, and getMeasuredWidth() and getMeasuredHeight() will tell you the measured size (which can differ from the actual size). THe only caveat is that you have to wait for the first measure/layout before calling those 4 methods because otherwise those methods all return zero.
If you do want to inspect the layout parameters of a view, you can do
LayoutParams params = view.getLayoutParams();
int width = params.width;
int height = params.height;
As noted, either or both of those may be negative. You can compare them to LayoutParams.MATCH_PARENT and LayoutParams.WRAP_CONTENT to check for these cases, but again I'm not sure this is helpful to you if you aren't implementing onMeasure() and onLayout().
You can do this in callback ViewTreeObserver.OnGlobalLayoutListener. You can get view dimensions here and set size other views with these dimensions.
I was going through this http://developer.android.com/guide/topics/ui/declaring-layout.html when i cam across a line stating that the height may, but do not have to, be different from the measured height, I was thinking of how can the measured height be different from height of a layout.
The methods View#getMeasuredWidth() and View#getMeasuredHeight() represents the dimensions the view wants to be, before all views in the layout are calculated and laid in the screen.
After View#onMeasure(int, int) and View#onLayout(boolean, int, int, int, int), views measurements could be change to accommodate everything. These (possible) new values are then accessible through View#getWidth() and View#getHeight().
From the View class reference:
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().
TextView.getMinHeight() appears in API 16. But TextView.setMinHeight() appears in API 1. Where is any possible way to get min height in pre API 16 version without reflection?
Use ViewCompat.getMinimumHeight(view) from support-v4 library.
There's no way to get it without reflection.
The field is called mMaximum. It can hold a value in pixels or in lines of text, that's why it's not called mMaxHeight.
Saving the value in setMaxHeight() is not ideal, because there's also setMaxLines() method, which changes the max mode and effectively clears the max height value. You would have to overload all methods writing mMaximum field.
short answer:
View.getLayoutParams().height
View.getLayoutParams().width
other possibilities :
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().
ways:
using the famous OnGlobalLayoutListener
This is one of the most used mechanisms to get the view dimensions. You attach a Global Layout Listener to the view hierarchy. It helps you actually get the width of all the views in your view heirarchy:
by forcing a measurement of the View
View.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
int widht = View.getMeasuredWidth();
int height = View.getMeasuredHeight();
I have seen a lot of examples of creating custom views and layouts in android. What I've learned from them is that the measure (as said on Android developer's site) method is onMeasure(), which has widthMeasureSpec and heightMeasureSpec as parameters.
What is the actual meaning of those parameters?
What are their initial values?
With what values they are called if the custom view that I am creating is the parent view for my activity?
I am really very confused about these questions.
widthMeasureSpec and heightMeasureSpec are compound variables. Meaning while they are just plain old ints, they actually contain two separate pieces of data.
The first part of data stored in these variables is the available space (in pixels) for the given dimension.
You can extract this data using this convenience method:
int widthPixels = View.MeasureSpec.getSize( widthMeasureSpec );
The second piece of data is the measure mode, it is stored in the higher order bits of the int, and is one of these possible values:
View.MeasureSpec.UNSPECIFIED
View.MeasureSpec.AT_MOST
View.MeasureSpec.EXACTLY
You can extract the value with this convenience method:
int widthMode = View.MeasureSpec.getMode( widthMeasureSpec );
You can do some logic, change one or both of these, and then create a new meassureSpec using the last convenience method:
int newWidthSpec = View.MeasureSpec.makeMeasureSpec( widthPixels, widthMode );
And pass that on down to your children, usually by calling super.onMeasure( widthMeasureSpec, heightMeasureSpec );
In onMeasure() the MeasureSpec pattern serves the purpose of passing in the maximum allowed space your view and it's children are allowed to occupy. It also uses the spec mode as a way of placing some additional constrains on the child views, informing them on how they are allowed to use the available space.
A good example of how this is used is Padding. ViewGroups take the available width and height, and subtract out their padding, and then create a new meassureSpec, thus passing a slightly smaller area to their children.
This article will be helpful for you. I'm answering your question from the context of the article.
1. What is the actual meaning of those parameters?
Answer:
widthMeasureSpec Horizontal space requirements as imposed by the parent view to the child view.
heightMeasureSpec Vertical space requirements as imposed by the parent view to the child view
2. What are their initial values?
Answer:
when MODE_SHIFT = 30 when values are -
MeasureSpec.UNSPECIFIED = 0 << MODE_SHIFT = 0
MeasureSpec.EXACTLY = 1 << MODE_SHIFT = 1073741824
MeasureSpec.AT_MOST = 2 << MODE_SHIFT = 2147483648
3. With what values they are called if the custom view that I am creating is the parent view for my activity?
Answer:
It will depend on what height and width you give in the parent view. You will get a good insight about it in the last part of the article which also shows a chart below I mentioned -
I'm creating a custom component, where can I know the dimensions this can assume on it's parent? In Layout it's defined with fill_parent x fill_parent.
I tried getWidth() x getHeight() on the constructor, on the onMeasure method and onFinishInflate, in all cases this return 0, I wish to know the size it's have to draw some components in independent screen size.
You can override onMeasure() and get values from there.
http://developer.android.com/reference/android/view/View.html#onMeasure(int, int)
In onMeasure you can actually set your own dimensions for the component and build component accordingly to sizes after that.
Use View.MeasureSpec.getSize(one of the parameters methods takes in. Either width, or height) to get dimensions.
getWidth() and getHeight() will only be populated after the Layout Phase, that is after onLayout() has been called.
You should not use the values within onMeasure() or getMeasuredWidth()/getMeasuredHeight(), since those are only the dimensions the View is initially offered or would like to have, not necessarily the ones it actually ends up getting.
See http://developer.android.com/guide/topics/ui/how-android-draws.html for more information.