EditText自定义验证码输入框

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Snow_Ice_Yang/article/details/81868328

效果图:

一 分析

    在安卓开发中,实现自定义控件的方式有三种,继承控件,组合控件,自绘控件。现在我们需要通过分析决定使用哪种方式。首先我们需要有输入事件,那么我们肯定是需要有EditText控件的。其次我们用需要显示验证码。我们需要显示文本的控件TextView。那么很明显了,我们需要使用组合控件的方式来实现我们的需求。

二 思路

 1.用一个透明的EditText与六个TextView重叠,并给TextView设置默认背景
 2.监听EditText文本变化,获取输入内容,给TextView赋值并改变TextView背景
 3. 六个TextView有值后添加输入完成回调,监听删除键添加删除回调

三 实现

(1)组合控件的布局实现

package com.sharetronic.tip;

import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.sharetronic.R;

/**
 * Created by Administrator on 2018/8/15.
 */

public class VerifyCodeView extends RelativeLayout {
    private EditText editText;
    private TextView[] textViews;
    private static int MAX = 6;
    private String inputContent;

    public VerifyCodeView(Context context) {
        this(context, null);
    }

    public VerifyCodeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VerifyCodeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        View.inflate(context, R.layout.view_verify_code, this);

        textViews = new TextView[MAX];
        textViews[0] = (TextView) findViewById(R.id.tv_0);
        textViews[1] = (TextView) findViewById(R.id.tv_1);
        textViews[2] = (TextView) findViewById(R.id.tv_2);
        textViews[3] = (TextView) findViewById(R.id.tv_3);
        textViews[4] = (TextView) findViewById(R.id.tv_4);
        textViews[5] = (TextView) findViewById(R.id.tv_5);
        editText = (EditText) findViewById(R.id.edit_text_view);

        editText.setCursorVisible(false);//隐藏光标
        setEditTextListener();
    }

    private void setEditTextListener() {
        editText.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) {
                inputContent = editText.getText().toString();

                if (inputCompleteListener != null) {
                    if (inputContent.length() >= MAX) {
                        inputCompleteListener.inputComplete();
                    } else {
                        inputCompleteListener.invalidContent();
                    }
                }

                for (int i = 0; i < MAX; i++) {
                    if (i < inputContent.length()) {
                        textViews[i].setText(String.valueOf(inputContent.charAt(i)));
                    } else {
                        textViews[i].setText("");
                    }
                }
            }
        });
    }


    private InputCompleteListener inputCompleteListener;

    public void setInputCompleteListener(InputCompleteListener inputCompleteListener) {
        this.inputCompleteListener = inputCompleteListener;
    }

    public interface InputCompleteListener {

        void inputComplete();

        void invalidContent();
    }

    public String getEditContent() {
        return inputContent;
    }
}

布局 view_verify_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:layout_width="match_parent"
        android:layout_height="48dp"
        android:gravity="center"
        android:orientation="horizontal">


        <TextView
            android:id="@+id/tv_0"
            style="@style/textview_style" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_1"
            style="@style/textview_style" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_2"
            style="@style/textview_style" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_3"
            style="@style/textview_style" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_4"
            style="@style/textview_style" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_5"
            style="@style/textview_style" />


    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:gravity="center"
        android:orientation="horizontal">


        <View
            android:layout_width="41dp"
            android:layout_height="1dp"
            android:layout_gravity="bottom"
            android:background="@color/silver" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:layout_width="41dp"
            android:layout_height="1dp"
            android:layout_gravity="bottom"
            android:background="@color/silver" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:layout_width="41dp"
            android:layout_height="1dp"
            android:layout_gravity="bottom"
            android:background="@color/silver" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:layout_width="41dp"
            android:layout_height="1dp"
            android:layout_gravity="bottom"
            android:background="@color/silver" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:layout_width="41dp"
            android:layout_height="1dp"
            android:layout_gravity="bottom"
            android:background="@color/silver" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <View
            android:layout_width="41dp"
            android:layout_height="1dp"
            android:layout_gravity="bottom"
            android:background="@color/silver" />


    </LinearLayout>

    <com.sharetronic.tip.MyEditText
        android:id="@+id/edit_text_view"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="@android:color/transparent"
        android:inputType="number"
        android:longClickable="false"
        android:maxLength="6"
        android:textColor="@android:color/transparent" />
