Android--Custom Compass View

Source: Internet
Author: User
Tags drawtext getcolor

In some of the previous blogs about Android, there are articles about custom controls. So, in this blog post, I'll show you how to implement the Compass view in a way that customizes the control. We will create a new compass view by extending the view class. It indicates the direction of the current orientation by displaying the traditional compass.

First, realize 1, New Compassview class

This class extends from the view class, and then adds a constructor that allows you to instantiate it in code or populate it from a resource layout. After that, a new Initcompassview method is added to initialize the control and call it in each constructor.

The specific structure code is as follows:

Package Com.lyz.compass.view;import Android.content.context;import Android.util.attributeset;import android.view.view;/** * Custom View class * @author Liuyazhuang * */public class Compassview extends View {public Compassview (Conte XT context) {super (context); Initcompassview ();} Public Compassview (context context, AttributeSet Attrs) {Super (context, attrs); Initcompassview ();} Public Compassview (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle); Initcompassview ( );} /** * Initialize the individual properties of the view */protected void Initcompassview () {setfocusable (true);}}

2, Overwrite Onmeasure method

The compass view should be a positive circle, and should occupy as much space as the canvas allows. Therefore, you can override the Onmeasure method to calculate the length of the shortest edge, and then pass this value and set the height and width through the Setmeasureddimension method.

The specific code is as follows:

@Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {//Compass is a circle that fills as much space as possible, by setting the shortest bounds, Height or width to set the measured size int measurewidth = measure (widthmeasurespec); int measureheight = measure (HEIGHTMEASURESPEC); int d = Math.min (Measurewidth, measureheight); Setmeasureddimension (d, D);}
/** * Decoding data value * @param measurespec * @return */private int measure (int measurespec) {int result = 0;//decodes the measurement description int Specmode = Measurespec.getmode (measurespec); int specsize = Measurespec.getsize (MEASURESPEC);//If no bounds are specified, the default size of 200if is returned ( Specmode = = measurespec.unspecified) {result = 200;} else{//is always returning the entire available bounds because it wants to fill the available space result = specsize;} return result;}

3, modify the Activity_main.xml

Replace the TextView with the new Compassview

The specific code is as follows:

<framelayout xmlns:android= "http://schemas.android.com/apk/res/android"    android:layout_width= "Match_ Parent "    android:layout_height=" match_parent >    <!--Reference Custom View---    < Com.lyz.compass.view.CompassView        android:id= "@+id/compassview"        android:layout_width= "Match_parent"        android:layout_height= "Match_parent"/></framelayout>

4. Define the compass attribute in the resource file 1) Create a text resource in Res/values/strings.xml

<?xml version= "1.0" encoding= "Utf-8"?><resources>    <string name= "App_name" >compass</ string>    <string name= "action_settings" >Settings</string>    <string name= "Hello_world" >hello world!</string>    <string name= "Cardinal_north" >N</string>    <string name= " Cardinal_east ">E</string>    <string name=" Cardinal_south ">S</string>    <string name= "Cardinal_west" >W</string>    </resources>

2) Create a color resource in the Res/values/colors.xml file

<?xml version= "1.0" encoding= "Utf-8"?><resources>    <color name= "Background_color" > #555 </ color>    <color name= "Marker_color" > #AFFF </color>    <color name= "Text_color" > #AFFF < /color></resources>

5. Add a new attribute to the Compassview class

In the Compassview class, add a new property for the direction in which it is displayed, and create its set and get methods.

The direction shown is private float bearing;public float getbearing () {return bearing;} public void setbearing (float bearing) {this.bearing = bearing;}

6. Referencing resource files

Return to the Compassview class, reference each resource created in 4, store the string value as an instance variable, and use the color value to create a new class-scoped paint object. These objects will be used in the next step to draw the compass dial.

The specific code is as follows:

