欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-03-20 22:45:22
本文实例为大家分享了android实现通用验证码输入框第2篇具体实现代码,供大家参考,具体内容如下效果图话不多说,我们还是先上效果图,可以先先看看是不是自己想要的闲聊这种验证码输入框使用组合控件就比较...

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

效果图

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

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

闲聊

这种验证码输入框使用组合控件就比较烦人了,所以这边直接使用自定view步奏实现

源码

自定义输入框属性(attrs.xml)

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

  <declare-styleable name="codeinputview">
    <!-- 边框宽度 -->
    <attr name="borderwidth"
      format="dimension" />
    <!-- 边框高度 -->
    <attr name="borderheight"
      format="dimension" />
    <!-- 边框间距 -->
    <attr name="borderspacing"
      format="dimension" />
    <!-- 边框背景图 -->
    <attr name="borderimage"
      format="reference" />
    <!-- 最大输入长度 -->
    <attr name="android:maxlength" />
  </declare-styleable>

</resources>

资源文件(code_input_view_border_bg.xml)

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

  <item android:state_focused="true">
    <shape android:shape="rectangle">
      <corners android:radius="5mm" />
      <stroke android:width="2mm"
        android:color="@color/colormain" />
    </shape>
  </item>

  <item android:state_enabled="true">
    <shape android:shape="rectangle">
      <corners android:radius="5mm" />
      <stroke android:width="2mm"
        android:color="@color/colortextlight" />
    </shape>
  </item>

</selector>

自定义控件(codeinputview.java)

import android.annotation.suppresslint;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.rect;
import android.graphics.drawable.drawable;
import android.os.build;
import android.text.inputfilter;
import android.text.textpaint;
import android.util.attributeset;
import android.widget.edittext;

import androidx.annotation.requiresapi;
import androidx.core.content.contextcompat;

/**
 * <pre>
 *   <b>author</b>  :bravetou
 *   <b>blog</b>   :https://blog.csdn.net/bravetou
 *   <b>time</b>   :2020/9/8 11:49
 *   <b>desc</b>   :<pre>
 *     自定义验证码输入框
 *   </pre>
 * </pre>
 */
@suppresslint("appcompatcustomview")
public class codeinputview extends edittext {
  // <!-- 最大输入长度 -->
  private int mmaxlength = 4;
  // <!-- 边框宽度 -->
  private int mborderwidth = 100;
  // <!-- 边框高度 -->
  private int mborderheight = 100;
  // <!-- 边框间距 -->
  private int mborderspacing = 24;
  // <!-- 边框背景图 -->
  private drawable mborderimage;

  // 用矩形来保存方框的位置、大小信息
  private final rect mrect = new rect();

  // 文本颜色
  private int mtextcolor;

  public codeinputview(context context) {
    super(context);
    init(context, null);
  }

  public codeinputview(context context, attributeset attrs) {
    super(context, attrs);
    init(context, attrs);
  }

  public codeinputview(context context, attributeset attrs, int defstyleattr) {
    super(context, attrs, defstyleattr);
    init(context, attrs);
  }

  @requiresapi(api = build.version_codes.lollipop)
  public codeinputview(context context, attributeset attrs, int defstyleattr, int defstyleres) {
    super(context, attrs, defstyleattr, defstyleres);
    init(context, attrs);
  }

  // 初始化
  private void init(context context, attributeset attrs) {
    if (null == mborderimage) {
      mborderimage = contextcompat.getdrawable(context,
          r.drawable.code_input_view_border_bg);
    }
    initattrs(context, attrs);
    // 设置最大输入长度
    setmaxlength(mmaxlength);
    // 禁止长按
    setlongclickable(false);
    // 去掉背景颜色
    setbackgroundcolor(color.transparent);
    // 不显示光标
    setcursorvisible(false);
  }

  // 设置最大长度
  private void setmaxlength(int maxlength) {
    if (maxlength >= 0) {
      setfilters(new inputfilter[]{new inputfilter.lengthfilter(maxlength)});
    } else {
      setfilters(new inputfilter[0]);
    }
  }

