Simple tutorial for Android-46th guns (a compass for custom controls)
Preface
As an innovative developer, you will sooner or later find that the built-in controls cannot satisfy your imagination.
With the ability to expand existing views, build composite controls, and create unique new views, you can create a beautiful user interface that best suits your application workflow, this gives users the best experience.
The best way to create a new view is related to the target:
1. If the existing control can meet the basic functions you want to implement, you only need to modify or extend the appearance or behavior of the existing control. Rewrite the event handler and the onDraw () method.
2. You can create an inseparable and reusable control by combining multiple views so that it can use an associated view function, such as clearing the TextView Composite Control with one click.
3. Create a new control.
Next we will use a small instance to create a compass interface to experience how to customize controls.
1. Create a custom control class Compass to inherit the View:
Package com. example. compass; import android. content. context; import android. content. res. resources; import android. graphics. canvas; import android. graphics. paint; import android. util. attributeSet; import android. view. view; import android. view. accessibility. accessibilityEvent; public class Compass extends View {private Paint makerPaint; private Paint textPaint; private Paint circlePaint; private String north, south, east, west; private int textHeight; public Compass (Context context) {super (context); initCompassView ();} public Compass (Context context, AttributeSet attrs) {super (context, attrs); initCompassView ();} public Compass (Context context, attributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr); initCompassView ();} private void initCompassView () {setFocusable (true); Resources r = this. getResources (); // Circle = new Paint (Paint. ANTI_ALIAS_FLAG); circlePaint. setColor (r. getColor (R. color. background_color); circlePaint. setStrokeWidth (1); circlePaint. setStyle (Paint. style. FILL_AND_STROKE); north = r. getString (R. string. cardinal_north); south = r. getString (R. string. cardinal_south); east = r. getString (R. string. cardinal_east); west = r. getString (R. string. cardinal_west); textPaint = new Paint (Paint. ANTI_ALIAS_FLAG); textPaint. setColor (r. getColor (R. color. text_color); textHeight = (int) textPaint. measureText (yY); makerPaint = new Paint (Paint. ANTI_ALIAS_FLAG); // anti-sawtooth makerPaint. setColor (r. getColor (R. color. maker_color);} @ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super. onMeasure (widthMeasureSpec, heightMeasureSpec); int measureWidth = measure (widthMeasureSpec); int measureHeight = measure (heightMeasureSpec); int d = Math. min (measureHeight, measureWidth); setMeasuredDimension (d, d);} private int measure (int measureSpec) {int result = 0; // decode int speMode = MeasureSpec for the measurement description. getMode (measureSpec); int speSize = MeasureSpec. getSize (measureSpec); if (speMode = MeasureSpec. UNSPECIFIED) {// if no limit is specified, the default returned size is 200 result = 200;} else {// because you want to fill the available space, all rows always return the entire available boundary result = speSize;} return result;} // Add the attribute private float bearing; public float getBearing () {return bearing ;} public void setBearing (float _ bearing) {bearing = _ bearing; sendAccessibilityEvent (AccessibilityEvent. TYPE_VIEW_TEXT_CHANGED); // added support for accessibility and the direction of the compass display} @ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); int mMeasureWidth = getMeasuredWidth (); int mMeasureHeight = getMeasuredHeight (); int px = mMeasureWidth/2; int py = mMeasureHeight/2; int radius = Math. min (px, py); // use the minimum decimal value as the radius; // draw the background canvas. drawCircle (px, py, radius, circlePaint); canvas. save (); canvas. rotate (-bearing, px, py); // rotate-bearing degree angle; // draw the flag int textWidth = (int) textPaint. measureText (W); int cardinalX = px-textWidth/2; int cardinalY = py-radius + textHeight; // draw a tag every 15 degrees, draw a text for (int I = 0; I <24; I ++) {canvas. drawLine (px, py-radius, px, py-radius + 10, makerPaint); canvas. save (); canvas. translate (0, textHeight); // draw the basic orientation if (I % 6 = 0) {String dirString =; switch (I) {case 0: dirString = north; int arrowY = 2 * textHeight; canvas. drawLine (px, arrowY, px-5, 3 * textHeight, makerPaint); canvas. drawLine (px, arrowY, px + 5, 3 * textHeight, makerPaint); break; case 6: dirString = east; break; case 12: dirString = south; break; case 18: dirString = west; break; default: break;} canvas. drawText (dirString, cardinalX, cardinalY, textPaint); // draw text every 45 degrees} 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 () ;}// use the content in the current direction as an accessible event @ Overridepublic boolean dispatchPopulateAccessibilityEvent (AccessibilityEvent event) {super. dispatchPopulateAccessibilityEvent (event); if (isShown () {String bearingStr = String. valueOf (bearing); if (bearingStr. length ()> AccessibilityEvent. MAX_TEXT_LENGTH) bearingStr = bearingStr. substring (0, AccessibilityEvent. MAX_TEXT_LENGTH); event. getText (). add (bearingStr); return true;} else {return false ;}}}
Ii. Configure attributes
Compass
Hello world!
Settings
N
E
S
W
#F555
#AFFF
#AFFF
3. Introduce Custom Controls
package com.example.compass;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Compass compass=(Compass) this.findViewById(R.id.compass);compass.setBearing(0);}}