Search code examples
androidandroid-softkeyboard

Android custom numeric keyboard


I want to add numeric keyboard like the one in vault application

enter image description here

I don't know how to call it and how can I find in google ?


Solution

    1. Use TableLayout to create the numeric keyboard layout.
    2. Bind View.OnClickListener on each custom key view to response user input.
    3. In responses, append or delete text to that password field which implements by EditText.You can use append() or setText() to control what will be filled in the password field.

    I write a custom view for reusing in anywhere, here is the code:

    KeyboardView.java

    public class KeyboardView extends FrameLayout implements View.OnClickListener {
    
        private EditText mPasswordField;
    
        public KeyboardView(Context context) {
            super(context);
            init();
        }
    
        public KeyboardView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public KeyboardView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            inflate(getContext(), R.layout.keyboard, this);
            initViews();
        }
    
        private void initViews() {
            mPasswordField = $(R.id.password_field);
            $(R.id.t9_key_0).setOnClickListener(this);
            $(R.id.t9_key_1).setOnClickListener(this);
            $(R.id.t9_key_2).setOnClickListener(this);
            $(R.id.t9_key_3).setOnClickListener(this);
            $(R.id.t9_key_4).setOnClickListener(this);
            $(R.id.t9_key_5).setOnClickListener(this);
            $(R.id.t9_key_6).setOnClickListener(this);
            $(R.id.t9_key_7).setOnClickListener(this);
            $(R.id.t9_key_8).setOnClickListener(this);
            $(R.id.t9_key_9).setOnClickListener(this);
            $(R.id.t9_key_clear).setOnClickListener(this);
            $(R.id.t9_key_backspace).setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            // handle number button click
            if (v.getTag() != null && "number_button".equals(v.getTag())) {
                mPasswordField.append(((TextView) v).getText());
                return;
            }
            switch (v.getId()) {
                case R.id.t9_key_clear: { // handle clear button
                    mPasswordField.setText(null);
                }
                break;
                case R.id.t9_key_backspace: { // handle backspace button
                    // delete one character
                    Editable editable = mPasswordField.getText();
                    int charCount = editable.length();
                    if (charCount > 0) {
                        editable.delete(charCount - 1, charCount);
                    }
                }
                break;
            }
        }
    
        public String getInputText() {
            return mPasswordField.getText().toString();
        }
    
        protected <T extends View> T $(@IdRes int id) {
            return (T) super.findViewById(id);
        }
    }
    

    layout keyboard.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="8dp">
    
        <EditText
            android:id="@+id/password_field"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:background="#eeeeee"
            android:enabled="false"
            android:minHeight="48dp"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:singleLine="true"
            android:textAppearance="?android:attr/textAppearanceMedium"/>
    
        <TableLayout
            android:id="@+id/keyboard"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/white"
            android:divider="@drawable/keyboard_divider"
            android:orientation="vertical"
            android:showDividers="beginning|middle|end">
    
            <TableRow style="@style/keyboard_row">
    
                <TextView
                    android:id="@+id/t9_key_1"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_one"/>
    
                <TextView
                    android:id="@+id/t9_key_2"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_two"/>
    
                <TextView
                    android:id="@+id/t9_key_3"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_three"/>
            </TableRow>
    
            <TableRow style="@style/keyboard_row">
    
                <TextView
                    android:id="@+id/t9_key_4"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_four"/>
    
                <TextView
                    android:id="@+id/t9_key_5"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_five"/>
    
                <TextView
                    android:id="@+id/t9_key_6"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_six"/>
            </TableRow>
    
            <TableRow style="@style/keyboard_row">
    
                <TextView
                    android:id="@+id/t9_key_7"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_seven"/>
    
                <TextView
                    android:id="@+id/t9_key_8"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_eight"/>
    
                <TextView
                    android:id="@+id/t9_key_9"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_nine"/>
            </TableRow>
    
            <TableRow style="@style/keyboard_row">
    
                <TextView
                    android:id="@+id/t9_key_clear"
                    style="@style/keyboard_button"
                    android:text="@string/btn_clear"
                    android:textAppearance="?android:attr/textAppearanceMedium"/>
    
                <TextView
                    android:id="@+id/t9_key_0"
                    style="@style/keyboard_number_button"
                    android:text="@string/number_zero"/>
    
                <TextView
                    android:id="@+id/t9_key_backspace"
                    style="@style/keyboard_button"
                    android:text="@string/btn_backspace"
                    android:textAppearance="?android:attr/textAppearanceMedium"/>
            </TableRow>
        </TableLayout>
    </LinearLayout>
    

    style.xml

    <style name="keyboard_row">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:divider">@drawable/keyboard_divider</item>
        <item name="android:gravity">center</item>
        <item name="android:showDividers">beginning|middle|end</item>
    </style>
    
    <style name="keyboard_button">
        <item name="android:layout_width">0dp</item>
        <item name="android:layout_height">match_parent</item>
        <item name="android:layout_weight">1</item>
        <item name="android:paddingTop">12dp</item>
        <item name="android:paddingBottom">12dp</item>
        <item name="android:clickable">true</item>
        <item name="android:gravity">center</item>
        <item name="android:scaleType">centerInside</item>
        <item name="android:background">@drawable/keyboard_button_bg</item>
        <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
    </style>
    
    <style name="keyboard_number_button" parent="keyboard_button">
        <item name="android:tag">number_button</item>
    </style>
    

    drawable keyboard_button_bg.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_shortAnimTime">
        <item android:state_pressed="true">
            <shape>
                <solid android:color="#dddddd"/>
            </shape>
        </item>
        <item android:state_pressed="false">
            <shape>
                <solid android:color="@android:color/transparent"/>
            </shape>
        </item>
    </selector> 
    

    drawable keyboard_divider.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="#dddddd"/>
        <size
            android:width="1px"
            android:height="1px"/>
    </shape>
    

    strings.xml

    <string name="number_zero">0</string>
    <string name="number_one">1</string>
    <string name="number_two">2</string>
    <string name="number_three">3</string>
    <string name="number_four">4</string>
    <string name="number_five">5</string>
    <string name="number_six">6</string>
    <string name="number_seven">7</string>
    <string name="number_eight">8</string>
    <string name="number_nine">9</string>
    <string name="btn_clear">Clear</string>
    <string name="btn_backspace">Back</string>
    

    Use the custom KeyboardView in your layout :

    <com.xxx.yyy.KeyboardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    

    Old answer:

    The keyboard layout code looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    
    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/anti_theft_t9_grid"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white_grey"
        android:divider="@android:color/darker_gray"
        android:orientation="vertical"
        android:showDividers="middle|beginning|end" >
    
    <TableRow
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:divider="@android:color/darker_gray"
        android:gravity="center"
        android:showDividers="middle" >
    
        <TextView
            android:id="@+id/anti_theft_t9_key_1"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_one"
            android:textIsSelectable="false" />
    
        <TextView
            android:id="@+id/anti_theft_t9_key_2"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_two"
            android:textIsSelectable="false" />
    
        <TextView
            android:id="@+id/anti_theft_t9_key_3"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_three"
            android:textIsSelectable="false" />
    </TableRow>
    
    <TableRow
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:divider="@android:color/darker_gray"
        android:gravity="center"
        android:showDividers="middle" >
    
        <TextView
            android:id="@+id/anti_theft_t9_key_4"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_four"
            android:textIsSelectable="false" />
    
        <TextView
            android:id="@+id/anti_theft_t9_key_5"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_five"
            android:textIsSelectable="false" />
    
        <TextView
            android:id="@+id/anti_theft_t9_key_6"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_six"
            android:textIsSelectable="false" />
    </TableRow>
    
    <TableRow
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:divider="@android:color/darker_gray"
        android:gravity="center"
        android:showDividers="middle" >
    
        <TextView
            android:id="@+id/anti_theft_t9_key_7"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_seven"
            android:textIsSelectable="false" />
    
        <TextView
            android:id="@+id/anti_theft_t9_key_8"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_eight"
            android:textIsSelectable="false" />
    
        <TextView
            android:id="@+id/anti_theft_t9_key_9"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_nine"
            android:textIsSelectable="false" />
    </TableRow>
    
    <TableRow
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:divider="@android:color/darker_gray"
        android:gravity="center"
        android:showDividers="middle" >
    
        <TextView
            android:id="@+id/anti_theft_t9_key_clear"
            style="@style/anti_theft_t9_key"
            android:text="@string/anti_theft_keyboard_clear"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textIsSelectable="false" />
    
        <TextView
            android:id="@+id/anti_theft_t9_key_0"
            style="@style/anti_theft_t9_key"
            android:text="@string/number_zero"
            android:textIsSelectable="false" />
    
        <ImageView
            android:id="@+id/anti_theft_t9_key_backspace"
            style="@style/anti_theft_t9_key"
            android:contentDescription="@string/app_name_for_anti_theft"
            android:src="@drawable/anti_theft_keyboard_backspace"
            android:textIsSelectable="false" />
    </TableRow>
    
    </TableLayout>
    

    Each key style:

    <style name="anti_theft_t9_key">
        <item name="android:layout_width">0dp</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_weight">1</item>
        <item name="android:paddingTop">@dimen/anti_theft_t9_key_paddingTop</item>
        <item name="android:paddingBottom">@dimen/anti_theft_t9_key_paddingBottom</item>
        <item name="android:clickable">true</item>
        <item name="android:gravity">center</item>
        <item name="android:scaleType">centerInside</item>
        <item name="android:background">@drawable/anti_theft_btn_blue_bg</item>
        <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
    </style>
    

    Responses of each key:

    private EditText mEtPassword ;
    
    private void setViews(){
        // find view references...
        // set OnClickListener to each key view...
    }
    
    private void onT9KeyClicked(int key) {
        switch (key) {
        case R.id.anti_theft_t9_key_0:
            mEtPassword.append("0");
            break;
        case R.id.anti_theft_t9_key_1:
            mEtPassword.append("1");
            break;
        case R.id.anti_theft_t9_key_2:
            mEtPassword.append("2");
            break;
        case R.id.anti_theft_t9_key_3:
            mEtPassword.append("3");
            break;
        case R.id.anti_theft_t9_key_4:
            mEtPassword.append("4");
            break;
        case R.id.anti_theft_t9_key_5:
            mEtPassword.append("5");
            break;
        case R.id.anti_theft_t9_key_6:
            mEtPassword.append("6");
            break;
        case R.id.anti_theft_t9_key_7:
            mEtPassword.append("7");
            break;
        case R.id.anti_theft_t9_key_8:
            mEtPassword.append("8");
            break;
        case R.id.anti_theft_t9_key_9:
            mEtPassword.append("9");
            break;
        case R.id.anti_theft_t9_key_backspace: {
            // delete one character
            String passwordStr = mEtPassword.getText().toString();
            if (passwordStr.length() > 0) {
                String newPasswordStr = new StringBuilder(passwordStr)
                        .deleteCharAt(passwordStr.length() - 1).toString();
                mEtPassword.setText(newPasswordStr);
            }
        }
            break;
        case R.id.anti_theft_t9_key_clear:
            // clear password field
            mEtPassword.setText(null);
            break;
        }
    }