  // 初始化属性
  private void initattrs(context context, attributeset attrs) {
    if (null != attrs) {
      // attributeset 属性值的索引
      typedarray o = context.obtainstyledattributes(attrs, r.styleable.codeinputview);
      // <!-- 最大输入长度 -->
      mmaxlength = o.getinteger(r.styleable.codeinputview_android_maxlength, 4);
      // <!-- 边框宽度 -->
      mborderwidth = (int) o.getdimension(r.styleable.codeinputview_borderwidth, 100f);
      // <!-- 边框高度 -->
      mborderheight = (int) o.getdimension(r.styleable.codeinputview_borderheight, 100f);
      // <!-- 边框间距 -->
      mborderspacing = (int) o.getdimension(r.styleable.codeinputview_borderspacing, 24);
      // <!-- 边框背景图 -->
      drawable drawable = o.getdrawable(r.styleable.codeinputview_borderimage);
      if (null != drawable) {
        mborderimage = drawable;
      }
      // 回收资源
      o.recycle();
    }
  }

  @override
  protected 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);

    // 判断高度是否小于自定义边框高度
    height = height < mborderheight ? mborderheight : height;

    // 自定义输入框宽度 = 边框宽度 * 数量 + 边框间距 * (数量 - 1)
    int customwidth = mborderwidth * mmaxlength
        + mborderspacing * ((mmaxlength - 1) > 0 ? (mmaxlength - 1) : 0);

    // 判断宽度是否小于自定义宽度
    width = width < customwidth ? customwidth : width;

    widthmeasurespec = measurespec.makemeasurespec(width, widthmode);
    heightmeasurespec = measurespec.makemeasurespec(height, heightmode);

    // 重新设置测量布局
    setmeasureddimension(widthmeasurespec, heightmeasurespec);
  }

  @override
  protected void ondraw(canvas canvas) {
    // 获取当前输入文本颜色
    mtextcolor = getcurrenttextcolor();
    // 屏蔽系统文本颜色,直接透明
    settextcolor(color.transparent);
    // 父类绘制
    super.ondraw(canvas);
    // 重新设置文本颜色
    settextcolor(mtextcolor);
    // 重绘背景
    drawborderbackground(canvas);
    // 重绘文本
    drawtext(canvas);
  }

  // 绘制背景
  private void drawborderbackground(canvas canvas) {
    // 下面绘制方框背景颜色
    // 确定反馈位置
    mrect.left = 0;
    mrect.top = 0;
    mrect.right = mborderwidth;
    mrect.bottom = mborderheight;
    // 当前画布保存的状态
    int count = canvas.getsavecount();
    // 保存画布
    canvas.save();
    // 获取当前输入字符串长度
    int length = geteditabletext().length();
    for (int i = 0; i < mmaxlength; i++) {
      // 设置位置
      mborderimage.setbounds(mrect);
      // 设置图像状态
      if (i == length) {
        // 当前输入位高亮的索引
        mborderimage.setstate(new int[]{android.r.attr.state_focused});
      } else {
        // 其他输入位置默认
        mborderimage.setstate(new int[]{android.r.attr.state_enabled});
      }
      // 画到画布上
      mborderimage.draw(canvas);
      // 确定下一个方框的位置
      // x坐标位置
      float dx = mrect.right + mborderspacing;
      // 保存画布
      canvas.save();
      // [注意细节] 移动画布到下一个位置
      canvas.translate(dx, 0);
    }
    // [注意细节] 把画布还原到画反馈之前的状态,这样就还原到最初位置了
    canvas.restoretocount(count);
    // 画布归位
    canvas.translate(0, 0);
  }

  // 绘制文本
  private void drawtext(canvas canvas) {
    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 = mborderwidth / 2 + (mborderwidth + mborderspacing) * i - (mrect.centerx());
      int y = canvas.getheight() / 2 + mrect.height() / 2;
      canvas.drawtext(text, x, y, textpaint);
    }
    canvas.restoretocount(count);
  }
}

使用

<relativelayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <*.*.*.widget.codeinputview
      android:id="@+id/mcodeinputview"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerinparent="true"
      android:layout_margintop="56mm"
      android:maxlength="5"
      android:text="156"
      android:textsize="48mm"
      app:borderheight="88mm"
      app:borderspacing="24mm"
      app:borderwidth="88mm" />

</relativelayout>

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