关于Android自定义View实现验证码输入框

简介: 在做校验验证的时候,经常需要手机接收短信,获取验证码,输入验证码,实现起来其实也不难,今天对输入框简单做了一个封装,通过自定义View来实现。

在做校验验证的时候,经常需要手机接收短信,获取验证码,输入验证码,实现起来其实也不难,今天对输入框简单做了一个封装,通过自定义View来实现。

先看效果图:
image.png

采用组合自定义view来实现,引入布局文件,这种方式实现起来虽然简单,但是不够智能通用,需求变动的话就需要改代码,但是也不难改,代码很简单,下面是完整代码,请自行阅读。

public class VerificationCodeView extends RelativeLayout {
    private Context context;
    private OnCodeFinishListener onCodeFinishListener;
    private TextView tvCode1;
    private TextView tvCode2;
    private TextView tvCode3;
    private TextView tvCode4;
    private TextView tvCode5;
    private TextView tvCode6;
    private View v1;
    private View v2;
    private View v3;
    private View v4;
    private View v5;
    private View v6;
    private EditText etCode;
    private List<String> codes = new ArrayList<>();
    private InputMethodManager imm;
 
 
    public OnCodeFinishListener getOnCodeFinishListener() {
        return onCodeFinishListener;
    }
 
    public void setOnCodeFinishListener(OnCodeFinishListener onCodeFinishListener) {
        this.onCodeFinishListener = onCodeFinishListener;
    }
 
    public VerificationCodeView(Context context) {
        super(context);
        this.context = context;
        loadView();
    }
 
    public VerificationCodeView(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.verification_code, this);
        initView(view);
        initEvent();
    }
 
    ArrayList<View> views = new ArrayList<>();
    ArrayList<TextView> tvList = new ArrayList<>();
 
    private void initView(View view) {
        tvCode1 = view.findViewById(R.id.tv_code1);
        tvCode2 = view.findViewById(R.id.tv_code2);
        tvCode3 = view.findViewById(R.id.tv_code3);
        tvCode4 = view.findViewById(R.id.tv_code4);
        tvCode5 = view.findViewById(R.id.tv_code5);
        tvCode6 = view.findViewById(R.id.tv_code6);
        etCode = view.findViewById(R.id.et_code);
        etCode.requestFocus();
        etCode.setFocusable(true);
        v1 = view.findViewById(R.id.v1);
        v2 = view.findViewById(R.id.v2);
        v3 = view.findViewById(R.id.v3);
        v4 = view.findViewById(R.id.v4);
        v5 = view.findViewById(R.id.v5);
        v6 = view.findViewById(R.id.v6);
        views.add(v1);
        views.add(v2);
        views.add(v3);
        views.add(v4);
        views.add(v5);
        views.add(v6);
        tvList.add(tvCode1);
        tvList.add(tvCode2);
        tvList.add(tvCode3);
        tvList.add(tvCode4);
        tvList.add(tvCode5);
        tvList.add(tvCode6);
    }
 
    private void initEvent() {
        //验证码输入
        etCode.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }
 
            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }
 
            @Override
            public void afterTextChanged(Editable editable) {
                if (editable != null && editable.length() > 0) {
                    etCode.setText("");
                    if (codes.size() < 8) {
                        etCode.setCursorVisible(false);
                        codes.add(editable.toString());
                        showCode();
                    }
                    onCodeFinishListener.onTextChange(getPhoneCode());
                }
            }
        });
        // 监听验证码删除按键
        etCode.setOnKeyListener(new 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();
                    onCodeFinishListener.onTextDel();
                    return true;
                }
                return false;
            }
        });
    }
 
    /**
     * 显示输入的验证码
     */
    private void showCode() {
        String code1 = "";
        String code2 = "";
        String code3 = "";
        String code4 = "";
        String code5 = "";
        String code6 = "";
        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);
        }
        if (codes.size() >= 5) {
            code5 = codes.get(4);
        }
        if (codes.size() >= 6) {
            code6 = codes.get(5);
        }
 
        tvCode1.setText(code1);
        tvCode2.setText(code2);
        tvCode3.setText(code3);
        tvCode4.setText(code4);
        tvCode5.setText(code5);
        tvCode6.setText(code6);
    }
 
    /**
     * 设置下划线高亮颜色
     */
    private void setColor(int defaultColor, int focusColor) {
        int color_default = context.getResources().getColor(defaultColor);
        int color_focus = context.getResources().getColor(focusColor);
        for (View v : views) {
            //默认颜色
            v.setBackgroundColor(color_default);
        }
        int length = getPhoneCode().length();
        for (int i = 0; i < length; i++) {
            views.get(i).setBackgroundColor(color_focus);
        }
    }
 
    /**
     * 显示键盘
     */
    public void showSoftInput() {
        //显示软键盘
        if (imm != null && etCode != null) {
            etCode.postDelayed(new Runnable() {
                @Override
                public void run() {
                    imm.showSoftInput(etCode, 0);
                }
            }, 200);
        }
    }
 
    /**
     * 获得手机号验证码
     *
     * @return 验证码
     */
    public String getPhoneCode() {
        StringBuilder sb = new StringBuilder();
        for (String code : codes) {
            sb.append(code);
        }
        return sb.toString();
    }
 
    public void errorText(int color) {
        for (View v : views) {
            v.setBackgroundColor(color);
        }
    }
 
    public void textBgColor(int color) {
        for (View v : views) {
            v.setBackgroundColor(color);
        }
    }
 
    public interface OnCodeFinishListener {
        /**
         * 文本改变
         */
        void onTextChange(String content);
 
        void onTextDel();
    }
 
 
    public void setEditTextCursorDrawable(EditText editText) {
        //修改光标的颜色(反射)
        try {
            @SuppressLint("SoonBlockedPrivateApi") Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
            f.setAccessible(true);
//            f.set(editText, R.drawable.et_otp_cursor);
        } catch (Exception ignored) {
        }
    }
}

