Android自定义控件实现通用验证码输入框

本文为大家分享了Android实现通用验证码输入框的具体代码,供大家参考,具体内容如下

效果图

话不多说先上效果图,可以先先看看是不是自己想要的

闲聊

闲来无事优化项目时,发现原来的验证码输入框,可扩展性不高,就拿来优化了一下,说说我开始的的思路吧,最开始是想用自定义View实现的,但是发现各种画矩,太烦人了,最后采用的组合控件的形式,Android有现成的控件,用来组合组合就能用,为什么不用呢。

源码

xml ITEM 布局文件(view_auth_code_input_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">

 <TextView
  android:id="@+id/number_tv"
  style="@style/TextStyleMain"
  android:layout_width="match_parent"
  android:layout_height="0mm"
  android:layout_weight="1"
  android:maxLength="1"
  android:text="0"
  android:textSize="72mm" />

 <View
  android:id="@+id/split_v"
  android:layout_width="match_parent"
  android:layout_height="1mm"
  android:background="@color/colorMain" />

</LinearLayout>

attrs 自定义属性(attrs.xml)

<?xml version="1.0" encoding="utf-8"?>
<resources>

 <!-- 自定义验证码输入框 属性 -->
 <declare-styleable name="AuthCodeInputView">
  <!-- 当前输入位分割线颜色 -->
  <attr name="currentSplitLineColor"
   format="reference|color" />
  <!-- 其他输入位分割线颜色 -->
  <attr name="otherSplitLineColor"
   format="reference|color" />
  <!-- 分割线高度 -->
  <attr name="splitLineHeight"
   format="dimension" />
  <!-- 验证码位数 -->
  <attr name="digit"
   format="integer" />
  <!-- 单个验证码宽度 -->
  <attr name="singleCaptchaWidth"
   format="dimension" />
  <!-- 验证码当前输入位字体颜色 -->
  <attr name="currentTextColor"
   format="reference|color" />
  <!-- 验证码当前输入位字体大小 -->
  <attr name="currentTextSize"
   format="dimension" />
  <!-- 验证码其他输入位字体颜色 -->
  <attr name="otherTextColor"
   format="reference|color" />
  <!-- 验证码其它输入位字体大小 -->
  <attr name="otherTextSize"
   format="dimension" />
  <!-- 默认颜色 -->
  <attr name="defaultColor"
   format="reference|color" />
  <!-- 默认字体大小 -->
  <attr name="defaultTextSize"
   format="dimension" />
  <!-- 默认间距 -->
  <attr name="defaultSpacing"
   format="dimension" />
 </declare-styleable>

</resources>

组合控件(AuthCodeInputView.java)

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.ColorInt;
import androidx.annotation.RequiresApi;

/**
 * <pre>
 *  <b>author</b> :BraveTou
 *  <b>blog</b>  :https://blog.csdn.net/bravetou
 *  <b>time</b>  :2020/9/4 16:43
 *  <b>desc</b>  :<pre>
 *   自定义验证码输入框
 *  </pre>
 * </pre>
 */
public class AuthCodeInputView extends LinearLayout {
 // <!-- 默认间距 -->
 private int mDefaultSpacing = 16;
 // <!-- 默认颜色 -->
 @ColorInt
 private int mDefaultColor = Color.BLACK;
 // <!-- 默认字体大小 -->
 private int mDefaultTextSize = 36;
 // <!-- 当前输入位分割线颜色 -->
 @ColorInt
 private int mCurrentSplitLineColor = mDefaultColor;
 // <!-- 其他输入位分割线颜色 -->
 @ColorInt
 private int mOtherSplitLineColor = mDefaultColor;
 // <!-- 分割线高度 -->
 private int mSplitLineHeight = 1;
 // <!-- 验证码位数 -->
 private int mDigit = 4;
 // <!-- 单个验证码宽度 -->
 private int mSingleCaptchaWidth = 100;
 // <!-- 验证码当前输入位字体颜色 -->
 @ColorInt
 private int mCurrentTextColor = mDefaultColor;
 // <!-- 验证码当前输入位字体大小 -->
 private int mCurrentTextSize = mDefaultTextSize;
 // <!-- 验证码其他输入位字体颜色 -->
 @ColorInt
 private int mOtherTextColor = mDefaultColor;
 // <!-- 验证码其它输入位字体大小 -->
 private int mOtherTextSize = mDefaultTextSize;

 // 记录当前输入文本
 private String mText = "";

 public AuthCodeInputView(Context context) {
  super(context);
  init(context, null);
 }

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

 public AuthCodeInputView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init(context, attrs);
 }

 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 public AuthCodeInputView(Context context, AttributeSet attrs, int defStyleAttr,
        int defStyleRes) {
  super(context, attrs, defStyleAttr, defStyleRes);
  init(context, attrs);
 }

 // 初始化
 private void init(Context context, AttributeSet attrs) {
  setOrientation(LinearLayout.HORIZONTAL);
  setGravity(Gravity.CENTER);
  if (getChildCount() > 0) {
   removeAllViews();
  }
  initAttrs(context, attrs);
  if (mDigit <= 0) {
   return;
  }
  for (int i = 0; i < mDigit; i++) {
   // 实例化 ITEM 组件
   View child = LayoutInflater.from(context).inflate(
     R.layout.view_auth_code_input_item, this, false);
   LayoutParams lp = new LayoutParams(mSingleCaptchaWidth,
     ViewGroup.LayoutParams.MATCH_PARENT);
   if (i != 0) {
    lp.leftMargin = mDefaultSpacing;
   }
   child.setLayoutParams(lp);
   setViewAttrs(child, null, false);
   // 分割线高度只在初始化时设置一次
   View mSplitV = child.findViewById(R.id.split_v);
   LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
     ViewGroup.LayoutParams.MATCH_PARENT, mSplitLineHeight);
   mSplitV.setLayoutParams(params);
   addView(child);
  }
 }

 // 设置(未)选中属性
 private void setViewAttrs(View child, String text, boolean isSelected) {
  TextView mNumberTv = child.findViewById(R.id.number_tv);
  View mSplitV = child.findViewById(R.id.split_v);
  if (isSelected) {
   mNumberTv.setTextColor(mCurrentTextColor);
   mNumberTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCurrentTextSize);
   mSplitV.setBackgroundColor(mCurrentSplitLineColor);
  } else {
   mNumberTv.setTextColor(mOtherTextColor);
   mNumberTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, mOtherTextSize);
   mSplitV.setBackgroundColor(mOtherSplitLineColor);
  }
  mNumberTv.setText(TextUtils.isEmpty(text) ? "" : text);
 }

 // 初始化属性
 private void initAttrs(Context context, AttributeSet attrs) {
  if (null != attrs) {
   // AttributeSet 属性值的索引
   TypedArray o = context.obtainStyledAttributes(attrs, R.styleable.AuthCodeInputView);
   // 默认间距
   mDefaultSpacing = (int) o.getDimension(R.styleable.AuthCodeInputView_defaultSpacing,
     16f);
   // 获取默认颜色
   mDefaultColor = o.getColor(R.styleable.AuthCodeInputView_defaultColor, Color.BLACK);
   // 获取默认字体大小
   mDefaultTextSize = (int) o.getDimension(R.styleable.AuthCodeInputView_defaultTextSize
     , 36f);
   // 输入位分割线颜色
   mCurrentSplitLineColor =
     o.getColor(R.styleable.AuthCodeInputView_currentSplitLineColor, mDefaultColor);
   // 其他输入位分割线颜色
   mOtherSplitLineColor = o.getColor(R.styleable.AuthCodeInputView_otherSplitLineColor,
     mDefaultColor);
   // 分割线高度
   mSplitLineHeight = (int) o.getDimension(R.styleable.AuthCodeInputView_splitLineHeight
     , 1f);
   mSplitLineHeight = mSplitLineHeight <= 1 ? 1 : mSplitLineHeight;
   // 验证码位数
   mDigit = o.getInteger(R.styleable.AuthCodeInputView_digit, 4);
   // 单个验证码宽度
   mSingleCaptchaWidth =
     (int) o.getDimension(R.styleable.AuthCodeInputView_singleCaptchaWidth, 100f);
   // 验证码当前输入位字体颜色
   mCurrentTextColor = o.getColor(R.styleable.AuthCodeInputView_currentTextColor,
     mDefaultColor);
   // 验证码当前输入位字体大小
   mCurrentTextSize = (int) o.getDimension(R.styleable.AuthCodeInputView_currentTextSize
     , mDefaultTextSize);
   // 验证码其他输入位字体颜色
   mOtherTextColor = o.getColor(R.styleable.AuthCodeInputView_otherTextColor,
     mDefaultColor);
   // 验证码其它输入位字体大小
   mOtherTextSize = (int) o.getDimension(R.styleable.AuthCodeInputView_otherTextSize,
     mDefaultTextSize);
   // 回收资源
   o.recycle();
  }
 }

 // 追加文本
 public void addText(String text) {
  text = TextUtils.isEmpty(text) ? "" : text;
  setText(mText + text);
 }

 // 删除文本
 public void delText() {
  int count = TextUtils.isEmpty(mText) ? 0 : mText.length();
  if (count > 0) {
   setText(mText.substring(0, count - 1));
  } else {
   setText("");
  }
 }

 // 设置文本
 public void setText(String text) {
  text = text.trim();
  int length = TextUtils.isEmpty(text) ? 0 : text.length();
  if (length > mDigit) {
   this.mText = text.substring(0, mDigit);
   length = mDigit;
  } else {
   this.mText = length > 0 ? text : "";
  }
  int count = getChildCount();
  for (int i = 0; i < count; i++) {
   View child = getChildAt(i);
   if (i + 1 < length) {
    setViewAttrs(child, String.valueOf(text.charAt(i)), false);
   } else if (i + 1 == length) {
    setViewAttrs(child, String.valueOf(text.charAt(i)), true);
   } else {
    setViewAttrs(child, null, false);
   }
  }
 }

 // 获取文本
 public String getText() {
  return mText;
 }
}

