Android Custom View draw randomly generated picture verification code _android

Source: Internet
Author: User
Tags drawtext getcolor stringbuffer

This article is about the Android custom view of the random generation of image verification code, development, we will often need to generate a random image verification code, but this is second, the main still want to summarize some of the custom view development process and some need to pay attention to the place.

Take a look at the effect chart first:


First, summarize the steps to customize the view:

1. Customize View Properties
2, in the view of the construction method to get our custom attributes
3. Rewrite onmesure
4. Rewrite OnDraw
Where the Onmesure method does not have to be rewritten, but most of the cases need to be rewritten

Two, several constructors of View

1, public customview (context)
->java code is directly new to a CustomView instance, it calls this constructor with only one argument;
2, public customview (context, AttributeSet attrs)
-> calls this constructor with two arguments when it is created in the default XML layout file. The AttributeSet type parameter is responsible for bringing the custom attributes in the XML layout file into the view through AttributeSet;
3, public customview (context, AttributeSet attrs, int defstyleattr)
The third parameter in the-> constructor is the default style, where the default style refers to its default style in the theme that is used in the current application or activity, and is invoked only when explicitly called
4, Public CustomView (context context, AttributeSet attrs, int defstyleattr, int defstyleres)
-> The constructor is added at API21 time.

Three, let's start by looking at the code.

1. Custom View properties, first create a attr.xml under res/values/, define the attributes we need to use, and the type of value that declares the corresponding attribute.

<?xml version= "1.0" encoding= "Utf-8"?>
<resources>

 <attr name= "text" format= "string"/>
 <attr name= "textcolor" format= "color"/> <attr name=
 "textsize" format= "Dimension"/>
 < attr name= "bgcolor" format= "color"/> <declare-styleable "name="

 >
  customview <attr "text"/ >
  <attr name= "textcolor/> <attr name=" textsize "/> <attr name=
  " bgcolor "/>
 </declare-styleable>

</resources>

We have defined the font, font color, font size, and font background color 4 properties, format is the value of the property of the type, the format is a total of 10 types, including: String,color,demension,integer,enum, Reference,float,boolean,fraction and Flag.

2, and then declare our custom view in the XML layout

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"
 xmlns:custom= "http:// Schemas.android.com/apk/res-auto "
 android:layout_width=" match_parent "
 android:layout_height=" Match_ Parent ">

 <com.per.customview01.view.customview
  android:layout_width=" Wrap_content "
  android: layout_height= "Wrap_content"
  android:layout_centerinparent= "true"
  android:padding= "10DP"
  Custom: Bgcolor= "#FF27FF28"
  custom:text= "J2RDWQG"
  custom:textcolor= "#ff0000"
  custom:textsize= "36DP"/ >

</RelativeLayout>

Be sure to introduce xmlns:custom= "Http://schemas.android.com/apk/res-auto", where we can use the Res-atuo namespace in Android studio without adding a custom view full class name.

3, in the view of the construction method, get our custom style

