日常开发中,我们会遇到一些很炫酷的手机短信验证码输入,但系统自带的EditText显然并不能满足所需的短信验证码输入框,因此,在系统自带的EditText基础上自定义短信验证码输入框。

实现思路是:定义类继承EditText,重写onMeasure、onDraw方法,添加onTextChanged监听文本输入,利用Canvas绘制输入文本、输入框及光标图形等。

【输入框背景edit_code_bg.xml(注:具体样式可自主定义)】

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_focused="false"><shape><solid android:color="@android:color/transparent" /><corners android:radius="4dp" /><stroke android:width="1dp" android:color="#F1F1F1" /></shape></item><item android:state_focused="true"><shape><solid android:color="@android:color/transparent" /><corners android:radius="4dp" /><stroke android:width="1dp" android:color="#FFA500" /></shape></item>
</selector>

【光标背景edit_cursor_style.xml(注:具体样式可自主定义)】

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_focused="false"><shape android:shape="rectangle"><solid android:color="@android:color/transparent" /><size android:width="1dp" /></shape></item><item android:state_focused="true"><shape android:shape="rectangle"><solid android:color="#FFA500" /><size android:width="1dp" /></shape></item>
</selector>

【自定义EditText】

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.InputFilter;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;public class CodeEditText extends EditText {public interface OnTextFinishListener {void onTextFinish(CharSequence text, int length);}private int mTextColor;// 输入的最大长度private int mMaxLength;// 边框宽度private int mStrokeWidth;// 边框高度private int mStrokeHeight;// 边框之间的距离private int mStrokePadding;// 光标宽度private int mCursorWidth;// 光标高度private int mCursorHeight;// 方框的背景private Drawable mStrokeDrawable;// 光标的背景private Drawable mCursorDrawable;// 输入结束监听private OnTextFinishListener mOnInputFinishListener;// 是否光标获取焦点private boolean mCursorStateFocused = true;// 记录上次光标获取焦点时间private long mLastCursorFocusedTimeMillis = System.currentTimeMillis();public void setStrokeWidth(int strokeWidth) {mStrokeWidth = strokeWidth;}public void setStrokeHeight(int strokeHeight) {mStrokeHeight = strokeHeight;}public void setStrokePadding(int strokePadding) {mStrokePadding = strokePadding;}public void setCursorWidth(int cursorWidth) {mCursorWidth = cursorWidth;}public void setCursorHeight(int cursorHeight) {mCursorHeight = cursorHeight;}public void setStrokeDrawable(Drawable strokeDrawable) {mStrokeDrawable = strokeDrawable;}public void setCursorDrawable(Drawable cursorDrawable) {mCursorDrawable = cursorDrawable;}/*** 设置最大长度*/public void setMaxLength(int maxLength) {mMaxLength = maxLength;if (maxLength >= 0) {setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});} else {setFilters(new InputFilter[0]);}}/*** 构造方法**/public CodeEditText(Context context) {this(context, null);}public CodeEditText(Context context, AttributeSet attrs) {super(context, attrs);mStrokeWidth = toDip(context, 30);mStrokeHeight = toDip(context, 30);mStrokePadding = toDip(context, 10);mCursorWidth = toDip(context, 1);mCursorHeight = toDip(context, 20);mStrokeDrawable = context.getResources().getDrawable(R.drawable.edit_code_bg);mCursorDrawable = context.getResources().getDrawable(R.drawable.edit_cursor_style);mMaxLength = 6;setMaxLength(mMaxLength);setLongClickable(false);// 去掉背景颜色setBackgroundColor(Color.TRANSPARENT);// 不显示光标setCursorVisible(false);setFocusable(true);setFocusableInTouchMode(true);}@Overridepublic boolean onTextContextMenuItem(int id) {return false;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = getMeasuredWidth();int height = getMeasuredHeight();int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);// 判断高度是否小于推荐高度if (height < mStrokeHeight) {height = mStrokeHeight;}// 判断高度是否小于推荐宽度int recommendWidth = mStrokeWidth * mMaxLength + mStrokePadding * (mMaxLength - 1);if (width < recommendWidth) {width = recommendWidth;}widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, widthMode);heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, heightMode);setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onDraw(Canvas canvas) {mTextColor = getCurrentTextColor();setTextColor(Color.TRANSPARENT);super.onDraw(canvas);setTextColor(mTextColor);// 重绘背景颜色drawStrokeBackground(canvas);drawCursorBackground(canvas);// 重绘文本drawText(canvas);}/*** 重绘背景*/private void drawStrokeBackground(Canvas canvas) {Rect mRect = new Rect();if (mStrokeDrawable != null) {// 绘制方框背景mRect.left = 0;mRect.top = 0;mRect.right = mStrokeWidth;mRect.bottom = mStrokeHeight;int count = canvas.getSaveCount();canvas.save();for (int i = 0; i < mMaxLength; i++) {mStrokeDrawable.setBounds(mRect);mStrokeDrawable.setState(new int[]{android.R.attr.state_enabled});mStrokeDrawable.draw(canvas);float dx = mRect.right + mStrokePadding;// 移动画布canvas.save();canvas.translate(dx, 0);}canvas.restoreToCount(count);canvas.translate(0, 0);// 绘制激活状态// 当前激活的索引int activatedIndex = Math.max(0, getEditableText().length());if (activatedIndex < mMaxLength) {mRect.left = mStrokeWidth * activatedIndex + mStrokePadding * activatedIndex;mRect.right = mRect.left + mStrokeWidth;mStrokeDrawable.setState(new int[]{android.R.attr.state_focused});mStrokeDrawable.setBounds(mRect);mStrokeDrawable.draw(canvas);}}}/*** 重绘光标*/private void drawCursorBackground(Canvas canvas) {Rect mRect = new Rect();if (mCursorDrawable != null) {// 绘制光标mRect.left = (mStrokeWidth - mCursorWidth) / 2;mRect.top = (mStrokeHeight - mCursorHeight) / 2;mRect.right = mRect.left + mCursorWidth;mRect.bottom = mRect.top + mCursorHeight;int count = canvas.getSaveCount();canvas.save();for (int i = 0; i < mMaxLength; i++) {mCursorDrawable.setBounds(mRect);mCursorDrawable.setState(new int[]{android.R.attr.state_enabled});mCursorDrawable.draw(canvas);float dx = mRect.right + mStrokePadding;// 移动画布canvas.save();canvas.translate(dx, 0);}canvas.restoreToCount(count);canvas.translate(0, 0);// 绘制激活状态// 当前激活的索引int activatedIndex = Math.max(0, getEditableText().length());if (activatedIndex < mMaxLength) {mRect.left = mStrokeWidth * activatedIndex + mStrokePadding * activatedIndex + (mStrokeWidth - mCursorWidth) / 2;mRect.right = mRect.left + mCursorWidth;int[] state = new int[]{isFocusable() && isFocusableInTouchMode() && mCursorStateFocused ? android.R.attr.state_focused : android.R.attr.state_enabled};mCursorDrawable.setState(state);mCursorDrawable.setBounds(mRect);mCursorDrawable.draw(canvas);if ((System.currentTimeMillis() - mLastCursorFocusedTimeMillis) >= 800) {mCursorStateFocused = !mCursorStateFocused;mLastCursorFocusedTimeMillis = System.currentTimeMillis();}}}}/*** 重绘文本*/private void drawText(Canvas canvas) {Rect mRect = new Rect();int count = canvas.getSaveCount();canvas.translate(0, 0);int length = getEditableText().length();for (int i = 0; i < length; i++) {String text = String.valueOf(getEditableText().charAt(i));TextPaint textPaint = getPaint();textPaint.setColor(mTextColor);// 获取文本大小textPaint.getTextBounds(text, 0, 1, mRect);// 计算(x,y) 坐标int x = mStrokeWidth / 2 + (mStrokeWidth + mStrokePadding) * i - (mRect.centerX());int y = (canvas.getHeight() + mRect.height()) / 2;canvas.drawText(text, x, y, textPaint);}canvas.restoreToCount(count);}@Overrideprotected void onTextChanged(CharSequence text, int start,int lengthBefore, int lengthAfter) {super.onTextChanged(text, start, lengthBefore, lengthAfter);// 当前文本长度int textLength = getEditableText().length();if (textLength == mMaxLength) {clearFocus();hideSoftInput();if (mOnInputFinishListener != null) {mOnInputFinishListener.onTextFinish(getEditableText().toString(), mMaxLength);}}}public void hideSoftInput() {InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);if (imm != null)imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);}/*** 设置输入完成监听*/public void setOnTextFinishListener(OnTextFinishListener onInputFinishListener) {this.mOnInputFinishListener = onInputFinishListener;}/*** 转 dp 值* @param context* @param paramFloat* @return*/public static int toDip(Context context, float paramFloat) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, paramFloat, context.getResources().getDisplayMetrics());}
}

