一、效果:
1,點選一下,生成一個四位數驗證碼,
2,并且驗證碼由一個矩形框包裹着
二、參閱本案例主要留兩個點:
1,繪制驗證碼和矩形的過程(onDraw),以及擷取字元串的寬高(Paint.getTextBounds)
2,重點關注測量過程,即onMeasure()方法的使用
三、代碼:
MainActivity中的代碼:
package com.myapplication.myyanzhengcode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
/**
* 自定義繼承View,寫一個随機産生驗證碼(4位)
* 1.繼承View
* 2.在ondraw()方法裡面繪制随機生成的字元串(Random)
* 3.設定點選的監聽,監聽到點選之後更改生成的數字(重繪)
* 4.因為布局裡面設定的屬性,我需要重新計算顯示控件的大小(重要)
* 5.驗證你的控件
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
MyYanzheng.java 檔案中的代碼:
package com.myapplication.myyanzhengcode;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
/**
* 效果,點選一次,生成一次驗證碼
* Created by Administrator on 2016/2/26.
*/
public class MyYanZheng extends View {
private Paint codePaint;
private Paint rectPaint;
private String data = "1234";
private Rect rectString;
public MyYanZheng(Context context) {
super(context);
}
public MyYanZheng(Context context, AttributeSet attrs) {
super(context, attrs);
//初始化
init();
//設定監聽,點選一次就重新生成一次驗證碼
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
data = getRandom2();
//重新繪制,讓點選前的重置為無效
invalidate();
}
});
}
//初始化畫筆
private void init() {
//設定生成代碼的畫筆的屬性
codePaint = new Paint();
codePaint.setColor(Color.RED);
codePaint.setStrokeWidth();
codePaint.setTextSize();
//設定矩形畫筆屬性
rectPaint = new Paint();
rectPaint.setStyle(Paint.Style.STROKE);//空心風格
rectPaint.setColor(Color.GREEN);
rectPaint.setStrokeWidth();
//通過一個矩形将繪制文字包裹在裡面,那麼你的控件大小就轉換成矩形的大小
rectString = new Rect();
/**
* 1,字元串内容 2,字元串起點 3,字元串長度 4,空矩形
*/
codePaint.getTextBounds(data, , data.length(), rectString);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//記住顯示的順序不要寫反了,否則圖層覆寫,影響顯示
//畫矩形
canvas.drawRect(, , getWidth(), getHeight(), rectPaint);
//畫驗證碼
canvas.drawText(data, , getHeight(), codePaint);
}
//生成四位随機數的方法一
// public String getRandom() {
// Random random = new Random();
// Set<Integer> set = new HashSet<>();
// 循環注意終止條件是set.size()<4
// for (int i = 0; set.size() < 4; i++) {
// int value = random.nextInt(10);
// set.add(value);
// }
// //将生成的驗證碼裝載stringbuffer裡面
// StringBuffer stringBuffer = new StringBuffer();
// for (Integer i : set) {
// stringBuffer.append(i);
// }
// return stringBuffer.toString();
// }
//生成四位随機數的方法二(弊端:隻能生成>1000的數字,如0069此法無法生成)
public String getRandom2() {
//(int) (Math.random() * (大數 - 小數 + 1) + 小數)
String codeStr = (int) (Math.random() * ( - + ) + ) + "";
return codeStr;
}
/**
* 當設定wrap_content屬性的時候,系統測量的不準确你需重新計算
* MeasureSpec這個類可以幫助我們進行計算和擷取目前在布局裡面設定的模式
* At_most-------wrap_content
* Exactly-------match_parent,或者固定尺寸,如100dp;
* At_most通常計算不準确,需要自己計算
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//擷取目前寬度設定模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
//擷取寬度參考值,下面高度同理分别擷取
int widthCK = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightCK = MeasureSpec.getSize(heightMeasureSpec);
int width, height;
if (widthMode == MeasureSpec.EXACTLY) {
//如果精确測量模式,直接指派
width = widthCK;
} else {
//如果不是精确測量模式,取字元串的寬度來指派
width = rectString.width();
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightCK;
} else {
height = rectString.height();
}
//重新設定計算的值
setMeasuredDimension(width, height);
}
}
布局檔案中代碼:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.myapplication.myyanzhengcode.MainActivity"
>
<com.myapplication.myyanzhengcode.MyYanZheng
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
效果圖: