Reputation: 382
I have searched for answers regarding this but haven't found a solution. So i am requesting help here. I am creating a custom View. I have overridden onMeasure. Code given Below.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize,heightSize;
int measureWidthSpec = MeasureSpec.getMode(widthMeasureSpec);
int measureHeightSpec = MeasureSpec.getMode(heightMeasureSpec);
widthSize = getCircleWidth(measureWidthSpec, MeasureSpec.getSize(widthMeasureSpec));
heightSize = getCircleHeight(measureHeightSpec,MeasureSpec.getSize(heightMeasureSpec));
int circleSize = Math.min(widthSize,heightSize);
setMeasuredDimension(circleSize, circleSize);
Log.d(TAG, "View Measured and ViewDimension : " + heightSize + " " + MeasureSpec.getSize(widthMeasureSpec));
}
When requesting the size here using MeasureSpec.getSize(widthMeasureSpec), 0 is returned. But for the height i get a value of 67. The getCircleWidth() and getCircleHeight are methods used to fix values according to the specMode. The part of the layout xml file where i declare my view is below.
<com.example.raaja.circleview.CircleView
android:id="@+id/CircleView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/textView"
android:layout_toRightOf="@+id/textView"
circle:circleColor="#5dade2"
circle:innerCircleColor="#2874a6"
circle:numberTextColor="#b3b6b7"
/>
Could anyone help me find why the value 0 is returned. Also the onDraw is not called as i fix a min value in setMeasuredDimension().
Upvotes: 3
Views: 2751
Reputation: 350
Before u can use the measurements passed to onMeasure(int,int)
you need to understand what this parameters mean.
The Official documentation reads as follows:
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. Handle Layout Events
This paragraph tells us 2 Things:
WidthMeasureSpec and WeightMeasureSpec are not pixel measurments. To get the actual pixel value use MeasureSpec.getSize()
int width = MeasureSpec.getSize(widthMeasureSpec)
WidthMeasureSpec and WeightMeasureSpec are suggested or maximum values to be used. To know which is which you can use MeasureSpec.getMode()
int mode = MeasureSpec.getMode(widthMeasureSpec);
then you can test against the defined constants(MeasureSpec.UNSPECIFIED, MeasureSpec.AT_MOST, MeasureSpec.EXACTLY) like so(Note that you must do this for both width and height):
switch (mode) {
case MeasureSpec.UNSPECIFIED:
//no restriction we can set any width
break;
case MeasureSpec.AT_MOST:
//we have to set a value that's less or equal
//to MeasureSpec.getSize(widthMeasureSpec)
break;
case MeasureSpec.EXACTLY:
//we have to use suggested measurement
//use MeasureSpec.getSize(widthMeasureSpec);
break;
}
always make sure the measurements you set are equal or higher than getSuggestedMinimumHeight() and getSuggestedMinimumWidth().
Now with that in mind we can answer your question. When u get a width/height MeasuredSpec of 0, you have to check the mode(Remember this tells you what the measurement means). A value of 0 with MeasureSpec.AT_MOST or MeasureSpec.EXACTLY means that there is no space in the layout for the view, so u must modify the layout and leave some space for the view. Now when you get 0 and the mode is MeasureSpec.UNSPECIFIED then it means that you can set measurement to whatever you want, an example of this is when you have a RecyclerView with a vertical LinearLayoutManager,i t doesn't matter what height you set because the RecyclerView can scroll vertically.
Regards
Upvotes: 2
Reputation: 382
I Have found the answers to this solution from BladeCoder's response. The problem is actually with the Layout.xml. I have defined the View side by side with another button. The Button took up all the width space. So this is the problem. If your view is not drawn below is the 2 point solution.
Check the MeasureSpec.getsize(). If it returns 0 then there is no space for the layout to put view there (either width or height), Fix your layout.xml. If not then proceed to check the Calculations you do to fix a dimension on setMeasuredDimension(). These 2 problems will will be the reason for the second point.
The onDraw() will not be drawn if you pass 0 on setMeasuredDimension(). The reason you can pass a width of 1000 or more but if you pass a height of 0 (like this setMeasureDimension(1000,0)) the view will not be visible as it has zero height.
I hope this answer helped you to find a solution to such a problem stated above.
Upvotes: 3
Reputation: 12929
You did not explain what you exactly want to do in onMeasure()
, but assuming you just want to make the view square, you can simply do this instead:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int circleSize = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(circleSize, circleSize);
}
Upvotes: 1