Android   发布时间:2022-04-28  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Android自定义View绘制随机生成图片验证码大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

本篇文章讲的是Android自定义view随机生成图片验证码,开发中我们会经常需要随机生成图片验证码,但是这个是其次,主要还是想总结一些自定义view的开发过程以及一些需要注意的地方。

按照惯例先看看效果图:

Android自定义View绘制随机生成图片验证码


一、先总结下自定义view的步骤:

1、自定义view属性
2、在View的构造方法中获得我们自定义属性
3、重写onMesure
4、重写onDraw
其中onMesure方法不一定要重写,但大部分情况下还是需要重写的

二、View 的几个构造函数

1、public CustomView(Context context)
―>java代码直接new一个CustomView实例的时候,会调用这个只有一个参数的构造函数
2、public CustomView(Context context,AttributeSet attrs)
―>在认的XML布局@L_801_24@中创建的时候调用这个有两个参数的构造函数。AttributeSet类型的参数负责把XML布局@L_801_24@中所自定义属性通过AttributeSet带入到View内;
3、public CustomView(Context context,AttributeSet attrs,int defStyleAttr)
―>构造函数中第三个参数是认的Style,这里的认的Style是指它在当前Application或者Activity所用的Theme中的认Style,且只有在明确调用的时候才会调用
4、public CustomView(Context context,int defStyleAttr,int defStyleRes)
―>该构造函数是在API21的时候才添加上的

三、下面我们就开始来看看代码

1、自定义view属性,首先在res/values/ 下建立一个attr.xml , 在里面定义我们的需要用到的属性以及声明相对应属性的取值类型

<?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 name="text" />
  <attr name="textColor" />
  <attr name="textSize" />
  <attr name="bgColor" />
 </declare-styleable>

</resources>

我们定义了字体,字体颜色,字体大小以及字体的背景颜色4个属性,format是值该属性的取值类型,format取值类型总共有10种,包括String,color,demension,Integer,enum,reference,float,Boolean,fraction和flag。

2、然后在XML布局中声明我们的自定义view

<RelativeLayout xmlns:android="http://scheR_871_11845@as.android.com/apk/res/android"
 xmlns:custom="http://scheR_871_11845@as.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>

一定要引入xmlns:custom=”http://scheR_871_11845@as.android.com/apk/res-auto”,Android studio中我们可以使用res-atuo命名空间,就不用在添加自定义view全类名。

3、在View的构造方法中,获得我们的自定义的样式

/**
  * 文本
  */
 private String mText;
 /**
  * 文本的颜色
  */
 privatE int mTextColor;
 /**
  * 文本的大小
  */
 privatE int mTextSize;
 /**
  * 文本的背景颜色
  */
 privatE int mBgCplor;
 private Rect mBound;
 private Paint mPaint;

 public CustomView(Context context) {
  this(context,null);
 }

 public CustomView(Context context,AttributeSet attrs) {
  this(context,attrs,0);
 }

 public CustomView(Context context,int defStyleAttr) {
  super(context,defStyleAttr);
  /**
   * 获得我们所定义的自定义样式属性
   */
  TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomView,defStyleAttr,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:
     // 文本颜色设置为黑色
     mTextColor = a.getColor(R.styleable.CustomView_textColor,Color.bLACK);
     break;
    case R.styleable.CustomView_bgColor:
     // 文本背景颜色设置为蓝色
     mBgCplor = a.getColor(R.styleable.CustomView_bgColor,Color.bLUE);
     break;
    case R.styleable.CustomView_textSize:
     // 认设置为16sp,TypeValue也可以把sp转化为px
     mTextSize = a.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getresources().getDisplaymetrics()));
     break;
   }
  }
  a.recycle();
  // 获得绘制文本的宽和高
  mPaint = new Paint();
  mPaint.setTextSize(mTextSizE);

  mBound = new Rect();
  mPaint.getTextBounds(mText,mText.length(),mBound);
 }

我们重写了3个构造方法,在上面的构造方法中说过认的布局@L_801_24@调用的是两个参数的构造方法,所以记得让所有的构造方法调用三个参数的构造方法,然后在三个参数的构造方法中获得自定义属性
一开始一个参数的构造方法和两个参数的构造方法是这样的

 public CustomView(Context context) {
  super(context);
 }

 public CustomView(Context context,AttributeSet attrs) {
  super(context,attrs);
 }