最终的实现效果图

Android 短信验证码输入框相关推荐

  1. android短信验证码代码,Android短信验证码自动填写实现代码

    今天给大家分享一个Android短信验证码自动填写的功能.先看下效果图,我发送了一条短信到手机,自动填写验证码.如图: 这个小功能运用到了观察者模式,什么是观察者模式? 观察者模式 :定义对象间的一种 ...

  2. android短信验证码方案,Android之短信验证码

    今天所使用的方案只是android手机设备集成短信验证码功能的方案之一. 我们所采用的方案是使用聚合数据的短信验证sdk. 接口文档:https://www.juhe.cn/docs/api/... ...

  3. Android短信验证码自动填写功能的实现

    本文出自:黄敏争的博客 前言: android应用经常会涉及到注册登录功能,而许多的注册登录或修改密码功能常常需要输入短信验证码,通常,用户收到短信需要最小化应用去查看短信再填入验证码,必然比较麻烦, ...

  4. android 短信验证码的实现

    公司用的短信验证码是Mob.com 网址:http://www.mob.com 进入网站 注册登录之后 进入后在上面有应用是让选择android还是ios 之类的,点击下载SDK --选择免费短信验证 ...

  5. android 短信验证码自动填写的二种方法

    转载自:https://blog.csdn.net/VirusDerekRuler/article/details/78506522 现在开发越来越注重用户体验了,现今Android基本都有短信验证功 ...

  6. Android 短信验证码自动填写

    这个也不是什么新东西,目前很多app都有这个功能,最近有几个小伙伴问我是怎么实现的,索性写一篇博客来为大家解答. 实现思路很简单:1.在需要输入验证码的Activity代码注册监听短信的广播 2.拦截 ...

  7. android短信验证码方案,Android开发之属于你的短信验证码(一)

    不飞则已,一飞冲天;不鸣则已,一鸣惊人---------司马迁 最近工作又有新需求,要求用户在注册的时候需要通过手机验证码,这样做的目的是防止用户通过一个邮箱来随便的注册,那么好,今天我们就 一起来学 ...

  8. android 短信验证码自动填写的两种方式

    https://blog.csdn.net/u010399316/article/details/48781319 https://www.01hai.com/note/av123438 https: ...

  9. android 验证码短信验证码,Android​短信验证码倒计时验证的2种常用方式

    前言 ​本文主要介绍的是短信验证码功能,这里总结了两种常用的方式,可以直接拿来使用. 看图 计时器 说明:这里的及时从10开始,是为了演示的时间不要等太长而修改的. 方法如下 1.第一种方式:Time ...

