Alipay Taobao custom password input box and keyboard

1. Password input box

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="PasswordEditText">
        <! -- number of passwords -- >
        <attr name="passwordNumber" format="integer"/>
        <! -- radius of password dot -- >
        <attr name="passwordRadius" format="dimension" />
        <! -- color of password dot -- >
        <attr name="passwordColor" format="color" />
        <! -- color of split line -- >
        <attr name="divisionLineColor" format="color" />
        <! -- size of split line -- >
        <attr name="divisionLineSize" format="color" />
        <! -- color of background border -- >
        <attr name="bgColor" format="color" />
        <! -- size of background border -- >
        <attr name="bgSize" format="dimension" />
        <! -- fillet size of background border -- >
        <attr name="bgCorner" format="dimension"/>
    </declare-styleable>
</resources>

PasswordEditText

public class PasswordEditText extends EditText {
    // Paint brush
    private Paint mPaint;
    // The width of a password
    private int mPasswordItemWidth;
    // The number of passwords is 6 digits by default
    private int mPasswordNumber = 6;
    // Background border color
    private int mBgColor = Color.parseColor("#d1d2d6");
    // Background border size
    private int mBgSize = 1;
    // Background border fillet size
    private int mBgCorner = 0;
    // Color of split line
    private int mDivisionLineColor = mBgColor;
    // Size of split line
    private int mDivisionLineSize = 1;
    // Color of code dot
    private int mPasswordColor = mDivisionLineColor;
    // Radius size of cipher dot
    private int mPasswordRadius = 4;
    private PasswordFullListener mListener;

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

    public PasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
        initAttributeSet(context, attrs);
        // Set input mode as password
        setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
        // Don't show cursor
        setCursorVisible(false);
    }

    /**
     * Initialize properties
     */
    private void initAttributeSet(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText);
        // Get size
        mDivisionLineSize = (int) array.getDimension(R.styleable.PasswordEditText_divisionLineSize, dip2px(mDivisionLineSize));
        mPasswordRadius = (int) array.getDimension(R.styleable.PasswordEditText_passwordRadius, dip2px(mPasswordRadius));
        mBgSize = (int) array.getDimension(R.styleable.PasswordEditText_bgSize, dip2px(mBgSize));
        mBgCorner = (int) array.getDimension(R.styleable.PasswordEditText_bgCorner, 0);
        // get colors
        mBgColor = array.getColor(R.styleable.PasswordEditText_bgColor, mBgColor);
        mDivisionLineColor = array.getColor(R.styleable.PasswordEditText_divisionLineColor, mDivisionLineColor);
        mPasswordColor = array.getColor(R.styleable.PasswordEditText_passwordColor, mDivisionLineColor);
        array.recycle();
    }

    /**
     * Initialize brush
     */
    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
    }

    /**
     * dip Turn px
     */
    private int dip2px(int dip) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dip, getResources().getDisplayMetrics());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int passwordWidth = getWidth() - (mPasswordNumber - 1) * mDivisionLineSize;
        mPasswordItemWidth = passwordWidth / mPasswordNumber;
        // Draw background
        drawBg(canvas);
        // Draw split line
        drawDivisionLine(canvas);
        // Draw password
        drawHidePassword(canvas);
    }

    /**
     * Draw background
     */
    private void drawBg(Canvas canvas) {
        mPaint.setColor(mBgColor);
        // Set brush to empty
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mBgSize);
        RectF rectF = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight() - mBgSize);
        // If the fillet is not set, draw a rectangle
        if (mBgCorner == 0) {
            canvas.drawRect(rectF, mPaint);
        } else {
            // Draw a circle rectangle if you have rounded corners
            canvas.drawRoundRect(rectF, mBgCorner, mBgCorner, mPaint);
        }
    }

    /**
     * Draw hidden password
     */
    private void drawHidePassword(Canvas canvas) {
        int passwordLength = getText().length();
        mPaint.setColor(mPasswordColor);
        // Set brush to solid
        mPaint.setStyle(Paint.Style.FILL);
        for (int i = 0; i < passwordLength; i++) {
            int cx = i * mDivisionLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mPasswordRadius, mPaint);
        }
        // Determine whether the password is filled
        if (passwordLength >= mPasswordNumber) {
            // The password is full
            if (mListener != null) {
                mListener.passwordFull(getText().toString().trim());
            }
        }
    }

    /**
     * Draw split line
     */
    private void drawDivisionLine(Canvas canvas) {
        mPaint.setStrokeWidth(mDivisionLineSize);
        mPaint.setColor(mDivisionLineColor);
        for (int i = 0; i < mPasswordNumber - 1; i++) {
            int startX = (i + 1) * mDivisionLineSize + (i + 1) * mPasswordItemWidth + mBgSize;
            canvas.drawLine(startX, mBgSize, startX, getHeight() - mBgSize, mPaint);
        }
    }

    /**
     * Add password
     */
    public void addPassword(String number) {
        number = getText().toString().trim() + number;
        if (number.length() > mPasswordNumber) {
            return;
        }
        setText(number);
    }

    /**
     * Delete last password
     */
    public void deleteLastPassword() {
        String currentText = getText().toString().trim();
        if (TextUtils.isEmpty(currentText)) {
            return;
        }
        currentText = currentText.substring(0, currentText.length() - 1);
        setText(currentText);
    }

    /**
     * Set the monitor with full password
     */
    public void setOnPasswordFullListener(PasswordFullListener listener) {
        this.mListener = listener;
    }

    /**
     * The password is full
     */
    public interface PasswordFullListener {
        public void passwordFull(String password);
    }
}

