What is an Android view's measured state? - android

I'm having a hard time finding example usage, or explanations, of the Android View concept of "measured state".
To be clear, this is different from measured width and measured height. See in Android docs.

The general idea is that a View has a desired width and height, which is constrained by two factors.
The first constraint is the parent View to which the View is attached. This will describe the maximum width and size of the View. If the View has asked to be wider or taller than the parent view, then it's measured height and measured width will be constrained such that the values are no greater than the parent's. These values, which can be MATCH_PARENT, WRAP_CONTENT or a dp value, get converted to measured widths and heights once the parent View's width and height constraints are included. This guarantees that no child is larger than it's parent.
The second constraint comes from the View's siblings, or in other words, from other Views attached to the same layout. The ViewGroup (Layout) will resolve a View's width and height such that it displays correctly. These resolved width's and height's are the values you get from getWidth() and getHeight().
There is a lot of good documentation on the Android development portal. In particular look at the Layout section of the View class: http://developer.android.com/reference/android/view/View.html#Layout
Edit: Sorry for misunderstanding your question. I've taken a look at the concept of measured state for a view, and I can only find a single documented state: MEASURED_STATE_TOO_SMALL. This leads me to believe that it's use may be very limited and it's existence is primarily for the purpose of future functionality or to be made use of by custom Views/ViewGroups.
The documentation for MEASURED_STATE_TOO_SMALL states the following:
Bit of getMeasuredWidthAndState() and getMeasuredWidthAndState() that
indicates the measured size is smaller that the space the view would
like to have.
This leads me to believe that the bit will be set whenever a fixed dp/px value is given to the View which is larger than the parent's width and height and therefore the View's measured width and height will have been scaled down.
If you manage to find more states or additional information as to where it is used, please to update the question. All the best!

Related

Custom View onMeasure vs onSizeChanged vs onLayout

I have implemented some custom views in Android and one of the most frequent problems I have is to adapt the layout to the screen, weather by matching the parent's content, MATCH_PARENT, or wrapping its own content, WRAP_CONTENT. The ConstraintLayout, for instance, does not support WRAP_CONTENT.
The trouble starts when I have to adapt the children size, which initially I was doing on onLayout. One use case of this is when I want to have children which width and height respect a certain aspect ratio; and the width grow as much as possible.
So, in my onLayout, if changed was true I had reset constraints reset. However, it was causing a loop, since it changes the layout again.
What would be the proper place to size the custom widget children?
onSizeChanged or onMeasure?

How to indicate width is 'flexible' in Android layout editor?

I want to keep distance from left and right, but keep width of the widget flexible. How can I define it in Android?
I do not understand your question, but i guess you're looking for a way to give your ListView a width which is dynamic based on e.g. the screen width.
You should have a look at MATCH_PARENT
LayoutParams are used by views to tell their parents how they want to
be laid out. See ViewGroup Layout Attributes for a list of all child
view attributes that this class supports.
The base LayoutParams class just describes how big the view wants to
be for both width and height. For each dimension, it can specify one
of:
FILL_PARENT (renamed MATCH_PARENT in API Level 8 and higher), which
means that the view wants to be as big as its parent (minus padding)
WRAP_CONTENT, which means that the view wants to be just big enough to
enclose its content (plus padding)
an exact number
There are subclasses of LayoutParams for different subclasses of ViewGroup. For
example, AbsoluteLayout has its own subclass of LayoutParams which
adds an X and Y value.
https://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html
https://developer.android.com/guide/topics/ui/declaring-layout.html

How does Android achieve the attribute "wrap_content"?

