android 自定义控件以及自定义view学习(随机验证码生成)

来源:互联网 发布:办公室暧昧 知乎 编辑:程序博客网 时间:2024/06/05 00:34

在上一篇的博客中介绍了自定义控件的属性,详情见  android 自定义控件属性(TypedArray以及attrs解释)那么在这基础上实现随机验证码生成,里面的代码是自定义控件以及涉及到自定义view绘画。

资源下载

1、先看实现的效果图



看到这个效果图是不是感觉还可以。那么就看看源码吧。

2、attr文件

<?xml version="1.0" encoding="utf-8"?><resources>    <attr name="titleText" format="string" />    <attr name="titleTextColor" format="color" />    <attr name="titleTextSize" format="dimension" />    <declare-styleable name="AuthCodeView">        <attr name="titleText" />        <attr name="titleTextColor" />        <attr name="titleTextSize" />    </declare-styleable></resources>


3、布局layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:authcodeview="http://schemas.android.com/apk/res/com.example.authcodeview"    android:id="@+id/LinearLayout1"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <com.example.authcodeview.view.AuthCodeView            android:id="@+id/AuthCodeView"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="10dp"            authcodeview:titleText="3712"            authcodeview:titleTextColor="#00ffff"            authcodeview:titleTextSize="40sp" />        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="点击验证码,换一张" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="输入验证码" />        <EditText            android:id="@+id/editText1"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:ems="10"            android:inputType="number" >            <requestFocus />        </EditText>    </LinearLayout>    <Button        android:id="@+id/button1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="验证" /></LinearLayout>


4、自定义AuthCodeView.class

继承View,重写了
onMeasure(int widthMeasureSpec, int heightMeasureSpec)
onDraw(Canvas canvas)方法。
看代码,有详细注释了。