Show direction private float bearing;private paint markerpaint;private paint textpaint;private paint circlepaint;private String Northstring;private string Eaststring;private string southstring;private string weststring;private int textheight;/** * Initializes the individual properties of the view */protected void Initcompassview () {setfocusable (true); Resources r = this.getresources (); circlepaint = new Paint (paint.anti_alias_flag); Circlepaint.setcolor (R.getcolor ( R.color.background_color)); Circlepaint.setstrokewidth (1); Circlepaint.setstyle (Paint.Style.FILL_AND_STROKE); northstring = r.getstring (R.string.cardinal_north); eaststring = r.getstring (r.string.cardinal_east); southString = R.getstring (r.string.cardinal_south); weststring = 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"); markerpaint = new Paint (paint.anti_alias_flag); Markerpaint.setcolor (R.getcolor ( R.color.marker_color));}

7. Draw the Compass

Use the string and paint created in 6 to draw the dial of the compass.

The specific code is as follows:

@Overrideprotected void OnDraw (canvas canvas) {//TODO auto-generated method Stub//super.ondraw (canvas); int Measuredwidth = Getmeasuredwidth (); int measuredheight = Getmeasuredheight (); int px = Measuredwidth/2;int py = measuredHe ight/2;//takes a smaller value for radius int radius = math.min (px, py);//Draw background canvas.drawcircle (px, py, radius, circlepaint); Canvas.save (); Canvas.rotate (-bearing, px, py), int textWidth = (int) textpaint.measuretext ("W"); int cadinalx = Px-textwidth/2;int CAD Inaly = Py-radius + textheight;//Draws a marker every 15 degrees, draws a text for each 45 degrees for (int i = 0; i <; i++) {//Draws a marker canvas.drawline (px, Px-ra Dius, py, Py-radius +, markerpaint); Canvas.save () canvas.translate (0, textHeight);//Draw Basic azimuth if (i% 6 = = 0) {String Dirst ring = ""; 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 = Eaststr Ing;break;case 12:dirstring = southstring;brEak;case 18:dirstring = Weststring;break;default:break;} Canvas.drawtext (dirstring, Cadinalx, Cadinaly, textpaint);} else if (i% 3 = = 0) {//Draw text every 45 degrees String angle = string.valueof (i *); float angletextwidth = textpaint.measuretext (angle); in T angletextx = (int) (PX-ANGLETEXTWIDTH/2); int angletexty = Py-radius + textheight;canvas.drawtext (angle, ANGLETEXTX, a Ngletexty, textpaint);} Canvas.restore (); Canvas.rotate (px, py);} Canvas.restore ();}

8. Add Accessibility support

The Compass view displays the orientation visually, so in order to improve accessibility, when the direction changes, you need to broadcast an accessibility event stating that the text (in this case, content) has changed. To do this, you need to modify the Setbearing method.

The specific code is as follows:

public void setbearing (float bearing) {this.bearing = Bearing;sendaccessibilityevent (accessibilityevent.type_view_ text_changed);}

9. Overriding the Dispatchpopulateaccessibilityevent method

Use the current orientation as a content value for accessibility events.

The specific code is as follows:

@Overridepublic boolean dispatchpopulateaccessibilityevent (Accessibilityevent event) {//TODO auto-generated method Stubsuper.dispatchpopulateaccessibilityevent (event), if (Isshown ()) {String bearingstr = string.valueof (bearing); Bearingstr.length () > accessibilityevent.max_text_length) {bearingstr = bearingstr.substring (0, Accessibilityevent.max_text_length); Event.gettext (). Add (bearingstr); return true;} return false;} return false;}

10, Compassview complete code

Package Com.lyz.compass.view;import Com.lyz.compass.activity.r;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;/** * Custom View class * @author Liuyazhuang * */public class Compassview extends View {//Display direction private float bearing;private Paint Marke Rpaint;private Paint textpaint;private Paint circlepaint;private string Northstring;private string eaststring;private String Southstring;private string weststring;private int textheight;public Compassview (context context) {Super (context ); Initcompassview ();} Public Compassview (context context, AttributeSet Attrs) {Super (context, attrs); Initcompassview ();} Public Compassview (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle); Initcompassview ( );} /** * Initialize the individual properties of the view */protected void Initcompassview () {setfocusable (true); Resources r = This.getrEsources (); circlepaint = new Paint (paint.anti_alias_flag); Circlepaint.setcolor (R.getcolor (r.color.background_ color); Circlepaint.setstrokewidth (1); Circlepaint.setstyle (Paint.Style.FILL_AND_STROKE); northstring = R.getstring (R.string.cardinal_north); eaststring = r.getstring (r.string.cardinal_east); southString = R.getString ( R.string.cardinal_south); weststring = 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"); Markerpaint = new Paint (paint.anti_alias_flag); Markerpaint.setcolor (R.getcolor (R.color.marker_color));} public float getbearing () {return bearing;} public void setbearing (float bearing) {this.bearing = Bearing;sendaccessibilityevent (accessibilityevent.type_view_ text_changed);} @Overridepublic boolean dispatchpopulateaccessibilityevent (Accessibilityevent event) {//TODO auto-generated method Stubsuper.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;} return false;} return false;} @Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {//Compass is a circle that fills as much space as possible, by setting the shortest bounds, Height or width to set the measured size int measurewidth = measure (widthmeasurespec); int measureheight = measure (HEIGHTMEASURESPEC); int d = Math.min (Measurewidth, measureheight); Setmeasureddimension (d, D);} /** * Decoding data value * @param measurespec * @return */private int measure (int measurespec) {int result = 0;//decodes the measurement description int Specmode = Measurespec.getmode (measurespec); int specsize = Measurespec.getsize (MEASURESPEC);//If no bounds are specified, the default size of 200if is returned ( Specmode = = measurespec.unspecified) {result = 200;} else{//is always returning the entire available bounds because it wants to fill the available space result = specsize;} return result;} @Overrideprotected void OnDraw (canvas canvas) {//TODO auto-generated method Stub//super.ondraw (canvas); int MEAsUredwidth = Getmeasuredwidth (); int measuredheight = Getmeasuredheight (); int px = Measuredwidth/2;int py = measuredHeight /2;//take a smaller value for radius int radius = math.min (px, py);//Draw background canvas.drawcircle (px, py, radius, circlepaint); Canvas.save (); Canvas.rotate (-bearing, px, py), int textWidth = (int) textpaint.measuretext ("W"); int cadinalx = Px-textwidth/2;int CAD Inaly = Py-radius + textheight;//Draws a marker every 15 degrees, draws a text for each 45 degrees for (int i = 0; i <; i++) {//Draws a marker canvas.drawline (px, Px-ra Dius, py, Py-radius +, markerpaint); Canvas.save () canvas.translate (0, textHeight);//Draw Basic azimuth if (i% 6 = = 0) {String Dirst ring = ""; 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 = Eaststr Ing;break;case 12:dirstring = southstring;break;case 18:dirstring = weststring;break;default:break;} Canvas.drawtext (dirstring, Cadinalx, Cadinaly, Textpaint);} else if (i% 3 = = 0) {//Draw text every 45 degrees String angle = string.valueof (i *); float angletextwidth = textpaint.measuretext (angle); in T angletextx = (int) (PX-ANGLETEXTWIDTH/2); int angletexty = Py-radius + textheight;canvas.drawtext (angle, ANGLETEXTX, a Ngletexty, textpaint);} Canvas.restore (); Canvas.rotate (px, py);} Canvas.restore ();}}

11. Using Custom Controls

There are two ways to reference a custom control in Mainactivity, which is to refer to a layout file, to create a custom control object, and to set the custom object to the current view.

1) referencing the layout file

Package Com.lyz.compass.activity;import Android.app.activity;import Android.os.bundle;import com.lyz.compass.view.compassview;/** * Program Main entrance * @author Liuyazhuang * */public class Mainactivity extends Activity {@Overr ideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview ( R.layout.activity_main); Compassview Compassview = (compassview) This.findviewbyid (R.id.compassview); compassview.setbearing (0);}}

2) Create a custom control object

Package Com.lyz.compass.activity;import Android.app.activity;import Android.os.bundle;import com.lyz.compass.view.compassview;/** * Program Main entrance * @author Liuyazhuang * */public class Mainactivity extends Activity {@Overr ideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Compassview Compassview = new Compassview (this); Setcontentview (Compassview); compassview.setbearing (0);}}

Second, the Operation effect


Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Android--Custom Compass View

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.