在看看布局文件

<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_marginLeft="20dp"
        android:layout_marginRight="20dp"
        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="10dp">
            <TextView
                android:id="@+id/tv_code1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/black"
                android:textSize="24dp"
                android:textStyle="bold"
                android:background="@null"
                android:gravity="center"/>
            <View
                android:id="@+id/v1"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#4c000000" />
        </LinearLayout>
 
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginRight="10dp"
            >
            <TextView
                android:id="@+id/tv_code2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/black"
                android:textSize="24dp"
                android:textStyle="bold"
                android:background="@null"
                android:gravity="center"/>
            <View
                android:id="@+id/v2"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#4c000000" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginRight="10dp"
            >
            <TextView
                android:id="@+id/tv_code3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/black"
                android:textSize="24dp"
                android:textStyle="bold"
                android:background="@null"
                android:gravity="center"/>
            <View
                android:id="@+id/v3"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#4c000000" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginRight="10dp">
            <TextView
                android:id="@+id/tv_code4"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/black"
                android:textSize="24dp"
                android:textStyle="bold"
                android:background="@null"
                android:gravity="center"/>
            <View
                android:id="@+id/v4"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#4c000000" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginRight="10dp">
            <TextView
                android:id="@+id/tv_code5"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:textColor="@color/black"
                android:textSize="24dp"
                android:textStyle="bold"
                android:gravity="center"/>
            <View
                android:id="@+id/v5"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#4c000000" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginRight="10dp"
            >
            <TextView
                android:id="@+id/tv_code6"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/black"
                android:textSize="24dp"
                android:textStyle="bold"
                android:background="@null"
                android:gravity="center"/>
            <View
                android:id="@+id/v6"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#4c000000" />
        </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:layout_marginLeft="20dp"
        android:inputType="number"/>
</RelativeLayout>
相关文章
|
20天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
22天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
30 5
|
29天前
|
缓存 数据处理 Android开发
在 Android 中使用 RxJava 更新 View
【10月更文挑战第20天】使用 RxJava 来更新 View 可以提供更优雅、更高效的解决方案。通过合理地运用操作符和订阅机制,我们能够轻松地处理异步数据并在主线程中进行 View 的更新。在实际应用中,需要根据具体情况进行灵活运用,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在 Android 中使用 RxJava 更新 View 的技巧和方法,为开发高质量的 Android 应用提供有力支持。
|
29天前
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
32 2
|
30天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
1月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
25 2
|
存储 缓存 Android开发
Android EditText输入框实现下拉且保存最近5个历史记录
Android EditText输入框实现下拉且保存最近5个历史记录
440 0
Android EditText输入框实现下拉且保存最近5个历史记录
|
6天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
12天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
13天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
下一篇
无影云桌面