0.  前言  

验证码无处不在。有人问我,你知道达芬奇password以下是什么吗,对。答案就是达芬奇验证码。

验证码一个最基本的作用就是防止恶意暴力破解登录,防止不间断的登录尝试,事实上能够在server端对该终端进行登录间隔检測。假设间隔太短能够展示拒绝的姿态。可是还是本地验证码作用更加实在。能够减轻server端的压力。这篇将使用自己定义View来实现一个例如以下效果的简易本地验证码。算是对自己定义View知识的复习吧。



1.  布局结构  

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myattribute="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" > <com.calvin.verification_code.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:padding="10dp"
myattribute:text="0 0 0 0 "
myattribute:textcolor="#000"
myattribute:textsize="40sp"
android:id="@+id/myView" /> <EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="number"
android:hint="刷新后输入"
android:layout_below="@+id/myView"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:id="@+id/editText" /> <Button
android:text="确认"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/editText"
android:layout_alignParentEnd="true"
android:layout_marginEnd="10dp"
android:id="@+id/button" />
</RelativeLayout>

在自己定义控件MyView中使用了自己定义属性。面试的时候偶尔也会被问到,事实上并不难。这里使用文字内容、颜色和字号三个自己定义属性。命名空间别忘了加。

自己定义属性声明仅仅须要在values文件夹下声明一个xml文件就可以。文件名称字不重要。重要的是这个name属性,由于我们会在自己定义控件类中通过R.styleable.MyView来找到这个自己定义属性声明信息。

<?

xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyView">
<attr name="text" format="string"/>
<attr name="textcolor" format="color"/>
<attr name="textsize" format="dimension"/>
</declare-styleable>
</resources>

2.  自己定义View类

看一下这个类的构造函数:

public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
for (int i = 0; i < a.getIndexCount(); i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.MyView_text:
mText = a.getString(attr);
break;
case R.styleable.MyView_textcolor:
//二參为默认颜色
mTextColor = a.getColor(attr, Color.BLACK);
break;
case R.styleable.MyView_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, 0, mText.length(), mBound); this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//生成一个随机的四位数字,并发送一个自己定义广播
mText = randomText();
postInvalidate();
} });
}

核心代码就是解析自己定义属性,并初始化一个画笔。并把解析出来的字体大小设置给画笔,设计点击时间,使其被点击后又一次随机产生四位数字验证码,并使用postInvalidate()刷新界面。最后使用mBound记录这个四位数文本的宽高。

2.  自己定义View类中的其它细节

@Override
protected void onMeasure(int widthMeasureSpec, int 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:
width = getPaddingLeft() + getPaddingRight() + mBound.width();
break;
}
//相同逻辑处理高
setMeasuredDimension(width, height);
} @Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(Color.YELLOW);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(mTextColor);
canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
Random random = new Random();
for(int i = 0; i <= 3; i++){
int temp = random.nextInt(colors.length);
mPaint.setColor(colors[temp]);
mPaint.setStrokeWidth(3);
canvas.drawLine(randomStartWidth(),randomStartHeight(),randomEndWidth(),randomEndHeight(),mPaint);
}
}

事实上主要还是measure和draw的过程了。

在onMeasure()方法中最重要的逻辑应该就是处理MeasureSpec.AT_MOST的这样的情况了。这时候前面的mBound.width()就起作用了。还有就是无论何种測量模式,都手动处理了padding的情况。

onDraw()方法中首先绘制了一个黄色矩形作为自己定义View的背景,接着依据自己定义属性中的文字内容和颜色绘制四位数字,最后绘制四条噪声直线。颜色随机,而且起始位置和结束位置也是随机产生的。

3.  实时改变维护的正确验证码

为了验证用户输入的验证码的正确性,须要在MainActivity中维护一个变量。在用户点击自己定义View刷新验证码时,能够实时改变这个变量的值。这里使用自己定义广播实现。在生成一个随机的四位数字,发送一个自己定义广播。

Intent intent = new Intent();
intent.setAction("com.seu_calvin.update");
intent.putExtra("data", sb.toString());
getContext().sendBroadcast(intent);

接着在MainActivity注冊一个广播接收者就可以取得此时的验证码信息,在用户点击确定按钮后在拿到EditText中的值与其进行对照就可以。

这个逻辑还是比較简单的。

笔者水平有限,假设有问题或者错误请多留言交流。

转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/70156547

