1. 程式人生 > >Android自定義數字驗證碼輸入框

Android自定義數字驗證碼輸入框

先上效果圖

效果圖

設計思路

剛開始想過使用EditText來實現,但是具體實施時發現並不是這麼容易,而且還有一堆的坑,不如直接繼承View自定義來的方便,先在onDraw方法中繪製邊框及驗證碼,調整彈出輸入法只能輸入數字,監聽輸入法輸入,每輸入一個字元都需要重新繪製,另外考慮到擴充套件性需要重寫onMeasure方法來計算View的大小。

具體實現

首先需要在onDraw中繪製外面帶有圓角的矩形邊框以及數字中間的分割線。

/**
 * 繪製邊框及分割線
 *
 * @param canvas
 */
private void drawFrame(Canvas canvas) {
    RectF oval = new
RectF(padding, padding, getWidth() - padding, getHeight() - padding); canvas.drawRoundRect(oval, 10, 10, boxPaint); for (int i = 1; i < count; i++) { canvas.drawLine(padding + boxSize * i, padding, padding + boxSize * i, padding + boxSize, boxPaint); } }

然後再繪製數字驗證碼,每當輸入或刪除文字時都需要呼叫invalidate()方法重新繪製一遍:

Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float fontHeight = fontMetrics.bottom - fontMetrics.top;
    if (textBaseY == 0)
textBaseY = getHeight() - (getHeight() - fontHeight) / 2 - fontMetrics.bottom;
int y = (int) textBaseY;

    if
(!TextUtils.isEmpty(currentNumber)) { if (currentNumber.length() > count) { currentNumber.delete(count, currentNumber.length() - 1); } for (int i = 0; i < currentNumber.length(); i++) { canvas.drawText("" + currentNumber.charAt(i), padding + boxSize * i + (boxSize / 2), y, textPaint); } }

這裡需要設定彈出的輸入法只能輸入數字,如下:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    outAttrs.inputType = InputType.TYPE_CLASS_NUMBER;//定義軟鍵盤樣式為數字鍵盤
    return super.onCreateInputConnection(outAttrs);
}

彈出軟鍵盤之後監聽按鍵輸入:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    //接收按鍵事件,67是刪除鍵(backspace),7-16就是0-9
    if (keyCode == 67 && currentNumber.length() > 0) {
        currentNumber.deleteCharAt(currentNumber.length() - 1);
        //重新繪製
        invalidate();
    } else if (keyCode >= 7 && keyCode <= 16 && currentNumber.length() < count) {
        currentNumber.append(keyCode - 7);
        invalidate();
    }
    return super.onKeyDown(keyCode, event);
}

下面連個方法是開啟輸入法和關閉輸入法,可以設定初始時開啟輸入法:

/**
 * 開啟輸入法
 */
private void showInputMethod() {
    postDelayed(new Runnable() {
        @Override
        public void run() {
            inputMethodManager.viewClicked(NumberInputView.this);
            inputMethodManager.showSoftInput(NumberInputView.this,
                    InputMethodManager.SHOW_FORCED);
        }
    }, 100);
}

/**
 * 關閉輸入法
 */
private void closeInputMethod() {
    post(new Runnable() {
        @Override
        public void run() {
            if (inputMethodManager.isActive()) {
                inputMethodManager.hideSoftInputFromInputMethod(NumberInputView.this.getWindowToken(),
                        0);
            }
        }
    });
}