Activation Code Verification Code Input Box for Custom view

Two days ago, I received a project. In the project, I need to customize an activation code input box, which is similar to the square input box of a drip taxi. Then I thought about how to do this input box. I finally got it today. The input box receives the number of customized input boxes, the width of the input box, the partition lines between the input boxes, the color of the input box, the size of the input box, and the focus of the input box. The border of a point, the number of words per input box, and the transparency of the input box

Effect display

Development thinking

We need to accept our input through the EditText control, which is obviously not visible in the interface, so we need to make the control transparent. Then we set the input we received to our TextView. To satisfy the square style, you just need to set a background for TextView. In the development process, we found that the number of validation codes is not fixed, there are four digits, there are six digits. In order to achieve low coupling reusability. We need a custom property to meet this requirement. Other specific ideas will be discussed when they are realized.

Realization

  • Layout Implementation of Composite Control
<?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="match_parent">

    <LinearLayout
        android:id="@+id/container_et"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:showDividers="middle">

    </LinearLayout>

    <EditText
        android:id="@+id/et"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:inputType="number" />

</RelativeLayout>

This is the way that Linear Layout stores TextVeiw, android: show Dividers = "middle" to set our intervals.

  • Design custom properties
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ActivationCodeView">

        <attr name="icv_et_number" format="integer" />
        <! - Width of input box - >
        <attr name="icv_et_width" format="dimension|reference" />
        <! - The partition line between input boxes - >
        <attr name="icv_et_divider_drawable" format="reference" />
        <! - Input box text color - >
        <attr name="icv_et_text_color" format="color|reference" />
        <! - Input Box Text Size - >
        <attr name="icv_et_text_size" format="dimension|reference" />
        <! - The border when the input box gets the focus - >
        <attr name="icv_et_bg_focus" format="reference" />
        <! - When the input box has no focus, the border - >
        <attr name="icv_et_bg_normal" format="reference" />
        <! - Number of words in each input box - >
        <attr name="icv_text_count_num" format="integer" />
        <! - Background Transparency of Input Box - >
        <attr name="icv_text_bg_alpha" format="integer" />
    </declare-styleable>
</resources>

The annotations are clear enough that they are no longer explained.

  • Get custom properties
