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

Android自定义控件通用验证码输入框的实现,第1张

概述需求4位验证码输入框:效果图:1.输入框一行可输入4位数字类型的验证码;2.4位数字之间有间隔(包括底线);

需求

4位验证码输入框:

效果图:


1. 输入框一行可输入4位数字类型的验证码;
2. 4位数字之间有间隔(包括底线);
3. 输入框不允许有光标;
4. 底线根据输入位置显示高亮(蓝色);
6. 输入完成,回调结果,输入过程中,也进行回调;

分析

这种效果,很难直接在Edittext上处理:
-- 输入框均分4等份,还要有间隔;
-- 更难处理的是Edittext输入框禁止光标,那么,没有光标,我们如何调起虚拟键盘输入数据?
-- 等...

与其在一个控件上折腾,这么难受,不如自定义一个控件,实现这种效果。
自定义控件最简单的方案:使用多个控件,组合出这种效果。

1、布局如何实现?

1.禁止光标,我们直接使用TextVIEw就解决了,而非Edittext;
2.一行显示4位数字,比较简单,可以使用线性布局的权重,对TextVIEw进行控制为4等分;
3.每个TextVIEw下面跟着一个底线,将来我们就能对底线设置高亮颜色了;
这样,基本的布局展示就可以了!!!

2、使用了TextVIEw,那么我们如何接收用户的输入呢?
也很简单,我们在4个TextVIEw的上方平铺一个EditText,设置透明,
当用户点击到该控件时,会自动调起软键盘,接收输入的文本。
EditText接收到用户输入的文本,如何显示在TextVIEw呢?

3、我们监听EditText文本输入事件,最多仅接收4个输入字符,
每接收到一个字符,我们就赋值给对应的TextVIEw;
底线也随要设置的文本切换显示高亮;

4、如何删除已输入的数值?
我们监听EditText按键事件,拦截DEL键,从后向前挨着删除字符即可;
底线也随要删除的文本切换显示高亮;

5、是否需要自定义属性
分析我们自己的项目,虽然是公用的控件,但是该控件比较简单,没有特别的要求,所以没必要自定义属性了!
如果大家有需要的,可根据需要自己定义;
如何定义属性?请自行查找资料;

既然,问题都分析清楚了,那我们就开始快速实现吧

具体实现

布局文件 phone_code.xml

<?xml version="1.0" enCoding="utf-8"?><relativeLayout  xmlns:androID="http://schemas.androID.com/apk/res/androID"  androID:layout_wIDth="match_parent"  androID:layout_height="wrap_content">  <linearLayout    androID:ID="@+ID/ll_code"    androID:layout_wIDth="match_parent"    androID:layout_height="wrap_content"    androID:orIEntation="horizontal">    <linearLayout      androID:layout_wIDth="0dp"      androID:layout_height="wrap_content"      androID:layout_weight="1"      androID:orIEntation="vertical"      androID:layout_marginRight="7dp">      <TextVIEw        androID:ID="@+ID/tv_code1"        androID:layout_wIDth="match_parent"        androID:layout_height="wrap_content"        androID:textcolor="#2D2D2D"        androID:textSize="40sp"        androID:background="@null"        androID:gravity="center"/>      <VIEw        androID:ID="@+ID/v1"        androID:layout_wIDth="match_parent"        androID:layout_height="1dp"        androID:background="#3F8EED" />    </linearLayout>    <linearLayout      androID:layout_wIDth="0dp"      androID:layout_height="wrap_content"      androID:layout_weight="1"      androID:orIEntation="vertical"      androID:layout_marginRight="7dp"      androID:layout_marginleft="7dp">      <TextVIEw        androID:ID="@+ID/tv_code2"        androID:layout_wIDth="match_parent"        androID:layout_height="wrap_content"        androID:textcolor="#2D2D2D"        androID:textSize="40sp"        androID:background="@null"        androID:gravity="center"/>      <VIEw        androID:ID="@+ID/v2"        androID:layout_wIDth="match_parent"        androID:layout_height="1dp"        androID:background="#999999" />    </linearLayout>    <linearLayout      androID:layout_wIDth="0dp"      androID:layout_height="wrap_content"      androID:layout_weight="1"      androID:orIEntation="vertical"      androID:layout_marginRight="7dp"      androID:layout_marginleft="7dp">      <TextVIEw        androID:ID="@+ID/tv_code3"        androID:layout_wIDth="match_parent"        androID:layout_height="wrap_content"        androID:textcolor="#2D2D2D"        androID:textSize="40sp"        androID:background="@null"        androID:gravity="center"/>      <VIEw        androID:ID="@+ID/v3"        androID:layout_wIDth="match_parent"        androID:layout_height="1dp"        androID:background="#999999" />    </linearLayout>    <linearLayout      androID:layout_wIDth="0dp"      androID:layout_height="wrap_content"      androID:layout_weight="1"      androID:orIEntation="vertical"      androID:layout_marginleft="7dp">      <TextVIEw        androID:ID="@+ID/tv_code4"        androID:layout_wIDth="match_parent"        androID:layout_height="wrap_content"        androID:textcolor="#2D2D2D"        androID:background="@null"        androID:textSize="40sp"        androID:gravity="center"/>      <VIEw        androID:ID="@+ID/v4"        androID:layout_wIDth="match_parent"        androID:layout_height="1dp"        androID:background="#999999" />    </linearLayout>  </linearLayout>  <EditText    androID:ID="@+ID/et_code"    androID:layout_wIDth="match_parent"    androID:layout_height="wrap_content"    androID:layout_aligntop="@+ID/ll_code"    androID:layout_alignBottom="@+ID/ll_code"    androID:background="@androID:color/transparent"    androID:textcolor="@androID:color/transparent"    androID:cursorVisible="false"    androID:inputType="number"/></relativeLayout>

