Android Rewrite view implements a completely new control _android

Source: Internet
Author: User
Tags getcolor

In general, Android implements custom controls in three different ways.

Ⅰ, inherits existing controls, and expands the functionality of its controls.

Ⅱ, combine existing controls to achieve more powerful controls.

Ⅲ, overriding view implementation of new controls

This article discusses one of the most difficult forms of custom control, overriding view to implement entirely new controls.

First, we want to understand in what circumstances, we need to rewrite the view to implement a completely new control, generally when we encounter the native control can not meet our existing requirements, we can consider creating a new view to achieve the functionality we need. Creating a new View implementation custom control is divided into a few steps:

Ⅰ, in the Onmeasure () method, measures the size of the custom control so that the custom control can adapt itself to the various requirements of the layout.

Ⅱ, in the OnDraw () method, uses Shanha (canvas and paint) to draw the content to be displayed.

Ⅲ, in the OnLayout () method to determine where the control is displayed.

Ⅳ, the Ontouchevent () method handles the control's touch events.

The corresponding mind map is as follows:

To say nothing, we use a few small cases to explain exactly how to implement a custom control.

De jure loop control with proportional progress

First look at the schematic diagram of this control:

With this simple schematic, we have a clear picture of the percentage of projects that we have completed. With this simple schematic, we can quickly divide the graph into three parts. Ⅰ, outer ring, Ⅱ, inside the garden, three, the corresponding text. With this idea in mind, we just need to draw one at a time in the OnDraw () method. I'm here for simplicity, set the width of this control to the width of the screen.

First, it's still the same, set some custom properties for the custom control to make it easier for the caller to extend it, and the custom property's setting code is:

 <declare-styleable name= "Circleview" >
  <attr name= "textsize" format= "Dimension"/> <attr
  Name = "Text" format= "string"/>
  <attr name= "circlecolor" format= "color"/> <attr name=
  "Arccolor" format= "Color"/>
  <attr name= "textcolor" format= "color"/> <attr "name=" StartAngle "format="
  Integer "/>
  <attr name=" sweepangle "format=" integer "/>
 </declare-styleable>

Ⅰ, textsize--correspond to the size of the intermediate text

Ⅱ, text--correspond to intermediate text

Ⅲ, circlecolor--corresponding to the color of the inner circle

Ⅳ, arccolor--corresponding to the outer ring color

Ⅴ, textcolor--color of corresponding text

The starting angle of Ⅵ and startangle--corresponding to outer ring

Ⅶ and sweepangle--corresponding to outer loop scanning angle

The next thing is to get these custom properties in the initialization method of the custom control:

TypedArray ta = context.obtainstyledattributes (attrs,
    r.styleable.circleview);
  if (Ta!= null) {
   Circlecolor = ta.getcolor (r.styleable.circleview_circlecolor, 0);
   Arccolor = Ta.getcolor (r.styleable.circleview_arccolor, 0);
   TextColor = Ta.getcolor (r.styleable.circleview_textcolor, 0);
   Textsize = Ta.getdimension (R.styleable.circleview_textsize, m);
   Text = ta.getstring (r.styleable.circleview_text);
   StartAngle = Ta.getint (r.styleable.circleview_startangle, 0);
   Sweepangle = Ta.getint (R.styleable.circleview_sweepangle,);
   Ta.recycle ();
  }

Here is a Zui zi Hou, in order to release more resources, be sure to typedarray this object for the release of resources.

Next, in the Onmeasure () method, initialize to draw the brush style, get the screen width, calculate the coordinates of the middle position, and specify the width-high code for the external rectangle as follows:

 private void Init () {
  int length = math.min (width, height);
  Mcirclexy = LENGTH/2;
  Mradius = length * 0.5F/2;
  Mcirclepaint = new Paint (paint.anti_alias_flag);
  Mcirclepaint.setcolor (Circlecolor);
  MRECTF = new RECTF (length * 0.1f, length * 0.1f, Length * 0.9f,
    length * 0.9f);

  Marcpaint = new Paint (paint.anti_alias_flag);
  Marcpaint.setcolor (Arccolor);
  Marcpaint.setstyle (Paint.Style.STROKE);
  Marcpaint.setstrokewidth ((Width * 0.1f));

  Mtextpaint = new Paint (paint.anti_alias_flag);
  Mtextpaint.settextsize (TEXTSIZE);
  Mtextpaint.setcolor (textcolor);
  Mtextpaint.settextalign (Align.center);

 }