These days I am learning how to customize the view on Android.I know if we set the minimum width, then the system will compare the min width we set and the measured width and choose the proper one to fit the view.What I am confusing is that how does android system change the size of the view according to the content of the view as the word "wrap_content" means.I want to know more details about how to achieve "wrap_content". Thanks a lot.
This is what Official Documentation says (I am adding just a part of it for a quick read)
When a View object's measure() method returns, its getMeasuredWidth() and getMeasuredHeight() values must be set, along with those for all of that View object's descendants. A View object's measured width and measured height values must respect the constraints imposed by the View object's parents. This guarantees that at the end of the measure pass, all parents accept all of their children's measurements. A parent View may call measure() more than once on its children. For example, the parent may measure each child once with unspecified dimensions to find out how big they want to be, then call measure() on them again with actual numbers if the sum of all the children's unconstrained sizes is too big or too small (that is, if the children don't agree among themselves as to how much space they each get, the parent will intervene and set the rules on the second pass).
The measure pass uses two classes to communicate dimensions. The ViewGroup.LayoutParams class is used by View objects to tell their parents how they want to be measured and positioned. The base ViewGroup.LayoutParams class just describes how big the View wants to be for both width and height. For each dimension, it can specify one of:
MATCH_PARENT, which means the View wants to be as big as its parent (minus padding)
WRAP_CONTENT, which means that the View wants to be just big enough to enclose its content (plus padding).
MeasureSpec objects are used to push requirements down the tree from parent to child. A MeasureSpec can be in one of three modes:
UNSPECIFIED: This is used by a parent to determine the desired dimension of a child View. For example, a LinearLayout may call measure() on its child with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how tall the child View wants to be given a width of 240 pixels.
EXACTLY: This is used by the parent to impose an exact size on the child. The child must use this size, and guarantee that all of its descendants will fit within this size.
AT MOST: This is used by the parent to impose a maximum size on the child. The child must guarantee that it and all of its descendants will fit within this size.

Android onMeasure and draw()

I Have some really strange problems.
First problem is as follow:
I read how to override onMeasure(). I did it. I was expecting that when I set width/height in onMeasure that they will be exactly the same in onDraw, but apparently this is not true.
Also I except that measuredWidth will be same as width in draw phase, but again it isn't true.
onMeasure could be called many times. On each call I invoke setMeasuredDimension with calculated width and height. So for example, first time my view should be 480 x 245, on second call I recalculate it again, based on parent of course, and it should be 90 x 245.
For my great surprise android somehow is just ignoring everything but the first call. So in this case my final view size is 480 x 245.
Second issue which is as follow:
My view height is match_parent, my parent height is 0. So how am I supposed to set right height on onMeasure when I don't know it ?
Any Idea how to make android not to ignore my setMeasureDimensions calls and how to set match_parent ?
The space that's allocated to your view doesn't depend only on the size you measured, here's a snapshot of the process :
View.onMeasure gets called during the measurement of your parent. You got your MeasureSpec that is essentially how much space at most you can take (very summarized).
Given these specs, you determine the size of yourself, logically measuring your own children and calling setMeasuredDimension
A while after, your parent assigns you concrete dimensions, based on what you measured (but this also means it can be different). Then as these will be your dimensions, that's the one you have to use. The callback called at this point is onLayout, and you shall layout your children in the process, based on the dimensions that were affected to you.
After all this, your View will be drawn, that is View.dispatchDraw being called and resulting for simple views to onDraw. Drawing yourself also means drawing your children if you're a ViewGroup.
When drawing, the system passes a Canvas whose dimensions are these of the screen, and using translation and clipping, the canvas is passed along views so that they draw themselves. This avoids allocation during draw. For this reason, if your want to know what space is dedicated to you, you should not use Canvas.getWidth or Canvas.getHeight which are the dimensions of the screen, but rather retrieve the clipped dimensions (Canvas.getClipBounds())
And finally, when you correctly retrieve the clip bounds, they should usually be the same as your width and height (View.getWidth or View.getHeight), but they might be different, for example if the canvas was scaled.
So to summarize :
onMeasure purpose, is to determine the size of children, so that ViewGroup can compute they're dezired size.
onLayout purpose is to affect a width and height to each view, propagating to children.
onDraw purpose is to render your view.

Get size of GridView when creating items within its adapter

I want to arrange a set of custom widgets inside a GridView. There are predefined templates which describe a count of elements and arrangement config. Max width and heigh for each of them have to be provided in order to avoid scrolling. How can I get a size of the displayed GridView when computing items size in adapter's "GetView" method?
You have access to few functions in order to get a GridView Height and Width as any other View. Look at the documentation here.
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().
Try doing a quick search on their doc next time, even if it's Xamarin, the Android doc is pretty reliable and you only need some adjustment to make it work.
(e.g.) : grivView.Width; instead of gridView.getWidth(); one being a property on Xamarin to follow C# standards, the other is a function.

Categories

Resources