The current effect is that the system's keyboard will pop up after clicking, realizing the basic effect. Next, we add monitoring, which means that when the password is input, we need to callback monitoring.  
  
 

 

2. Custom keyboard:

ui_customer_keyboard.xml:

  1 <?xml version="1.0" encoding="utf-8"?>
  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3     android:id="@+id/activity_main"
  4     android:layout_width="match_parent"
  5     android:layout_height="wrap_content"
  6     android:background="#EBEBEB"
  7     android:orientation="vertical">
  8 
  9     <LinearLayout
 10         android:layout_width="match_parent"
 11         android:layout_height="wrap_content">
 12 
 13         <TextView
 14             android:layout_width="0dp"
 15             android:layout_height="wrap_content"
 16             android:layout_marginRight="1dp"
 17             android:layout_weight="1"
 18             android:background="#FFFFFF"
 19             android:gravity="center"
 20             android:padding="20dp"
 21             android:text="1" />
 22 
 23         <TextView
 24             android:layout_width="0dp"
 25             android:layout_height="wrap_content"
 26             android:layout_marginRight="1dp"
 27             android:layout_weight="1"
 28             android:background="#FFFFFF"
 29             android:gravity="center"
 30             android:padding="20dp"
 31             android:text="2" />
 32 
 33         <TextView
 34             android:layout_width="0dp"
 35             android:layout_height="wrap_content"
 36             android:layout_weight="1"
 37             android:background="#FFFFFF"
 38             android:gravity="center"
 39             android:padding="20dp"
 40             android:text="3" />
 41     </LinearLayout>
 42 
 43     <LinearLayout
 44         android:layout_width="match_parent"
 45         android:layout_height="wrap_content"
 46         android:layout_marginTop="1dp">
 47 
 48         <TextView
 49             android:layout_width="0dp"
 50             android:layout_height="wrap_content"
 51             android:layout_marginRight="1dp"
 52             android:layout_weight="1"
 53             android:background="#FFFFFF"
 54             android:gravity="center"
 55             android:padding="20dp"
 56             android:text="4" />
 57 
 58         <TextView
 59             android:layout_width="0dp"
 60             android:layout_height="wrap_content"
 61             android:layout_marginRight="1dp"
 62             android:layout_weight="1"
 63             android:background="#FFFFFF"
 64             android:gravity="center"
 65             android:padding="20dp"
 66             android:text="5" />
 67 
 68         <TextView
 69             android:layout_width="0dp"
 70             android:layout_height="wrap_content"
 71             android:layout_weight="1"
 72             android:background="#FFFFFF"
 73             android:gravity="center"
 74             android:padding="20dp"
 75             android:text="6" />
 76     </LinearLayout>
 77 
 78     <LinearLayout
 79         android:layout_width="match_parent"
 80         android:layout_height="wrap_content"
 81         android:layout_marginTop="1dp">
 82 
 83         <TextView
 84             android:layout_width="0dp"
 85             android:layout_height="wrap_content"
 86             android:layout_marginRight="1dp"
 87             android:layout_weight="1"
 88             android:background="#FFFFFF"
 89             android:gravity="center"
 90             android:padding="20dp"
 91             android:text="7" />
 92 
 93         <TextView
 94             android:layout_width="0dp"
 95             android:layout_height="wrap_content"
 96             android:layout_marginRight="1dp"
 97             android:layout_weight="1"
 98             android:background="#FFFFFF"
 99             android:gravity="center"
100             android:padding="20dp"
101             android:text="8" />
102 
103         <TextView
104             android:layout_width="0dp"
105             android:layout_height="wrap_content"
106             android:layout_weight="1"
107             android:background="#FFFFFF"
108             android:gravity="center"
109             android:padding="20dp"
110             android:text="9" />
111 
112     </LinearLayout>
113 
114     <LinearLayout
115         android:layout_width="match_parent"
116         android:layout_height="wrap_content"
117         android:layout_marginTop="1dp"
118         android:orientation="horizontal">
119 
120         <TextView
121             android:layout_width="0dp"
122             android:layout_height="wrap_content"
123             android:layout_marginRight="1dp"
124             android:layout_weight="1"
125             android:gravity="center"
126             android:padding="20dp" />
127 
128         <TextView
129             android:layout_width="0dp"
130             android:layout_height="wrap_content"
131             android:layout_marginRight="1dp"
132             android:layout_weight="1"
133             android:background="#FFFFFF"
134             android:gravity="center"
135             android:padding="20dp"
136             android:text="0" />
137 
138         <ImageView
139             android:layout_width="0dp"
140             android:layout_height="wrap_content"
141             android:layout_weight="1"
142             android:gravity="center"
143             android:padding="15dp"
144             android:layout_gravity="center_vertical"
145             android:src="@drawable/customer_password_keyboard_delete" />
146     </LinearLayout>
147 </LinearLayout>