</RelativeLayout>

注意:background 和 textColor 均设置为透明

MyEditText.java:

package com.sharetronic.tip;

import android.content.Context;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * Created by Administrator on 2018/8/15.
 */

public class MyEditText extends AppCompatEditText {

    private long lastTime = 0;

    public MyEditText(Context context) {
        super(context);
    }

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

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

    @Override
    protected void onSelectionChanged(int selStart, int selEnd) {
        super.onSelectionChanged(selStart, selEnd);
        this.setSelection(this.getText().length());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                long currentTime = System.currentTimeMillis();
                if (currentTime - lastTime < 500) {
                    lastTime = currentTime;
                    return true;
                } else {
                    lastTime = currentTime;
                }
                break;
        }
        return super.onTouchEvent(event);
    }
}

主布局 activity_input_verifycode.xml:

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:fitsSystemWindows="true"
    tools:context=".account.activity.InputVerifycodeActivity">

    <include
        android:id="@+id/include_sign_in"
        layout="@layout/sign_in_background_text" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/include_sign_in"
        android:layout_marginLeft="44dp"
        android:layout_marginRight="44dp"
        android:layout_marginTop="40dp"
        android:orientation="vertical"
        android:padding="5dp">

        <TextView
            android:id="@+id/tv_input_Verifycode_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/input_code"
            android:textColor="@color/black"
            android:textSize="32sp"/>

        <TextView
            android:id="@+id/tv_input_Verifycode_prompt"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="18dp"
            android:text="@string/input_code_1"
            android:textColor="@color/black"
            android:textSize="12sp" />

        <com.sharetronic.tip.VerifyCodeView
            android:id="@+id/verify_code_view"
            android:layout_width="match_parent"
            android:layout_height="82dp"
            android:layout_marginTop="22dp" />

        <TextView
            android:id="@+id/tv_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:textSize="10sp" />

        <Button
            android:id="@+id/btn_login_sign_in"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="56dp"
            android:background="@drawable/btn_login"
            android:text="@string/next"
            android:textColor="@color/white"
            android:textSize="20sp" />

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="16dp">

            <TextView
                android:id="@+id/tv_prompt1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:paddingRight="5dp"
                android:text="@string/sign_0"
                android:textColor="@color/silver"
                android:textSize="12sp" />
        </RelativeLayout>

    </LinearLayout>


</RelativeLayout>

主程序 InputVerifycodeActivity.java:

package com.sharetronic.account.activity;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.sharetronic.R;

import com.sharetronic.account.presenter.InputVerifycodePresenterImpl;
import com.sharetronic.account.presenter.VerifyAccountPresenterImpl;
import com.sharetronic.account.view.IInputVerifycodeView;
import com.sharetronic.base.context.BaseActivity;
import com.sharetronic.tip.VerifyCodeView;
import com.sharetronic.util.PatternMatchUtil;
import com.sharetronic.util.ToastUtil;

import static com.sharetronic.account.presenter.VerifyAccountPresenterImpl.FORGOT_SEND;
import static com.sharetronic.account.presenter.VerifyAccountPresenterImpl.REGIST_SEND;
import static com.sharetronic.account.presenter.VerifyAccountPresenterImpl.REGIST_SEND_CODE;

public class InputVerifycodeActivity extends BaseActivity implements IInputVerifycodeView,View.OnClickListener {

    private InputVerifycodePresenterImpl inputVcPre;
    private VerifyCodeView verifyCodeView;
    private String phone;
    private int VERIFY_TYPE;
    private TextView tvPrompt;
    private TextView tvPrompt1;
    private TextView tvTitle;
    private TextView tvTime;

    private ImageView ivCancle;
    private Button btnNext;