/** * Text/private String mtext;
 /** * Text color * * private int mtextcolor;
 /** * Text Size * * private int mtextsize;
 /** * Text Background color */private int mbgcplor;
 Private Rect Mbound;

 Private Paint Mpaint;
 Public CustomView {This (context, NULL);
 Public CustomView (context, AttributeSet attrs) {This (context, attrs, 0);
  Public CustomView (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); /** * Get the Custom style attribute we defined/TypedArray a = Context.gettheme (). Obtainstyledattributes (Attrs, R.styleable.customview, D
  efstyleattr, 0);
   for (int i = 0; i < A.getindexcount (); i++) {int attr = A.getindex (i);
     Switch (attr) {Case r.styleable.customview_text:mtext = a.getstring (attr);
    Break Case R.styleable.customview_textcolor://The default text color is set to black Mtextcolor = A.getcolor (R.styleable.customview_textcolor,
     Color.Black);
    Break Case R.styleable.customview_bgcolOR:////The default text background color is set to blue Mbgcplor = A.getcolor (R.styleable.customview_bgcolor, Color.Blue);
    Break Case R.styleable.customview_textsize://The default setting is 16sp,typevalue can also convert sp to px mtextsize = a.getdimensionpixelsize (attr
     , (int) typedvalue.applydimension (typedvalue.complex_unit_sp, Getresources (). Getdisplaymetrics ());
   Break
  } a.recycle ();
  Gets the width and height mpaint = new Paint () of the drawn text;

  Mpaint.settextsize (mtextsize);
  Mbound = new Rect ();
 Mpaint.gettextbounds (mtext, 0, Mtext.length (), mbound);

 }

We have rewritten 3 construction methods, and in the previous constructor we have said that the default layout file calls the construction method of two parameters, so remember to have all the constructors call the construction method of three parameters and then get the custom attribute in the construction method of three parameters.
The first method of constructing a parameter and the construction method of two parameters are as follows:

 Public CustomView {
  super (context);
 }

 Public CustomView (context, AttributeSet attrs) {
  Super (context, attrs);
 }

One thing to note is that super should be changed to this, and then let the constructor of one parameter refer to the construction method of two parameters, and the construction method of two parameters refers to the construction method of three parameters, the code is as follows:

 Public CustomView {This
  (context, NULL);
 }

 Public CustomView (context, AttributeSet attrs) {This
  (context, attrs, 0);
 }

4, rewrite the Ondraw,onmesure method

@Override
 protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
  super.onmeasure ( Widthmeasurespec, Heightmeasurespec);

 @Override
 protected void OnDraw (Canvas Canvas) {
  super.ondraw (Canvas);
  Mpaint.setcolor (Mbgcplor);
  Canvas.drawrect (0, 0, getmeasuredwidth (), Getmeasuredheight (), mpaint);

  Mpaint.setcolor (Mtextcolor);
  Canvas.drawtext (Mtext, getwidth ()/2-mbound.width ()/2, GetHeight ()/2 + mbound.height ()/2, mpaint);
 

The view's drawing process begins with the Viewroot Performtravarsals method, and the three processes of measure, layout, and draw can ultimately draw a view, where:
• measuring--onmeasure (): Used to measure view width and height to determine the size of the view
• Layout--onlayout (): Used to determine where view is placed in the parent container ViewGroup
• Draw--ondraw (): Responsible for drawing view on screen

Take a look at this picture of the effect


Careful friends will find that in the above layout file, we are the width and height set to wrap_content, but this effect chart is not what we want, this is because the system to help us measure the height and width by default is Match_parnet, when we set the clear width and height, The result that the system helps us to measure is the result that we set, this is right. But in addition to setting a clear width and height, whether we set it to Wrap_content or match_parent, the system helps us measure the result is match_parent, so when we set the wrap_content, we need to measure ourselves, Which means we need to rewrite the Onmesure method.

Here's how we rewrite the Onmeasure code:

 @Override
 protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
  super.onmeasure ( Widthmeasurespec, Heightmeasurespec);
  int widthmode = Measurespec.getmode (widthmeasurespec);
  int widthsize = measurespec.getsize (widthmeasurespec);
  int heighmode = Measurespec.getmode (heightmeasurespec);
  int heighsize = measurespec.getsize (heightmeasurespec);
  Setmeasureddimension (Widthmode = = measurespec.exactly? Widthsize:getpaddingleft () + getpaddingright () + mBound.width ( ), Heighmode = = measurespec.exactly? Heighsize:getpaddingtop () + getpaddingbottom () + mbound.height ());
 }

Measurespec encapsulates the layout requirements that the parent layout passes to the child layout, there are altogether three modes of Measurespec Specmode:
(1) exactly (complete): Generally set a definite value or match_parent, the parent element determines the size of the child element, the child element will be limited to the given scope and ignore its own size;
(2) At_most (at most): Indicates that the child element reaches at most a given maximum value, generally warp_content;

Let's take another look at the effect chart:

Now this is the result we want, return to the theme, today is the custom view of the random generated picture verification code, now the custom view part of the complete, I put the complete code posted

Package Com.per.customview01.view;
Import Android.content.Context;
Import Android.content.res.TypedArray;
Import Android.graphics.Canvas;
Import Android.graphics.Color;
Import Android.graphics.Paint;
Import Android.graphics.Rect;
Import Android.util.AttributeSet;
Import Android.util.Log;
Import Android.util.TypedValue;

Import Android.view.View;

Import COM.PER.CUSTOMVIEW01.R;

Import Java.util.Random; /** * @author: Adan * @description: * @projectName: CUSTOMVIEW01 * @date: 2016-06-12 * @time: 10:26/public class CustomView extends View {private static final char[] CHARS = {' 0 ', ' 1 ', ' 2 ', ' 3 ', ' 4 ', ' 5 ', ' 6 ', ' 7 ', ' 8 ', ' 9 ', ' a ', ' B ', ' C ', ' d ', ' e ', ' f ', ' g ', ' h ', ' I ', ' j ', ' K ', ' l ', ' m ', ' n ', ' o ', ' P ', ' Q ', ' R ', ' s ', ' t ', ' u ', ' V ', ' w ', ' X ', ' Y ', ' z ', ' A ', ' B ', ' C ', ' D ', ' E ', ' F ', ' G ', ' H ', ' I ', ' J ', ' K ', ' L ', ' M ', ' N ', ' O ', ' P ', ' Q ', ' R ', ' S ', ' T ', ' U ', ' V ',
 ' W ', ' X ', ' Y ', ' Z '};
 /** * Initialize the class that generates random numbers * * Private Random Mrandom = new Random (); /** * Initialize variable wordsstring/private StringBuffer SB = new StringBuffer ();
 /** * Text/private String mtext;
 /** * Text color * * private int mtextcolor;
 /** * Text Size * * private int mtextsize;
 /** * Text Background color */private int mbgcplor;
 Private Rect Mbound;

 Private Paint Mpaint;
 Public CustomView {This (context, NULL);
 Public CustomView (context, AttributeSet attrs) {This (context, attrs, 0);
  Public CustomView (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); /** * Get the Custom style attribute we defined/TypedArray a = Context.gettheme (). Obtainstyledattributes (Attrs, R.styleable.customview, D
  efstyleattr, 0);
   for (int i = 0; i < A.getindexcount (); i++) {int attr = A.getindex (i);
     Switch (attr) {Case r.styleable.customview_text:mtext = a.getstring (attr);
    Break Case R.styleable.customview_textcolor://The default text color is set to black Mtextcolor = A.getcolor (R.styleable.customview_textcolor, Color.blACK);
    Break Case R.styleable.customview_bgcolor://Default text background color set to blue Mbgcplor = A.getcolor (R.styleable.customview_bgcolor, Colo
     R.blue);
    Break Case R.styleable.customview_textsize://The default setting is 16sp,typevalue can also convert sp to px mtextsize = a.getdimensionpixelsize (attr
     , (int) typedvalue.applydimension (typedvalue.complex_unit_sp, Getresources (). Getdisplaymetrics ());
   Break
  } a.recycle ();
  Gets the width and height mpaint = new Paint () of the drawn text;

  Mpaint.settextsize (mtextsize);
  Mbound = new Rect ();

  Mpaint.gettextbounds (mtext, 0, Mtext.length (), mbound);
    This.setonclicklistener (New Onclicklistener () {@Override public void OnClick (View v) {mtext = Createcode ();
    Mtextcolor = Randomcolor ();
    Mbgcplor = Randomcolor ();
   View to invoke the draw process again to play the role of the interface Refresh Postinvalidate ();
 }
  }); /** * Generate Verification Code */Public String Createcode () {sb.delete (0, Sb.length ());////(int i = 0; i < 6 ; i++) {sb.append (Chars[mrandom.nexTInt (Chars.length)]);
  } log.e ("Generate Verification Code", Sb.tostring ());
 return sb.tostring ();
  /** * Random color/private int randomcolor () {sb.delete (0, Sb.length ());
   for (int i = 0; i < 3; i++) {haxstring = Integer.tohexstring (Mrandom.nextint (0xFF));
   if (haxstring.length () = = 1) {haxstring = "0" + haxstring;
  } sb.append (haxstring);
  } log.e ("Random Color", "#" + sb.tostring ());
 Return Color.parsecolor ("#" + sb.tostring ());  @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec,
  HEIGHTMEASURESPEC);
  int widthmode = Measurespec.getmode (Widthmeasurespec);
  int widthsize = measurespec.getsize (Widthmeasurespec);
  int heighmode = Measurespec.getmode (Heightmeasurespec);
  int heighsize = measurespec.getsize (Heightmeasurespec); Setmeasureddimension (Widthmode = = measurespec.exactly? Widthsize:getpaddingleft () + getpaddingright () + mBound.width ( ), Heighmode = = MeasurespEc. Exactly?
 Heighsize:getpaddingtop () + getpaddingbottom () + mbound.height ());
  } @Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas);
  Mpaint.setcolor (Mbgcplor);

  Canvas.drawrect (0, 0, getmeasuredwidth (), Getmeasuredheight (), mpaint);
  Mpaint.setcolor (Mtextcolor);
 Canvas.drawtext (Mtext, getwidth ()/2-mbound.width ()/2, GetHeight ()/2 + mbound.height ()/2, mpaint);

 }
}

We added a click event, and each time I clicked view I let it print out the generated captcha and font color as well as the font background color, as follows:

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.