Android 仿支付寶數字鍵盤

簡介

在一些帶有支付功能的 App 中,輸入的密碼一般只能是純數字,雖然我們可以指定 EditText 輸入框只能輸入數字,但是爲了提供用戶的使用體驗,我們往往更傾向於使用自定義的純數字鍵盤。

本文效果:

自定義 KeyboardView

實現步驟:

  1. 集成系統的 KeyBoardView 類,在初始化時初始化鍵盤佈局,設置 KeyBoard 對象。
  2. 實現 OnKeyboardActionListener 接口,處理按鍵交互事件。
  3. 根據需求繪製按鍵背景和按鍵圖標。
  4. 設置監聽器,將輸入的內容回調給調用方。

鍵盤佈局

在 res/xml/ 目錄下創建 xml 文件:key_password_number.xml

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="1dp"
    android:keyHeight="9%p"
    android:keyWidth="33.3333%p"
    android:verticalGap="1dp">

    <Row>
        <Key
            android:codes="49"
            android:keyLabel="1" />
        <Key
            android:codes="50"
            android:keyLabel="2" />
        <Key
            android:codes="51"
            android:keyLabel="3" />
    </Row>

    <Row>
        <Key
            android:codes="52"
            android:keyLabel="4" />
        <Key
            android:codes="53"
            android:keyLabel="5" />
        <Key
            android:codes="54"
            android:keyLabel="6" />
    </Row>

    <Row>
        <Key
            android:codes="55"
            android:keyLabel="7" />
        <Key
            android:codes="56"
            android:keyLabel="8" />
        <Key
            android:codes="57"
            android:keyLabel="9" />
    </Row>

    <Row>
        <Key
            android:codes="-10"
            android:keyLabel="" />
        <Key
            android:codes="48"
            android:keyLabel="0" />
        <Key
            android:codes="-5"
            android:keyLabel="" />
    </Row>
</Keyboard>

繼承 KeyBoardView

public class PwdKeyboardView extends KeyboardView implements KeyboardView.OnKeyboardActionListener {

    private static final String TAG = "PwdKeyboardView";

    private static final int KEY_EMPTY = -10;

    private int delKeyBackgroundColor = 0xffcccccc;

    private Rect keyIconRect;


    public PwdKeyboardView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Log.d(TAG, "PwdKeyboardView: two params");
        init(context);

    }

    public PwdKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Log.d(TAG, "PwdKeyboardView: three params");
        init(context);
    }


    private void init(Context context) {
        Keyboard keyboard = new Keyboard(context, R.xml.key_password_number);  // 初始化 keyboard
        setKeyboard(keyboard);
        setEnabled(true);
        setFocusable(true);
        setPreviewEnabled(false);  // 設置點擊按鍵不顯示預覽氣泡
        setOnKeyboardActionListener(this);
    }

    /**
     * 重新繪製刪除按鍵和空白鍵
     *
     * @param canvas
     */
    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        List<Keyboard.Key> keys = getKeyboard().getKeys();
        for (Keyboard.Key key : keys) {
            if (key.codes[0] == KEY_EMPTY) {
                // 繪製空白鍵背景
                drawKeyBackground(key, canvas, delKeyBackgroundColor);
            }
            if (key.codes[0] == Keyboard.KEYCODE_DELETE) {
                // 刪除刪除按鍵背景
                drawKeyBackground(key, canvas, delKeyBackgroundColor);
                // 繪製刪除按鍵圖標
                drawKeyIcon(key, canvas, getResources().getDrawable(R.drawable.ic_delete));
            }
        }

    }

    /**
     * 繪製按鍵的背景
     *
     * @param key
     * @param canvas
     * @param color
     */
    private void drawKeyBackground(Keyboard.Key key, Canvas canvas, int color) {
        ColorDrawable drawable = new ColorDrawable(color);
        drawable.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
        drawable.draw(canvas);
    }

    /**
     * 繪製按鍵的 icon
     *
     * @param key
     * @param canvas
     * @param iconDrawable
     */
    private void drawKeyIcon(Keyboard.Key key, Canvas canvas, Drawable iconDrawable) {
        if (iconDrawable == null) {
            return;
        }
        // 計算按鍵icon 的rect 範圍
        if (keyIconRect == null || keyIconRect.isEmpty()) {
            // 得到 keyicon 的顯示大小,因爲圖片放在不同的drawable-dpi目錄下,顯示大小也不一樣
            int intrinsicWidth = iconDrawable.getIntrinsicWidth();
            int intrinsicHeight = iconDrawable.getIntrinsicHeight();
            int drawWidth = intrinsicWidth;
            int drawHeight = intrinsicHeight;
            // 限制圖片的大小,防止圖片按鍵範圍
            if (drawWidth > key.width) {
                drawWidth = key.width;
                // 此時高就按照比例縮放
                drawHeight = (int) (drawWidth * 1.0f / intrinsicWidth * intrinsicHeight);
            } else if (drawHeight > key.height) {
                drawHeight = key.height;
                drawWidth = (int) (drawHeight * 1.0f / intrinsicHeight * intrinsicWidth);
            }
            // 獲取圖片的 x,y 座標,圖片在按鍵的正中間
            int left = key.x + key.width / 2 - drawWidth / 2;
            int top = key.y + key.height / 2 - drawHeight / 2;
            keyIconRect = new Rect(left, top, left + drawWidth, top + drawHeight);
        }

        if (keyIconRect != null && !keyIconRect.isEmpty()) {
            iconDrawable.setBounds(keyIconRect);
            iconDrawable.draw(canvas);
        }
    }


    @Override
    public void onPress(int primaryCode) {

    }

    @Override
    public void onRelease(int primaryCode) {

    }

    /**
    * 處理按鍵的點擊事件
    */
    @Override
    public void onKey(int primaryCode, int[] keyCodes) {
        Log.d(TAG, "onKey: primaryCode = " + primaryCode + ", keyCodes = " + Arrays.toString(keyCodes));
        if (primaryCode == KEY_EMPTY) {
            return;
        }
        if (listener != null) {
            if (primaryCode == Keyboard.KEYCODE_DELETE) {
                listener.onDelete();
            } else {
                listener.onInput(String.valueOf((char) primaryCode));
            }
        }


    }

    @Override
    public void onText(CharSequence charSequence) {

    }

    @Override
    public void swipeLeft() {

    }

    @Override
    public void swipeRight() {

    }

    @Override
    public void swipeDown() {

    }

    @Override
    public void swipeUp() {

    }

    public interface OnKeyListener {
        // 輸入回調
        void onInput(String text);
       // 刪除回調
        void onDelete();
    }

    private OnKeyListener listener;

    public void setOnKeyListener(OnKeyListener listener) {
        this.listener = listener;
    }

}

使用 PwdKeyboardView

<com.xing.pwdkeyboardview.PwdKeyboardView
        android:id="@+id/key_board"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#919191"
        android:keepScreenOn="true"
        android:keyBackground="@drawable/selector_key_board"    <! --設置按鍵的背景選擇器 -->
        android:keyTextColor="@android:color/black"
        android:keyTextSize="26sp"
        android:shadowRadius="0" />      <!-- shadowRadius = 0 ,防止按鍵數字顯示模糊 --->

顯示結果爲:

keynumber![](C:\Users\Administrator\Desktop\2018-03-25_203243.png)

完整代碼:https://github.com/xing16/PwdKeyboardView

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