最新文章

  1. nlohmann/json使用笔记
  2. Java面试笔试题大汇总三(最全+详细答案)
  3. Java中的反射的应用
  4. 【Markdown/typora】程序员写博客2分钟简单入门
  5. 下列服务使用的默认端口:ftp,ssh,telnet,dhcp,mail,pop3,smtp,dns,http,sm
  6. 【昇腾】【玩转Atlas200DK系列】为Atlas 200 DK制作python环境离线安装包
  7. 文件那些事儿之一(初稿)
  8. memmove、memcpy和memccpy简介
  9. java 基本语法 二_java基础语法2
  10. Wireshark通过TCP协议抓取QQ好友IP以及定位
  11. python对比excel重复数据_python入门之对比两份excel表格数据
  12. 上行下行带宽什么意思?代表了什么看完你就能懂
  13. 用Python分析豆瓣电影Top250
  14. android T分屏流程
  15. 一千万数据,怎么快速查询
  16. 长沙航空职业技术学院计算机系,长沙航空职业技术学院机器人专业怎么样
  17. 灰度值阈值设置matlab,基本全局阈值法(basic global thresholding)MATLAB实现
  18. 2022国际数维杯C题思路
  19. Python——元组_元组的基本操作_元组与列表相互转换
  20. unity3D 魔兽争霸游戏开发案例教程

热门文章

  1. 用Mouse_event()来模拟鼠标操作
  2. 开发一款系统软件的流程步骤是什么
  3. 关于STM32与OpenMv通讯踩过的那些坑(1)
  4. css(六)--css高级技巧
  5. 免费的DNS服务OpenDNS、Google Public DNS
  6. 超详细Redis入门教程——Redis 的安装与配置
  7. 解决Past duration X.XXXX too large警告
  8. JAVA实现短信接口的调用
  9. 如何爬取微博全部粉丝python_python 登录新浪微博爬取粉丝信息
  10. N的阶乘:输入一个正整数N,输出N的阶乘