文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android自定义控件深入学习 Android生成随机验证码

2022-06-06 09:06

关注

在上一篇的文章中介绍了自定义控件的属性,详情见《详解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); 
 } 
  
 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转化为px 
    mTitleTextSize = 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() 
  { 
   @Override 
   public 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控件的大小 
 @Override 
 protected 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_CONTENT 
   width = 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_CONTENT 
   height = getPaddingTop() + getPaddingBottom() + mBound.height(); 
   break; 
  } 
  setMeasuredDimension(width, height); 
 } 
 @Override 
 protected 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; 
 @Override 
 protected 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); 
 } 
 @Override 
 public 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; 
  } 
 } 
} 

源码下载:Android生成随机验证码Demo

您可能感兴趣的文章:Android自定义view制作绚丽的验证码Android自定义控件通用验证码输入框的实现Android自定义View获取注册验证码倒计时按钮Android自定义Chronometer实现短信验证码秒表倒计时功能Android自定义View实现随机验证码Android自定义方框EditText注册验证码Android自定义View实现验证码Android自定义控件实现验证码倒计时Android自定义View绘制随机生成图片验证码Android View教程之自定义验证码输入框效果


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