    public static void startActivity(Context context, String phone, int verifytype){
        Intent intent = new Intent(context, InputVerifycodeActivity.class);
        intent.putExtra("phone", phone);
        intent.putExtra("verifytype", verifytype);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_input_verifycode);
        initView();
        inputVcPre.countDownResend();
    }

    public void initView() {
        if (null == getCurrentIntent()) {
            finish();
        } else {
            phone = getIntent().getStringExtra("phone");
            VERIFY_TYPE = getIntent().getIntExtra("verifytype", 0);
            inputVcPre = new InputVerifycodePresenterImpl(this);
        }
//        if (phone)
        tvPrompt = findViewById(R.id.tv_input_Verifycode_prompt);
        tvPrompt1 = findViewById(R.id.tv_prompt1);
//        tvPrompt.setText(getResources().getString(R.string.input_code_1, phone));
        btnNext = findViewById(R.id.btn_login_sign_in);
        ivCancle = findViewById(R.id.iv_sign_in_cancle);
        tvTitle = findViewById(R.id.tv_input_Verifycode_title);
        if(VERIFY_TYPE == VerifyAccountPresenterImpl.REGIST_SEND_CODE){
            tvTitle.setText(R.string.input_code);
            tvPrompt.setText(Html.fromHtml(getResources().getString(R.string.input_code_1, phone)));
            btnNext.setText(R.string.next);
        }else if(VERIFY_TYPE == VerifyAccountPresenterImpl.FORGOT_SEND_CODE){
            tvTitle.setText(R.string.account_safe_verify);
            tvPrompt.setText(Html.fromHtml(getResources().getString(R.string.input_code_2, phone)));
            btnNext.setText(R.string.sendmsg);
            tvPrompt1.setVisibility(View.GONE);
        }
        tvTime = findViewById(R.id.tv_time);
        ivCancle.setOnClickListener(this);
        btnNext.setOnClickListener(this);
        verifyCodeView = findViewById(R.id.verify_code_view);
        verifyCodeView.setInputCompleteListener(new VerifyCodeView.InputCompleteListener() {
            @Override
            public void inputComplete() {
                Log.i("fasfas", "inputComplete: " + verifyCodeView.getEditContent());
//                Toast.makeText(InputCodeActivity.this, "inputComplete: " + verifyCodeView.getEditContent(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void invalidContent() {

            }
        });
//        if (VERIFY_TYPE == 2) {
//            tvPrompt1.setVisibility(View.GONE);
//        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        inputVcPre.countDownStop();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_login_sign_in:
                if (!TextUtils.isEmpty(verifyCodeView.getEditContent())) {
                    if (VERIFY_TYPE == 1) {
                        inputVcPre.checkVerifyCode(phone, verifyCodeView.getEditContent(), REGIST_SEND);
                    } else if (VERIFY_TYPE == 2) {
                        inputVcPre.checkVerifyCode(phone, verifyCodeView.getEditContent(), FORGOT_SEND);
                    }
                }
                break;
            case R.id.iv_sign_in_cancle:
                finish();
                break;
        }
    }

    @Override
    public void notifyResendVerifyCodeState(int resendType) {

        if (resendType == InputVerifycodePresenterImpl.RESEND_CODE) {
            inputVcPre.countDownResend();
            if (PatternMatchUtil.isNumber(phone)) {
                /**
                 * 手机重发 resend by phone
                 */
                inputVcPre.sendVerifycode(phone,REGIST_SEND_CODE);

            }
        }
    }

    @Override
    public void notifyCheckVerifyCodeResult(String result) {
        if (result.equals("SUCCESS")) {
            getCurrentIntent().setClass(InputVerifycodeActivity.this, SetPwdActivity.class);
            getCurrentIntent().putExtra("account", phone);
            getCurrentIntent().putExtra("verifycode", verifyCodeView.getEditContent());
            getCurrentIntent().putExtra("verifytype", VERIFY_TYPE);
            startActivity(getCurrentIntent());
            finish();
        } else {
            ToastUtil.showToast(InputVerifycodeActivity.this, result);
        }

    }

    @Override
    public void showTime(int time) {
        String sAgeFormat = getResources().getString(R.string.input_code_3);
        String sFinalAge = String.format(sAgeFormat, time);
        tvTime.setText(sFinalAge);

    }

    @Override
    public void hideIllegalLayout() {

    }
}

文章参考于:https://blog.csdn.net/dianziagen/article/details/68946589

                     https://blog.csdn.net/qq_33553515/article/details/73344155

猜你喜欢

转载自blog.csdn.net/Snow_Ice_Yang/article/details/81868328