extends View to create customized User interface widget
package app.test; import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.util.AttributeSet; import android.view.View; class CompassView extends View { private Paint markerPaint; private Paint textPaint; private Paint circlePaint; private String northString; private String eastString; private String southString; private String westString; private int textHeight; public void setBearing(float _bearing) { bearing = _bearing; } public float getBearing() { return bearing; } private float bearing; public CompassView(Context context) { super(context); initCompassView(); } public CompassView(Context context, AttributeSet attrs) { super(context, attrs); initCompassView(); } public CompassView(Context context, AttributeSet attrs, int defaultStyle) { super(context, attrs, defaultStyle); initCompassView(); } protected void initCompassView() { setFocusable(true); Resources r = this.getResources(); northString = "North"; eastString = "East"; southString = "South"; westString = "West"; circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); circlePaint.setColor(Color.BLACK); circlePaint.setStrokeWidth(1); circlePaint.setStyle(Paint.Style.FILL_AND_STROKE); markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); markerPaint.setColor(Color.RED); textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); textPaint.setColor(Color.BLACK); textHeight = (int) textPaint.measureText("yY"); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = measure(widthMeasureSpec); int measuredHeight = measure(heightMeasureSpec); int d = Math.min(measuredWidth, measuredHeight); setMeasuredDimension(d, d); } private int measure(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.UNSPECIFIED) { result = 200; } else { result = specSize; } return result; } @Override protected void onDraw(Canvas canvas) { int px = getMeasuredWidth() / 2; int py = getMeasuredHeight() / 2; int radius = Math.min(px, py); canvas.drawCircle(px, py, radius, circlePaint); canvas.save(); canvas.rotate(-bearing, px, py); int textWidth = (int) textPaint.measureText("W"); int cardinalX = px - textWidth / 2; int cardinalY = py - radius + textHeight; for (int i = 0; i < 24; i++) { canvas.drawLine(px, py - radius, px, py - radius + 10, markerPaint); canvas.save(); canvas.translate(0, textHeight); if (i % 6 == 0) { String dirString = ""; switch (i) { case (0): { dirString = northString; int arrowY = 2 * textHeight; canvas.drawLine(px, arrowY, px - 5, 3 * textHeight, markerPaint); canvas.drawLine(px, arrowY, px + 5, 3 * textHeight, markerPaint); break; } case (6): dirString = eastString; break; case (12): dirString = southString; break; case (18): dirString = westString; break; } canvas.drawText(dirString, cardinalX, cardinalY, textPaint); } else if (i % 3 == 0) { String angle = String.valueOf(i * 15); float angleTextWidth = textPaint.measureText(angle); int angleTextX = (int) (px - angleTextWidth / 2); int angleTextY = py - radius + textHeight; canvas.drawText(angle, angleTextX, angleTextY, textPaint); } canvas.restore(); canvas.rotate(15, px, py); } canvas.restore(); } } public class Test extends Activity { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); CompassView cv = (CompassView) this.findViewById(R.id.compassView); cv.setBearing(45); } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <app.test.CompassView android:id="@+id/compassView" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>