Android开发——本地验证码的简易实现的更多相关文章

  1. Android开发中验证码的生成

    近期在做电商金融类的项目,验证码的生成方法不可缺少.先学习了一种.经过測试好用.从别处学习的代码,稍修改了一下可选择是否支持识别大写和小写.直接上代码. import android.app.Acti ...

  2. Android JNI 本地开发接口

    前言 我们为什么要用JNI --> 高效.扩展 高效:Native code效率高,数学运算,实时渲染的游戏上,音视频处理 (极品飞车,opengl,ffmpeg,文件压缩,图片处理-) 扩展: ...

  3. Android开发简易教程

    Android开发简易教程 Android 开发因为涉及到代码编辑.UI 布局.打包等工序,有一款好用的IDE非常重要.Google 最早提供了基于 Eclipse 的 ADT 作为开发工具,后来在2 ...

  4. Android 开发--CMakeList调用本地so文件

    这里写代码片Android开发常常遇到Java调用so文件的情况,本文介绍一下Google最近新推出的应用在android studio中的方法–cmakelist.txt格式调用. so文件分为jn ...

  5. Android开发用过的十大框架

    http://blog.csdn.net/u011200604/article/details/51695096 本文系多方综合与转载整合,意在Android开发中能够知道和使用一些好用的第三方支持, ...

  6. android开发新浪微博客户端 完整攻略 [新手必读]

    开始接触学习android已经有3个礼拜了,一直都是对着android的sdk文档写Tutorials从Hello World到Notepad Tutorial算是初步入门了吧,刚好最近对微博感兴趣就 ...

  7. Android 开发一定要看的15个实战项目

    前言: 虽说网上有太多的Android课程,但是大多都是视频,有Android在线开发环境的几乎没有,但是对于学习Android的人来说拥有在线的Android开发环境是非常好的,可以随时动手操作学习 ...

  8. [译]:Xamarin.Android开发入门——Hello,Android深入理解

    返回索引目录 原文链接:Hello, Android_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android深入理解 本部分介绍利用Xamarin开发And ...

  9. (转) Android开发性能优化简介

    作者:贺小令 随着技术的发展,智能手机硬件配置越来越高,可是它和现在的PC相比,其运算能力,续航能力,存储空间等都还是受到很大的限制,同时用户对手机的体验要求远远高于PC的桌面应用程序.以上理由,足以 ...

随机推荐

  1. python爬虫---从零开始(四)BeautifulSoup库

    BeautifulSoup是什么? BeautifulSoup是一个网页解析库,相比urllib.Requests要更加灵活和方便,处理高校,支持多种解析器. 利用它不用编写正则表达式即可方便地实现网 ...

  2. No-10.高级变量类型

    高级变量类型 目标 列表 元组 字典 字符串 公共方法 变量高级 知识点回顾 Python 中数据类型可以分为 数字型 和 非数字型 数字型 整型 (int) 浮点型(float) 布尔型(bool) ...

  3. 前端 (cookie )页面进入存储一次

     <!--引入jq--> <script> var isShowTip = window.sessionStorage.getItem("isShow") ...

  4. Git Bash 常用指令

    1. 关于git bash常用指令 推荐博客: 史上最简单的 GitHub 教程  猴子都能懂的GIT入门 Learn Version Control with Git for Free Git Do ...

  5. saltstack快速部署

    yum install wget deltarpm -y wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/rep ...

  6. python3.x Day6 协程

    协程:#定义来自牛人alex博客协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈 ...

  7. web即时通信技术

    ajax jsonp polling setInterval定期发送ajax请求.服务器压力大,浪费流量,大部分是无效请求 ajax long polling ajax发起请求,服务器对于这个请求一直 ...

  8. SSM调用数据库存储过程

    ServiceImpl中: Map<String,Object> map=new HashMap<String,Object>(); map.put("bid&quo ...

  9. Python数据结构--树遍历算法

    ''' 遍历是访问树的所有节点的过程,也可以打印它们的值. 因为所有节点都通过边(链接)连接,所以始终从根(头)节点开始. 也就是说,我们不能随机访问树中的一个节点. 这里介绍三种方式来遍历一棵树 - ...

  10. 数据结构实验1:C++实现静态顺序表类

    写了3个多小时,还是太慢了.太菜了! 图1 程序运行演示截图1 实验1 1.1 实验目的 熟练掌握线性表的顺序存储结构. 熟练掌握顺序表的有关算法设计. 根据具体问题的需要,设计出合理的表示数据的顺序 ...