Thursday, September 15, 2011

Android: Aligning Custom Views at Base Line

Have you ever try to align a non-symmetric custom view at a custom base line as follows?


I tried it using base line attribute of Relative Layout.
First adjust the size of view:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//Height should be always width * 7 / 12
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()*7/12);
}


Then Override the getBaseLine method:
@Override
public int getBaseline() {
//base line is from bottom to width/12 (radius of the blue circle)
return getMeasuredHeight()-getMeasuredWidth()/12;
}


Following onDraw method would explain the reason for the above calculation:

@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
//Draw the half circle
paint.setColor(Color.GRAY);
float width = getWidth();
float height = getHeight();
canvas.save();
canvas.translate(width/2, height-width/12);
canvas.drawArc(new RectF(-width/3, -width/3, +width/3, width/3), 0, -180, true, paint);
//Draw small circles
paint.setColor(Color.DKGRAY);
RectF rectF = new RectF(-width/2+width/24, -width/12+width/24, -width/3-width/24,                +width/12-width/24);
canvas.drawOval(rectF, paint);
for(int i = 0 ; i < 15 ;i++){
canvas.rotate(12f);
canvas.drawOval(rectF, paint);
}
//Draw blue circle
paint.setColor(Color.BLUE);
canvas.rotate(-180+30);
canvas.drawOval(new RectF(-width/2, -width/12, -width/3, +width/12), paint);
//Draw red arrow
paint.setColor(Color.RED);
Path path = new Path();
path.moveTo(-width*5/12, 0);
path.lineTo(10, -width/12);
path.lineTo(0, 0);
path.lineTo(10, +width/12);
path.close();
canvas.drawPath(path, paint);
canvas.restore();
}


Finally, create a layout xml as following:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<demo.ui.testing.DemoUITesting
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:layout_alignBaseline="@+id/radioButton1"
android:layout_toRightOf="@+id/radioButton1">
<RadioButton android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/radioButton1"
android:layout_centerVertical="true">
</RelativeLayout>

Enjoy!.

1 comment:

Unknown said...
This comment has been removed by the author.