et_code 输入框,设置了透明和无光标,仅接收数字;
tv_code1~4 为显示数字的控件;
v1~4 为数字文本的底线,用于设置高亮;

自定义控件代码 PhoneCode

package iwangzhe.customvIEw2.phonecode;import androID.content.Context;import androID.graphics.color;import androID.text.Editable;import androID.text.TextWatcher;import androID.util.AttributeSet;import androID.vIEw.KeyEvent;import androID.vIEw.LayoutInflater;import androID.vIEw.VIEw;import androID.vIEw.inputmethod.inputMethodManager;import androID.Widget.EditText;import androID.Widget.relativeLayout;import androID.Widget.TextVIEw;import java.util.ArrayList;import java.util.List;import iwangzhe.customvIEw2.R;/** * 类:PhoneCode * 作者: qxc * 日期:2018/3/14. */public class PhoneCode extends relativeLayout {  private Context context;  private TextVIEw tv_code1;  private TextVIEw tv_code2;  private TextVIEw tv_code3;  private TextVIEw tv_code4;  private VIEw v1;  private VIEw v2;  private VIEw v3;  private VIEw v4;  private EditText et_code;  private List<String> codes = new ArrayList<>();  private inputMethodManager imm;  public PhoneCode(Context context) {    super(context);    this.context = context;    loadVIEw();  }  public PhoneCode(Context context,AttributeSet attrs) {    super(context,attrs);    this.context = context;    loadVIEw();  }  private voID loadVIEw(){    imm = (inputMethodManager) context.getSystemService(Context.input_METHOD_SERVICE);    VIEw vIEw = LayoutInflater.from(context).inflate(R.layout.phone_code,this);    initVIEw(vIEw);    initEvent();  }  private voID initVIEw(VIEw vIEw){    tv_code1 = (TextVIEw) vIEw.findVIEwByID(R.ID.tv_code1);    tv_code2 = (TextVIEw) vIEw.findVIEwByID(R.ID.tv_code2);    tv_code3 = (TextVIEw) vIEw.findVIEwByID(R.ID.tv_code3);    tv_code4 = (TextVIEw) vIEw.findVIEwByID(R.ID.tv_code4);    et_code = (EditText) vIEw.findVIEwByID(R.ID.et_code);    v1 = vIEw.findVIEwByID(R.ID.v1);    v2 = vIEw.findVIEwByID(R.ID.v2);    v3 = vIEw.findVIEwByID(R.ID.v3);    v4 = vIEw.findVIEwByID(R.ID.v4);  }  private voID initEvent(){    //验证码输入    et_code.addTextChangedListener(new TextWatcher() {      @OverrIDe      public voID beforeTextChanged(CharSequence charSequence,int i,int i1,int i2) {      }      @OverrIDe      public voID onTextChanged(CharSequence charSequence,int i2) {      }      @OverrIDe      public voID afterTextChanged(Editable editable) {        if(editable != null && editable.length()>0) {          et_code.setText("");          if(codes.size() < 4){            codes.add(editable.toString());            showCode();          }        }      }    });    // 监听验证码删除按键    et_code.setonKeyListener(new VIEw.OnKeyListener() {      @OverrIDe      public boolean onKey(VIEw vIEw,int keyCode,KeyEvent keyEvent) {        if (keyCode == KeyEvent.KEYCODE_DEL && keyEvent.getAction() == KeyEvent.ACTION_DOWN && codes.size()>0) {          codes.remove(codes.size()-1);          showCode();          return true;        }        return false;      }    });  }  /**   * 显示输入的验证码   */  private voID showCode(){    String code1 = "";    String code2 = "";    String code3 = "";    String code4 = "";    if(codes.size()>=1){      code1 = codes.get(0);    }    if(codes.size()>=2){      code2 = codes.get(1);    }    if(codes.size()>=3){      code3 = codes.get(2);    }    if(codes.size()>=4){      code4 = codes.get(3);    }    tv_code1.setText(code1);    tv_code2.setText(code2);    tv_code3.setText(code3);    tv_code4.setText(code4);            setcolor();//设置高亮颜色    callBack();//回调  }  /**   * 设置高亮颜色   */  private voID setcolor(){    int color_default = color.parsecolor("#999999");    int color_focus = color.parsecolor("#3F8EED");    v1.setBackgroundcolor(color_default);    v2.setBackgroundcolor(color_default);    v3.setBackgroundcolor(color_default);    v4.setBackgroundcolor(color_default);    if(codes.size()==0){      v1.setBackgroundcolor(color_focus);    }    if(codes.size()==1){      v2.setBackgroundcolor(color_focus);    }    if(codes.size()==2){      v3.setBackgroundcolor(color_focus);    }    if(codes.size()>=3){      v4.setBackgroundcolor(color_focus);    }  }  /**   * 回调   */  private voID callBack(){    if(oninputListener==null){      return;    }    if(codes.size()==4){      oninputListener.onSucess(getPhoneCode());    }else{      oninputListener.oninput();    }  }  //定义回调  public interface OninputListener{    voID onSucess(String code);    voID oninput();  }  private OninputListener oninputListener;  public voID setoninputListener(OninputListener oninputListener){    this.oninputListener = oninputListener;  }  /**   * 显示键盘   */  public voID showSoftinput(){    //显示软键盘    if(imm!=null && et_code!=null) {      et_code.postDelayed(new Runnable() {        @OverrIDe        public voID run() {          imm.showSoftinput(et_code,0);        }      },200);    }  }  /**   * 获得手机号验证码   * @return 验证码   */  public String getPhoneCode(){    StringBuilder sb = new StringBuilder();    for (String code : codes) {      sb.append(code);    }    return sb.toString();  }}

codes 集合,用于存放用户输入的所有数字。使用该集合,可简化输入框、文本关联逻辑和事件之间处理;
showSoftinput方法:显示输入键盘,可被外界调用;
getPhoneCode方法:获得用户输入的验证码,可被外界调用;
OninputListener接口:定义的数值输入回调,用于告诉调用者是输入中,还是输入完成;

调用者 MainActivity

布局文件

<?xml version="1.0" enCoding="utf-8"?><relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"  xmlns:tools="http://schemas.androID.com/tools"  androID:ID="@+ID/activity_main"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  tools:context="iwangzhe.customvIEw2.MainActivity">  <iwangzhe.customvIEw2.phonecode.PhoneCode    androID:layout_wIDth="match_parent"    androID:layout_height="wrap_content"    androID:ID="@+ID/pc_1"    androID:layout_below="@+ID/fpc_1"    androID:layout_margintop="40dp"    androID:layout_marginleft="20dp"    androID:layout_marginRight="20dp"/></relativeLayout>

代码

package iwangzhe.customvIEw2;import androID.support.v7.app.AppCompatActivity;import androID.os.Bundle;import iwangzhe.customvIEw2.phonecode.PhoneCode;public class MainActivity extends AppCompatActivity {  PhoneCode pc_1;  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentVIEw(R.layout.activity_main);    pc_1 = (PhoneCode) findVIEwByID(R.ID.pc_1);    //注册事件回调(可写,可不写)    pc_1.setoninputListener(new PhoneCode.OninputListener() {      @OverrIDe      public voID onSucess(String code) {        //Todo:      }      @OverrIDe      public voID oninput() {        //Todo:      }    });  }  private voID test(){    //获得验证码    String phoneCode = pc_1.getPhoneCode();  }}

总结:

此控件实现起来,很简单,代码量也非常少。

本文章,主要是为了让大家了解自定义控件的过程,如果想在自己的项目中使用,请根据需要自行调整优化。

Demo下载地址:CustomView2_jb51.rar
(为了减小Demo大小,我删除了build下的文件,大家获取后rebuild一下代码,就可以了)

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

您可能感兴趣的文章:Android仿滴滴出行验证码输入框功能实例代码Android实现常见的验证码输入框实例代码 总结

以上是内存溢出为你收集整理的Android自定义控件通用验证码输入框的实现全部内容,希望文章能够帮你解决Android自定义控件通用验证码输入框的实现所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1149690.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存