/**
     * Initialization
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        LayoutInflater.from(context).inflate(R.layout.layout_activation_code, this);
        mContainerLl = (LinearLayout) this.findViewById(R.id.container_et);
        mInputEt = (EditText) this.findViewById(R.id.et);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ActivationCodeView, defStyleAttr, 0);
        mEtNumber = typedArray.getInteger(R.styleable.ActivationCodeView_icv_et_number, 1);
        mTvCountNumber = typedArray.getInteger(R.styleable.ActivationCodeView_icv_text_count_num, 1);
        mAlpha = typedArray.getInteger(R.styleable.ActivationCodeView_icv_text_bg_alpha,255);
        mEtWidth = typedArray.getDimensionPixelSize(R.styleable.ActivationCodeView_icv_et_width, 42);
        mEtDividerDrawable = typedArray.getDrawable(R.styleable.ActivationCodeView_icv_et_divider_drawable);
        mEtTextSize = typedArray.getDimensionPixelSize(R.styleable.ActivationCodeView_icv_et_text_size, 16);
        mEtTextColor = typedArray.getColor(R.styleable.ActivationCodeView_icv_et_text_color, Color.BLACK);
        mEtBackgroundDrawableFocus = typedArray.getDrawable(R.styleable.ActivationCodeView_icv_et_bg_focus);
        mEtBackgroundDrawableNormal = typedArray.getDrawable(R.styleable.ActivationCodeView_icv_et_bg_normal);
        //Release resources
        typedArray.recycle();


        // When not configured in xml, the default image is initially configured here
        if (mEtDividerDrawable == null) {
            mEtDividerDrawable = context.getResources().getDrawable(R.drawable.shape_divider_identifying);
        }

        if (mEtBackgroundDrawableFocus == null) {
            mEtBackgroundDrawableFocus = context.getResources().getDrawable(R.drawable.shape_icv_et_bg_focus);
        }

        if (mEtBackgroundDrawableNormal == null) {
            mEtBackgroundDrawableNormal = context.getResources().getDrawable(R.drawable.shape_icv_et_bg_normal);
        }

        initUI();
    }
  • Initialize TextView
 //Initialize TextView
    private void initTextViews(Context context, int etNumber, int etWidth, Drawable etDividerDrawable, float etTextSize, int etTextColor) {
        // Set the input length of editText
        mInputEt.setCursorVisible(false);//Hide the cursor
        mInputEt.setFilters(new InputFilter[]{new InputFilter.LengthFilter(etNumber)}); //Maximum input length
        // Set the width of the partition line
        if (etDividerDrawable != null) {
            etDividerDrawable.setBounds(0, 0, etDividerDrawable.getMinimumWidth(), etDividerDrawable.getMinimumHeight());
            mContainerLl.setDividerDrawable(etDividerDrawable);
        }
        mTextViews = new TextView[etNumber];
        for (int i = 0; i < mTextViews.length; i++) {
            TextView textView = new TextView(context);
            textView.setTextSize(etTextSize);
            textView.setTextColor(etTextColor);
            textView.setWidth(etWidth);
            textView.setHeight(etWidth);

            if (i == 0) {
                textView.setBackgroundDrawable(mEtBackgroundDrawableFocus);
            } else {
                textView.setBackgroundDrawable(mEtBackgroundDrawableNormal);
            }
            //Setting Transparency
            textView.getBackground().setAlpha(mAlpha);
            textView.setGravity(Gravity.CENTER);

            textView.setFocusable(false);

            mTextViews[i] = textView;
        }
    }

The dynamic generation of TextView implementation annotations is very clear here. One thing to note is that textView.setFocusable(false); otherwise TextView will get a cursor in the page. Use an array to store TextView.

  • Fill in the iner Layout that holds TextView
   private void initEtContainer(TextView[] mTextViews) {
        for (int i = 0; i < mTextViews.length; i++) {
             mContainerLl.addView(mTextViews[i]);
        }
    }
  • Handling our input events
 private class ActivationCodeTextWatcher implements TextWatcher {

        @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 editable) {
            String inputStr = editable.toString();
            if (inputStr != null && !inputStr.equals("")) {
                setText(inputStr);
                mInputEt.setText("");
            }
        }
    }

     // Listen for Delete Keys
        mInputEt.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
                    onKeyDelete();
                    return true;
                }
                return false;
            }
        });
    // Set text for TextView
    private void setText(String inputContent) {
        for (int i = 0; i < mTextViews.length; i++) {
            TextView tv = mTextViews[i];
            if (tv.getText().toString().trim().equals("") || tv.getText().toString().length() < mTvCountNumber) {
                tv.setText(tv.getText().toString() + inputContent);
                // Adding input-completed listening
                if (inputCompleteListener != null) {
                    inputCompleteListener.inputComplete();
                }
                //Hop the cursor to the next one
                if(tv.getText().toString().length() == mTvCountNumber) {
                    tv.setBackgroundDrawable(mEtBackgroundDrawableNormal);
                    if (i < mEtNumber - 1) {
                        mTextViews[i + 1].setBackgroundDrawable(mEtBackgroundDrawableFocus);
                    }
                }

                break;
            }
        }
    }

    // Monitor deletion
    private void onKeyDelete() {
        for (int i = mTextViews.length - 1; i >= 0; i--) {
            TextView tv = mTextViews[i];
            if (!tv.getText().toString().trim().equals("")) {

                tv.setText(tv.getText().subSequence(0,tv.getText().length()-1));
                // Added Delete Complete Listening
                if (inputCompleteListener != null) {
                    inputCompleteListener.deleteContent();
                }
                tv.setBackgroundDrawable(mEtBackgroundDrawableFocus);
                if (i < mEtNumber - 1) {
                    mTextViews[i + 1].setBackgroundDrawable(mEtBackgroundDrawableNormal);
                }
                break;
            }
        }
    }
  • The method provided to the outside world
 /**
     * Get input text
     *
     * @return string
     */
    public String getInputContent() {
        StringBuffer buffer = new StringBuffer();
        for (TextView tv : mTextViews) {
            buffer.append(tv.getText().toString().trim());
        }
        return buffer.toString();
    }

    /**
     * Delete input
     */
    public void clearInputContent() {
        for (int i = 0; i < mTextViews.length; i++) {
            if (i == 0) {
                mTextViews[i].setBackgroundDrawable(mEtBackgroundDrawableFocus);
            } else {
                mTextViews[i].setBackgroundDrawable(mEtBackgroundDrawableNormal);
            }
            mTextViews[i].setText("");
        }
    }

    /**
     * Set the number of input boxes
     * @param etNumber
     */
    public void setEtNumber(int etNumber) {
        this.mEtNumber = etNumber;
        mInputEt.removeTextChangedListener(mTextWatcher);
        mContainerLl.removeAllViews();
        initUI();
    }


    /**
     * Get the number of bits of input
     *
     * @return int
     */
    public int getEtNumber() {
        return mEtNumber;
    }

    // Successful listening for input completion and deletion
    private InputCompleteListener inputCompleteListener;

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

    public interface InputCompleteListener {
        void inputComplete();

        void deleteContent();
    }

Original address Activation Code Verification Code Input Box for Custom view

Keywords: Android xml encoding

Added by kratsg on Tue, 14 May 2019 18:45:47 +0300