I'm trying to draw a custom view, everything is rendering fine, except the right most portion is cut off. I want the view to fill the parent and only use the needed amount of height (i.e the height of the bitmap I'm drawing. When i remove padding from the xml layout of the activity the custom view renders fine. So I'm not calculating onMeasure with the parents padding taken into account.
Please could someone take a look at this code and describe why and how I am going wrong? Thanks
EDITED TO include @nicko's answer and more detail:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
ViewParent parent = getParent();
int leftPadding = 0;
int rightPadding = 0;
if (parent instanceof ViewGroup) {
leftPadding = ((ViewGroup) parent).getPaddingLeft();
rightPadding = ((ViewGroup) parent).getPaddingRight();
}
float wanabeHeight = calendar.getHeight();
float wanabeWidth = parentWidth - leftPadding - rightPadding;
int height = 0;
//Determine Height
switch(heightMode){
case MeasureSpec.EXACTLY: height = parentHeight;
break;
case MeasureSpec.AT_MOST:
height = Math.min((int)wanabeHeight, parentHeight);
break;
case MeasureSpec.UNSPECIFIED:
default:
height = (int)wanabeHeight;
break;
}
setMeasuredDimension((int)wanabeWidth, height);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
calendarX = left;
personX = (int)((right - left) * 0.5);
checkX = right - check.getWidth() - getPaddingRight();
lineY = (int)((bottom - top) * 0.5);
bitmapY = (int)(((bottom - top) * 0.5) - (calendar.getHeight() * 0.5));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(calendar, calendarX, bitmapY, paint);
canvas.drawBitmap(person, personX, bitmapY, paint);
canvas.drawBitmap(check, checkX, bitmapY, paint);
canvas.drawLine((calendarX + calendar.getWidth() + PADDING), lineY, personX - PADDING, lineY, linePaint);
canvas.drawLine((personX + person.getWidth() + PADDING), lineY, checkX - PADDING, lineY, linePaint);
}
In the onDraw
, everything is relative to the canvas - but it seems that you are drawing everything according to the view positions that come through in onLayout
which are relative to the screen.
So, for your right hand image, you actually need to calculate the X position like this:
checkX = right - left - check.getWidth();
You'll also probably find that the left hand image is indented a bit if the parent has any padding so try positioning it at 0:
calendarX = 0;
You can get parent padding following way:
ViewParent parent = getParent();
int topPadding = 0;
int bottomPadding = 0;
if (parent instanceof ViewGroup) {
topPadding = ((ViewGroup) parent).getPaddingTop();
bottomPadding = ((ViewGroup) parent).getPaddingBottom();
}
And use it:
parentHeight -= topPadding - bottomPadding;
int height = 0;
//Determine Height
switch(heightMode){
case MeasureSpec.EXACTLY:
height = parentHeight;
break;
case MeasureSpec.AT_MOST:
height = Math.min((int)wanabeHeight, parentHeight);
break;
case MeasureSpec.UNSPECIFIED:
default:
height = (int)wanabeHeight;
break;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With