至于效果图下面那个安全键盘源码就太多了,我就不多了的,我这边是组合控件实现的,超简单。

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

(0)

相关推荐

  • Android仿滴滴出行验证码输入框功能实例代码

    最近公司项目中有一个类似滴滴出行填写验证码的弹框,下面是我撸出来的效果: 中间的那个输入密码的6个框框其实就是用shape画的背景,通过监听EditText获取焦点来改变背景,废话少说,直接上代码吧. 2.效果实现 代码内容比较简单,所以大家可以直接看代码 VerificationCodeInput.java /** * @author hydCoder * @date 2017/9/22 14:39 * @desc 输入验证码的自定义view * @email hyd_coder@163.co

  • Android View教程之自定义验证码输入框效果

    前言 首先,我们来看看实现的是怎么样的效果: 如果我们拿到这样的UI,想到的布局应该是用4个EditText包在横向的LinearLayout里面,但今天要讲的View,所以我们决定用一个自定义的EditText 画出来. 学到什么? 基本理解画布概念 画布的状态.平移 布局测量 画图片 功能需求 高亮当前输入框 输入满4个数字自动调用方法 思路 完全重画一个EditText,就包含了测量布局和重新绘制这两个关键步骤.好了,到这里理一下整体的思路: 根据验证码个数以及边框大小来计算输入框显示的宽

  • Android实现常见的验证码输入框实例代码

    前言 验证码输入框是很多APP必不可少的组件,之前在重构注册登录页面的时候,重新设计了UI,所以不能再简单的用EditText来做了,所以这篇文章将分享一下如何实现一个常见的验证码输入框.下面话不多说了,来一起看看详细的介绍吧. 正文 先搂一眼效果吧 不要把注意力都放在头顶的那一抹绿上,重点在输入框,可能大多数APP里都是采用6个方框的UI效果,我这里是按照我们设计的要求,用6根横线来划出6个数字的位置.一开始我想的是直接用6个TextView,然后传递焦点的做法,但是发现实现起来有一定的难度.

  • Android 自定义验证码输入框的实例代码(支持粘贴连续性)

    需求 1.能自定义输入框个数和样式 2.支持长按粘贴或剪切板内容自动填充(粘贴连续性) 其中第2点是最为重要的,正是其他人没有这点,逼得自己弄一个 示例 别人的示例: 粘贴居然不支持连续性,只能粘贴第一个字符,所以用的有点难受 自己的示例: 原理 大致是Edittext + n* TextView,然后设置edittext字体跟背景颜色都为透明,隐藏光标 Edittext:监听edittext每次输入一个字符就赋值到对应的TextView上,然后在清空自己 下划线:在TextView下面添加Vi

  • Android自定义控件通用验证码输入框的实现

    需求 4位验证码输入框: 效果图: 1. 输入框一行可输入4位数字类型的验证码: 2. 4位数字之间有间隔(包括底线): 3. 输入框不允许有光标: 4. 底线根据输入位置显示高亮(蓝色): 6. 输入完成,回调结果,输入过程中,也进行回调: 分析 这种效果,很难直接在Edittext上处理: -- 输入框均分4等份,还要有间隔: -- 更难处理的是Edittext输入框禁止光标,那么,没有光标,我们如何调起虚拟键盘输入数据? -- 等... 与其在一个控件上折腾,这么难受,不如自定义一个控件,

  • Android实现自定义验证码输入框效果(实例代码)

    这里提一下,这个当时也是在网上看到一个博主写的代码改了下用在我么项目中的验证码输入框.博主的地址不记得了这里只能顺带标注一下... 效果图如下: 就是这个酱紫 直入主题,代码如下: xml布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" androi

  • Android自定义View验证码输入框

    本文实例为大家分享了Android自定义View验证码输入框的具体代码,供大家参考,具体内容如下 验证码输入框 1.先看下样式 2.直接上代码 public class MyVcode extends AppCompatEditText { private int mFigures = 0;// 验证码个数 private int mCodeMargin = 0;// 验证码之间的间距 private int mSelectColor = 0;// 选中框的颜色 private int mNor

  • Android自定义控件实现通用验证码输入框(二)

    本文实例为大家分享了Android实现通用验证码输入框第2篇具体实现代码,供大家参考,具体内容如下 效果图 话不多说,我们还是先上效果图,可以先先看看是不是自己想要的 闲聊 这种验证码输入框使用组合控件就比较烦人了,所以这边直接使用自定View步奏实现 源码 自定义输入框属性(attrs.xml) <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable

  • Android自定义控件实现通用验证码输入框

    本文为大家分享了Android实现通用验证码输入框的具体代码,供大家参考,具体内容如下 效果图 话不多说先上效果图,可以先先看看是不是自己想要的 闲聊 闲来无事优化项目时,发现原来的验证码输入框,可扩展性不高,就拿来优化了一下,说说我开始的的思路吧,最开始是想用自定义View实现的,但是发现各种画矩,太烦人了,最后采用的组合控件的形式,Android有现成的控件,用来组合组合就能用,为什么不用呢. 源码 xml ITEM 布局文件(view_auth_code_input_item.xml) <

  • Android实现短信验证码输入框

    本文实例为大家分享了Android实现短信验证码输入框的具体代码,供大家参考,具体内容如下 其实用官方自定的那个inputEditText默认带下划线的,然后自己再实行焦点和输入框弹出等操作也可以. 写这个自定义View主要是为了练习. /** * 实现了粘贴事件监听回调的 EditText */ open class ListenPasteEditTextTest : AppCompatEditText { constructor(context: Context): super(contex

  • Android自定义控件实现验证码倒计时

    今天给大家带来一个新的控件--验证码倒计时,先看下效果图 1 效果演示 2 使用方式 <com.landptf.view.CountDownM android:id="@+id/cdm_identifying_code" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_alignParentRight="true&quo

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

    在上一篇的文章中介绍了自定义控件的属性,详情见<详解Android自定义控件属性TypedArray以及attrs>.那么在这基础上实现随机验证码生成,里面的代码是自定义控件以及涉及到自定义view绘画. 1.先看实现的效果图 看到这个效果图是不是感觉还可以.那么就看看源码吧. 2.attr文件 <?xml version="1.0" encoding="utf-8"?> <resources> <attr name=&qu

随机推荐