有一点要注意的是super应该改成this,然后让一个参数的构造方法引用两个参数的构造方法,两个参数的构造方法引用三个参数的构造方法代码如下:

 public CustomView(Context context) {
  this(context,0);
 }
 

4、重写onDraw,onMesure方法

@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,getMeasuredWidth(),getMeasuredHeight(),mPaint);

  mPaint.setColor(mTextColor);
  canvas.drawText(mText,getWidth() / 2 - mBound.width() / 2,getHeight() / 2 + mBound.height() / 2,mPaint);
 }

View的绘制流程是从ViewRoot的performTravarsals方法开始的,经过measure、layout和draw三个过程才能最终将一个View绘制出来,其中:
 •测量――onMeasure():用来测量View的宽和高来决定View的大小
 •布局――onLayout():用来确定View在父容器ViewGroup中的放置位置
 •绘制――onDraw():负责将View绘制在屏幕上

来看下此时的效果

Android自定义View绘制随机生成图片验证码


细心的朋友会发现,在上面的布局@L_801_24@中,我们是把宽和高设置为wrap_content的,可是这个效果图怎么看都不是我们想要的,这是因为系统帮我们测量的高度和宽度认是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,这个是对的。但是除了设置明确的宽度和高度,不管我们设置为WRAP_CONTENT还是MATCH_PARENT,系统帮我们测量的结果就是MATCH_PARENT,所以,当我们设置了WRAP_CONTENT时,我们需要自己进行测量,也就是说我们需要重写onMesure方法

下面是我们重写onMeasure代码

 @Override
 protected void onMeasure(int 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());
 }
@H_102_0@measureSpec封装了父布局传递给子布局的布局要求,MeasureSpec的specMode一共有三种模式:
(1)EXACTLY(完全):一般是设置了明确的值或者是MATCH_PARENT,父元素决定了子元素的大小,子元素将被限定在给定的范围里而忽略它本身大小;
(2)AT_MOST(至多):表示子元素至多达到给定的一个最大值,一般为WARP_CONTENT;

我们再看看效果图:

Android自定义View绘制随机生成图片验证码

在这个是我们想要的结果了吧,回归到主题,今天讲的是自定义view随机生成图片验证码,现在把自定义view的部分完成了,我把完整的代码贴出来

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'};
 /**
  * 初始化生成随机数的类
  */
 private Random mRandom = new Random();
 /**
  * 初始化可变字符串
  */
 private StringBuffer sb = new StringBuffer();
 /**
  * 文本
  */
 private String mText;
 /**
  * 文本的颜色
  */
 privatE int mTextColor;
 /**
  * 文本的大小
  */
 privatE int mTextSize;
 /**
  * 文本的背景颜色
  */
 privatE int mBgCplor;
 private Rect mBound;
 private Paint mPaint;

 public CustomView(Context context) {
  this(context,mBound);

  this.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    mText = createCode();
    mTextColor = randomColor();
    mBgCplor = randomColor();
    //View重新调用一次draw过程,以起到界面刷新的作用
    posTinvalidate();
   }
  });
 }

 /**
  * 生成验证码
  */
 public String createCode() {
  sb.delete(0,sb.length()); // 使用之前首先清空内容
  for (int i = 0; i < 6; i++) {
   sb.append(CHARS[mRandom.nexTint(CHARs.length)]);
  }
  Log.e("生成验证码",sb.toString());
  return sb.toString();
 }

 /**
  * 随机颜色
  */
 privatE int randomColor() {
  sb.delete(0,sb.length()); // 使用之前首先清空内容
  String haxString;
  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("随机颜色","#" + sb.toString());
  return Color.parseColor("#" + sb.toString());
 }

 @Override
 protected void onMeasure(int widthMeasureSpec,heighMode == MeasureSpec.EXACTLY ? heighSize : getPaddingTop() + getPaddingBottom() + mBound.height());
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  mPaint.setColor(mBgCplor);
  canvas.drawRect(0,mPaint);
 }
}

我们添加一个点击事件,每一次点击View我都让它把生成的验证码和字体颜色以及字体背景颜色打印出来,如下所示:

Android自定义View绘制随机生成图片验证码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

大佬总结

以上是大佬教程为你收集整理的Android自定义View绘制随机生成图片验证码全部内容,希望文章能够帮你解决Android自定义View绘制随机生成图片验证码所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。