package com.example.authcodeview.view;import java.util.Random;import com.example.authcodeview.R;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.TypedValue;import android.view.View;public class AuthCodeView extends View{// 点数设置public static final int POINT_NUM = 100;// 线段数设置public static final int LINE_NUM = 2;//文本private String mTitleText;// 文本的颜色private int mTitleTextColor;// 文本的大小private int mTitleTextSize;String[] mCheckNum = new String[4];Random random = new Random();//绘制时控制文本绘制的范围private Rect mBound;private Paint mPaint;public AuthCodeView(Context context, AttributeSet attrs){this(context, attrs, 0);}public AuthCodeView(Context context){this(context, null);}/** * 获得我自定义的样式属性 *  * @param context * @param attrs * @param defStyle */public AuthCodeView(Context context, AttributeSet attrs, int defStyle){super(context, attrs, defStyle);/** * 获得我们所定义的自定义样式属性 */TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AuthCodeView, defStyle, 0);//获取在attr文件下,名字为AuthCodeView的declare-styleable属性有几个int n = a.getIndexCount();for (int i = 0; i < n; i++){int attr = a.getIndex(i);switch (attr){//这个属性可以不要,因为都是随机产生case R.styleable.AuthCodeView_titleText:mTitleText = a.getString(attr);break;case R.styleable.AuthCodeView_titleTextColor:// 默认颜色设置为黑色mTitleTextColor = a.getColor(attr, Color.BLACK);break;case R.styleable.AuthCodeView_titleTextSize:// 默认设置为16sp,TypeValue也可以把sp转化为pxmTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));break;}}a.recycle();mTitleText = randomText();/** * 获得绘制文本的宽和高 */mPaint = new Paint();mPaint.setTextSize(mTitleTextSize);mBound = new Rect();mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);this.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){mTitleText = randomText();postInvalidate();}});}//随机产生验证码private String randomText(){StringBuffer sbReturn = new StringBuffer();for (int i = 0; i < 4; i++) {StringBuffer sb = new StringBuffer();int randomInt = random.nextInt(10);mCheckNum[i] = sb.append(randomInt).toString();sbReturn.append(randomInt);}return sbReturn.toString();}//获取验证码public String getAuthCode() {return mTitleText;}//重写这个方法,设置自定义view控件的大小@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){// super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = 0;int height = 0;/** * 设置宽度 */int specMode = MeasureSpec.getMode(widthMeasureSpec);int specSize = MeasureSpec.getSize(widthMeasureSpec);switch (specMode){case MeasureSpec.EXACTLY:// 明确指定了width = getPaddingLeft() + getPaddingRight() + specSize;break;case MeasureSpec.AT_MOST:// 一般为WARP_CONTENTwidth = getPaddingLeft() + getPaddingRight() + mBound.width();break;}/** * 设置高度 */specMode = MeasureSpec.getMode(heightMeasureSpec);specSize = MeasureSpec.getSize(heightMeasureSpec);switch (specMode){case MeasureSpec.EXACTLY:// 明确指定了height = getPaddingTop() + getPaddingBottom() + specSize;break;case MeasureSpec.AT_MOST:// 一般为WARP_CONTENTheight = getPaddingTop() + getPaddingBottom() + mBound.height();break;}setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas){//画背景颜色mPaint.setColor(Color.BLUE);canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);//划线 mPaint.setColor(mTitleTextColor);int [] line;for(int i = 0; i < LINE_NUM; i ++){//设置线宽mPaint.setStrokeWidth(5);line = getLine(getMeasuredHeight(), getMeasuredWidth());            canvas.drawLine(line[0], line[1], line[2], line[3], mPaint);        } // 绘制小圆点int [] point; int randomInt;for(int i = 0; i < POINT_NUM; i ++)    {//随机获取点的大小randomInt = random.nextInt(5);point = getPoint(getMeasuredHeight(), getMeasuredWidth());            canvas.drawCircle(point[0], point[1], randomInt, mPaint);        }//绘制验证控件上的文本int dx = 20; for(int i = 0; i < 4; i ++){canvas.drawText("" + mCheckNum[i],dx, getHeight() / 2 + getPositon(mBound.height() / 2), mPaint);            dx += (getWidth() / 2 - mBound.width() / 2) + i / 5 + 20;        }//canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);}//计算验证码的绘制y点位置private  int getPositon(int height) {int tempPositoin = (int) (Math.random() * height);if (tempPositoin < 20) {tempPositoin += 20;}return tempPositoin;}// 随机产生点的圆心点坐标public static int[] getPoint(int height, int width) {int[] tempCheckNum = { 0, 0, 0, 0 };tempCheckNum[0] = (int) (Math.random() * width);tempCheckNum[1] = (int) (Math.random() * height);return tempCheckNum;}//随机产生划线的起始点坐标和结束点坐标public static int[] getLine(int height, int width) {int[] tempCheckNum = { 0, 0, 0, 0 };for (int i = 0; i < 4; i += 2) {tempCheckNum[i] = (int) (Math.random() * width);tempCheckNum[i + 1] = (int) (Math.random() * height);}return tempCheckNum;}}

5、在MainActivity中怎么使用这个自定义AuthCodeView

package com.example.authcodeview;import com.example.authcodeview.view.AuthCodeView;import android.os.Bundle;import android.app.Activity;import android.view.View;import android.view.View.OnClickListener;import android.widget.EditText;import android.widget.Toast;public class MainActivity extends Activity implements OnClickListener{private AuthCodeView mauthCodeView;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initUI();}private void initUI() {mauthCodeView = (AuthCodeView)findViewById(R.id.AuthCodeView);findViewById(R.id.button1).setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.button1:EditText editText = (EditText)findViewById(R.id.editText1);String codeString = editText.getText().toString().trim();if (codeString.equals(mauthCodeView.getAuthCode())) {Toast.makeText(this, "验证码验证正确!", Toast.LENGTH_LONG).show();}else {Toast.makeText(this, "验证码错误!", Toast.LENGTH_LONG).show();}break;default:break;}}}

再说一遍资源下载点击

资源下载




3 0