CustomerKeyboard.java:

 1 public class CustomerKeyboard extends LinearLayout implements View.OnClickListener {
 2     private CustomerKeyboardClickListener mListener;
 3 
 4     public CustomerKeyboard(Context context) {
 5         this(context, null);
 6     }
 7 
 8     public CustomerKeyboard(Context context, AttributeSet attrs) {
 9         this(context, attrs, 0);
10     }
11 
12     public CustomerKeyboard(Context context, AttributeSet attrs, int defStyleAttr) {
13         super(context, attrs, defStyleAttr);
14         inflate(context, R.layout.ui_customer_keyboard, this);
15         setChildViewOnclick(this);
16     }
17 
18     /**
19      * Set the click event of keyboard subview
20      */
21     private void setChildViewOnclick(ViewGroup parent) {
22         int childCount = parent.getChildCount();
23         for (int i = 0; i < childCount; i++) {
24             // Setting click events recursively
25             View view = parent.getChildAt(i);
26             if (view instanceof ViewGroup) {
27                 setChildViewOnclick((ViewGroup) view);
28                 continue;
29             }
30             view.setOnClickListener(this);
31         }
32     }
33 
34     @Override
35     public void onClick(View v) {
36         View clickView = v;
37         if (clickView instanceof TextView) {
38             // If you click Yes TextView
39             String number = ((TextView) clickView).getText().toString();
40             if (!TextUtils.isEmpty(number)) {
41                 if (mListener != null) {
42                     // Callback
43                     mListener.click(number);
44                 }
45             }
46         } else if (clickView instanceof ImageView) {
47             // If it's a picture, it must be deleted
48             if (mListener != null) {
49                 mListener.delete();
50             }
51         }
52     }
53 
54     /**
55      * Set keyboard click callback monitoring
56      */
57     public void setOnCustomerKeyboardClickListener(CustomerKeyboardClickListener listener) {
58         this.mListener = listener;
59     }
60 
61     /**
62      * Click callback monitor of keyboard
63      */
64     public interface CustomerKeyboardClickListener {
65         public void click(String number);
66         public void delete();
67     }
68 }

 

3. Final test

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="#f7f7f7"
    android:orientation="vertical">

    <com.hc.passwordedittext.PasswordEditText
        android:id="@+id/password_edit_text"
        android:layout_width="match_parent"
        android:layout_marginTop="23dp"
        android:layout_marginRight="45dp"
        android:background="@null"
        android:padding="10dp"
        app:bgCorner="3dp"
        android:layout_marginLeft="45dp"
        android:layout_height="wrap_content" />


    <com.hc.passwordedittext.CustomerKeyboard
        android:id="@+id/custom_key_board"
        android:layout_marginTop="23dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

MainActivity.java

 1 public class MainActivity extends Activity implements CustomerKeyboard.CustomerKeyboardClickListener,
 2         PasswordEditText.PasswordFullListener{
 3 
 4     private CustomerKeyboard mCustomerKeyboard;
 5     private PasswordEditText mPasswordEditText;
 6 
 7     @Override
 8     protected void onCreate(Bundle savedInstanceState) {
 9         super.onCreate(savedInstanceState);
10         setContentView(R.layout.activity_main);
11         mPasswordEditText = (PasswordEditText) findViewById(R.id.password_et);
12         mCustomerKeyboard = (CustomerKeyboard) findViewById(R.id.custom_key_board);
13         // Set listening
14         mCustomerKeyboard.setOnCustomerKeyboardClickListener(this);
15         mPasswordEditText.setOnPasswordFullListener(this);
16     }
17 
18     /**
19      * Keyboard number click monitor callback method
20      */
21     @Override
22     public void click(String number) {
23         mPasswordEditText.addPassword(number);
24     }
25 
26     /**
27      * Keyboard delete click listen callback method
28      */
29     @Override
30     public void delete() {
31         mPasswordEditText.deleteLastPassword();
32     }
33 
34     /**
35      * Callback method after password input
36      */
37     @Override
38     public void passwordFull(String password) {
39         Toast.makeText(this, "Password filled:" + password, Toast.LENGTH_SHORT).show();
40     }
41 }

 

 

https://github.com/HCDarren/PasswordEditText

Tags: Android xml encoding Java

Posted on Sun, 03 May 2020 21:44:04 -0400 by phpgeek17