Set our custom properties to different brushes.

After so much preparation, all we need is to draw the inner circle, outer ring and text in the OnDraw method. The code is as follows:

@Override
 protected void OnDraw (Canvas Canvas) {
  super.ondraw (Canvas);
  Drawsth (canvas);
 }

 private void Drawsth (Canvas Canvas) {
  canvas.drawcircle (mcirclexy, Mcirclexy, Mradius, mcirclepaint);
  Canvas.drawarc (MRECTF, StartAngle, Sweepangle, False, marcpaint);
  Canvas.drawtext (text, 0, Text.length (), mcirclexy, mcirclexy + textsize
    /4, mtextpaint);
 

It should be pointed out that the ring needs to be drawn in a specified rectangular area, and that you want to specify the starting angle, the scan angle, and these variables are custom attributes.

The final running effect of this custom control is:

Second, dynamic bar chart

Bar chart, it should be a more common icon in the chart display system. Static diagrams are like this:

What we need to do with this simple sketch is to draw a rectangle and then translate each of the rectangular x coordinates into a certain unit, and we see a phenomenon where the starting point of each bar is inconsistent and the termination point is the same. Starting coordinates with a random (random function) just fine, the realization of static bar chart is this idea:

First, calculate the width and height of each rectangle in the Onmeasure () method, where each rectangle defaults to the height of the screen for convenience, and the width of each rectangle is defined as the width of the screen multiplied by 80% divided by the number of rectangles. Then initialize the brush (Paint) According to the width and height. Why do I have to initialize the brush based on the width and height, and here I am rendering the custom view more lifelike, using the lineargradient (linear renderer), which needs to use a rectangular width and height. What needs to be pointed out is that this custom control is dynamic, and I just need OnDraw method to constantly redraw, here to prevent the control from refreshing too fast, I refresh the view every 300 milliseconds. The complete source code for this control is as follows:

public class Volumneview extends View {private Paint mpaint;
 private int mcount;
 private int mwidth;
 private int mrectheight;
 private int mrectwidth;
 Private LinearGradient mlineargradient;
 Private double mrandom;

 private float mcurrentheight;

 public static final int OFFSET = 5;
  Public Volumneview (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr);

 Initview (context, attrs);
  private void Initview (context context, AttributeSet attrs) {mpaint = new Paint (Paint.anti_alias_flag);
  Mpaint.setcolor (Color.green);
  Mpaint.setstyle (Paint.Style.FILL);
  TypedArray ta = context.obtainstyledattributes (attrs, R.styleable.volumneview);
   if (Ta!= null) {Mcount = Ta.getint (R.styleable.volumneview_count, 6);
  Ta.recycle ();
 } public Volumneview (context, AttributeSet attrs) {This (context, attrs, 0);
 The public Volumneview {This (context, NULL); } @Override protected void OnsizechanGed (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH);
  Mwidth = Getmeasuredwidth ();
  Mrectheight = Getmeasuredheight ();
  Mrectwidth = (int) (mwidth * 0.8/mcount);
  Mlineargradient = new LinearGradient (0, 0, mrectwidth, Mrectheight, Color.green, Color.yellow, Tilemode.clamp);

 Mpaint.setshader (mlineargradient);
  } @Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas);
   for (int i = 0; i < Mcount i++) {mrandom = Math.random ();
   Mcurrentheight = (float) (mrectheight * mrandom);
   Float width = (float) (Mwidth * 0.4/2 + OFFSET);
  Canvas.drawrect (width + i * mrectwidth, mcurrentheight, Width + (i + 1) * mrectwidth, Mrectheight, Mpaint);
 } postinvalidatedelayed (300);
 }


Finally, the results are as follows:

PostScript, through these two simple controls, I believe you have to understand the basic steps of the custom control, of course, to really do the custom control, we still need to follow this step by step, come on!

Related Article

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.