CodeEditView 短信驗證碼框

原理:

自定義佈局,包含一個EditText 和多個 TextView ,EditText隱藏看不見,可以判斷是否達到指定位數。

通過for循環取值EditText中的字符,再new出新的TextView對象,並填入對應數值即可。

 

核心代碼入下:

CodeEditView 

public class CodeEditView extends LinearLayout implements TextWatcher, View.OnClickListener, View.OnLongClickListener {
    private int editViewNum = 6; //默認輸入框數量
    private ArrayList<TextView> mTextViewsList = new ArrayList<>(); //存儲EditText對象
    private Context mContext;
    private EditText mEditText;
    private int borderSize = 35; //方格邊框大小
    private int borderMargin = 10; //方格間距
    private int textSize = 8; //字體大小
    private int textColor = 0xff; //字體顏色
    private int inputType = InputType.TYPE_CLASS_NUMBER;
    private inputEndListener callBack;

    public CodeEditView(Context context) {
        super(context);
        init(context);
    }

    public CodeEditView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initData(context, attrs);
        init(context);
    }

    public CodeEditView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData(context, attrs);
        init(context);
    }

    private void initData(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CodeEditView);
        borderSize = array.getInteger(R.styleable.CodeEditView_borderSize, 35);
        borderMargin = array.getInteger(R.styleable.CodeEditView_borderMargin, 10);
        textSize = array.getInteger(R.styleable.CodeEditView_textSize, 8);
        textColor = array.getColor(R.styleable.CodeEditView_textColor, Color.BLACK);
        editViewNum = array.getInteger(R.styleable.CodeEditView_borderNum, 6);
    }

    /**
     * 獲取輸入框內容
     */
    public String getText() {
        return mEditText.getText().toString();
    }

    public void setOnInputEndCallBack(inputEndListener onInputEndCallBack) {
        callBack = onInputEndCallBack;
    }

    /**
     * 長按彈出PopupWindow,用來粘貼文本
     */
    @Override
    public boolean onLongClick(View v) {
        showPopupWindow();
        return true;
    }

    private void showPopupWindow() {
        View popupwindow = LayoutInflater.from(mContext).inflate(R.layout.popupwindow_view, null);
        final PopupWindow popupWindow = new PopupWindow(popupwindow, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);
        popupWindow.showAsDropDown(this, getWidth() / 2, DensityUtil.dip2px(mContext, 5));
        popupwindow.findViewById(R.id.paste).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                popupWindow.dismiss();
                pasteTextToView();
            }
        });
    }

    /**
     * 粘貼內容到文本框
     */
    private void pasteTextToView() {
        if (getPasetText() != null && !TextUtils.isEmpty(getPasetText()) && isInteger(getPasetText())) {
            //純數字
            char[] chars = getPasetText().substring(0, editViewNum).toCharArray();
            mEditText.setText(getPasetText().substring(0, editViewNum));
            for (int i = 0; i < chars.length; i++) {
                mTextViewsList.get(i).setText(String.valueOf(chars[i]));
            }
        } else {
            Toast.makeText(mContext, "粘貼的文本必須爲純數字", Toast.LENGTH_SHORT).show();
        }
    }

    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    public String getPasetText() {
        ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
        ClipData clipData = clipboard.getPrimaryClip();
        if (clipData != null && clipData.getItemCount() > 0) {
            CharSequence text = clipData.getItemAt(0).getText();
            return text.toString().trim();
        }
        return "";
    }

    public interface inputEndListener {
        void input(String text);

        void afterTextChanged(String text);
    }

    private void init(final Context context) {
        mContext = context;
        initEditText(context);
        //設置方格間距
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                DensityUtil.dip2px(mContext, borderSize), DensityUtil.dip2px(mContext, borderSize));
        params.setMargins(DensityUtil.dip2px(mContext, borderMargin), 0, 0, 0);
        //設置方格文字
        for (int i = 0; i < editViewNum; i++) {
            TextView textView = new TextView(mContext);
            textView.setBackgroundResource(R.drawable.shape_border_normal);
            textView.setGravity(Gravity.CENTER);
            textView.setTextSize(DensityUtil.sp2px(mContext, textSize));
            textView.getPaint().setFakeBoldText(true);
            textView.setLayoutParams(params);
            textView.setInputType(inputType);
            textView.setTextColor(textColor);
            textView.setOnClickListener(this);
            textView.setOnLongClickListener(this);
            mTextViewsList.add(textView);
            addView(textView);
        }

        //顯示隱藏軟鍵盤
        new android.os.Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mEditText.setFocusable(true);
                mEditText.setFocusableInTouchMode(true);
                mEditText.requestFocus();
                InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
            }
        }, 500);

        //監聽刪除鍵
        mEditText.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_DEL) {
                    if (mEditText.getText().length() >= mTextViewsList.size()) return false;
                    mTextViewsList.get(mEditText.getText().length()).setText("");
                }
                return false;
            }
        });

        this.setOnLongClickListener(this);
    }

    private void initEditText(Context context) {
        mEditText = new EditText(context);
        mEditText.setBackgroundColor(Color.parseColor("#00000000"));
        mEditText.setMaxLines(1);
        mEditText.setInputType(inputType);
        mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(editViewNum)});
        mEditText.addTextChangedListener(this);
        mEditText.setTextSize(0);
        mEditText.setHeight(1);
        mEditText.setWidth(1);
        addView(mEditText);
    }

    //清空文字
    public void clearText() {
        mEditText.setText("");
        for (TextView textView : mTextViewsList) {
            textView.setText("");
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
        if (callBack != null) {
            callBack.afterTextChanged(s.toString());
        }
        if (s.length() <= 1) {
            mTextViewsList.get(0).setText(s);
        } else {
            mTextViewsList.get(mEditText.getText().length() - 1).setText(s.subSequence(s.length() - 1, s.length()));
        }
        if (s.length() == editViewNum) {
            if (callBack != null) {
                callBack.input(mEditText.getText().toString());
            }
        }
    }

    @Override
    public void onClick(View v) { //TextView點擊時獲取焦點彈出輸入法
        mEditText.setFocusable(true);
        mEditText.setFocusableInTouchMode(true);
        mEditText.requestFocus();
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

attrs : CodeEditView

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CodeEditView">
        <attr name="textColor" format="color"/>
        <attr name="textSize" format="integer"/>
        <attr name="borderSize" format="integer"/>
        <attr name="borderMargin" format="integer"/>
        <attr name="borderNum" format="integer"/>
    </declare-styleable>
</resources>

popupwindow_view.xlm

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content">
    <TextView
        android:background="@drawable/select_popupwindow_bg"
        android:id="@+id/paste"
        android:padding="8dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#ffffff"
        android:text="粘貼"/>
</LinearLayout>

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    
    <com.leixiansheng.codeeditview.CodeEditView
        android:id="@+id/normal_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"/>

    <Button
        android:id="@+id/btn_clear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:text="清除輸入"/>

    <com.leixiansheng.codeeditview.CodeEditView
        android:id="@+id/custom_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:layout_marginTop="20dp"
        app:textColor="@color/colorPrimary"
        app:textSize="5"
        app:borderNum="10"
        app:borderSize="30"
        app:borderMargin="10"/>

    <TextView
        android:padding="10dp"
        android:id="@+id/textview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="\n\t
        app:textColor=@color/colorAccent //字體顏色\n\t
        app:borderNum=4 //輸入框個數\n\t
        app:borderMargin=20 //輸入框間距\n\t
        app:borderSize=48 //輸入框大小\n\t
        app:textSize=10 //字體大小"
        android:layout_gravity="center_horizontal"/>
</LinearLayout>

主代碼:

public class MainActivity extends AppCompatActivity {

    private CodeEditView normalView;
    private CodeEditView customView;
    private Button mClear;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        normalView = findViewById(R.id.normal_view);
        customView = findViewById(R.id.custom_view);
        mClear = findViewById(R.id.btn_clear);

        normalView.setOnInputEndCallBack(new CodeEditView.inputEndListener() {
            @Override
            public void input(String text) {
                toast(text);
            }

            @Override
            public void afterTextChanged(String text) {

            }
        });

        customView.setOnInputEndCallBack(new CodeEditView.inputEndListener() {
            @Override
            public void input(String text) {
                toast(text);
            }

            @Override
            public void afterTextChanged(String text) {
                toast(text);
            }
        });

        mClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                clear(normalView);
            }
        });
    }

    //清除文字
    public void clear(CodeEditView view) {
        view.clearText();
    }

    public void toast(String str) {
        Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章