學習筆記-自定義密碼輸入框和自定義數字密碼軟鍵盤
阿新 • • 發佈:2019-02-04
最近專案裡有一個支付功能,需要自定義鍵盤,於是我在網上搜了一下,發現這個和我需求很相符,等專案完工,打算分享給大家,卻找不到專案的博主了,這裡還是感謝博主,我就直接貼程式碼分享給大家了;
程式碼裡面就是在鍵盤監聽下進行自己的操作就OK了;
然後是密碼輸入框控制元件GridPasswordView , 非常強大, Github地址;使用起來也很方便;
自定義屬性如下:
XNumberKeyboardView.java
layout.xmlimport android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; import android.util.AttributeSet; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * 數字鍵盤。 * * @author wuzhen */ public class XNumberKeyboardView extends KeyboardView implements KeyboardView.OnKeyboardActionListener { // 用於區分左下角空白的按鍵 private static final int KEYCODE_EMPTY = -10; private int mDeleteWidth; private int mDeleteHeight; private int mDeleteBackgroundColor; private Drawable mDeleteDrawable; private Rect mDeleteDrawRect; private IOnKeyboardListener mOnKeyboardListener; public XNumberKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public XNumberKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs, defStyleAttr); } private void init(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.XNumberKeyboardView, defStyleAttr, 0); mDeleteDrawable = a.getDrawable(R.styleable.XNumberKeyboardView_xnkv_deleteDrawable); mDeleteBackgroundColor = a.getColor( R.styleable.XNumberKeyboardView_xnkv_deleteBackgroundColor, Color.TRANSPARENT); mDeleteWidth = a.getDimensionPixelOffset(R.styleable.XNumberKeyboardView_xnkv_deleteWidth, -1); mDeleteHeight = a.getDimensionPixelOffset(R.styleable.XNumberKeyboardView_xnkv_deleteHeight, -1); a.recycle(); // 設定軟鍵盤按鍵的佈局 Keyboard keyboard = new Keyboard(context, R.xml.keyboard_number); setKeyboard(keyboard); setEnabled(true); setPreviewEnabled(false); // 設定按鍵沒有點選放大鏡顯示的效果 setOnKeyboardActionListener(this); } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); // 遍歷所有的按鍵 List<Keyboard.Key> keys = getKeyboard().getKeys(); for (Keyboard.Key key : keys) { // 如果是左下角空白的按鍵,重畫按鍵的背景 if (key.codes[0] == KEYCODE_EMPTY) { drawKeyBackground(key, canvas, mDeleteBackgroundColor); } // 如果是右下角的刪除按鍵,重畫按鍵的背景,並且繪製刪除圖示 else if (key.codes[0] == Keyboard.KEYCODE_DELETE) { drawKeyBackground(key, canvas, mDeleteBackgroundColor); drawDeleteButton(key, canvas); } } } // 繪製按鍵的背景 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); } // 繪製刪除按鍵 private void drawDeleteButton(Keyboard.Key key, Canvas canvas) { if (mDeleteDrawable == null) { return; } // 計算刪除圖示繪製的座標 if (mDeleteDrawRect == null || mDeleteDrawRect.isEmpty()) { int drawWidth, drawHeight; int intrinsicWidth = mDeleteDrawable.getIntrinsicWidth(); int intrinsicHeight = mDeleteDrawable.getIntrinsicHeight(); if (mDeleteWidth > 0 && mDeleteHeight > 0) { drawWidth = mDeleteWidth; drawHeight = mDeleteHeight; } else if (mDeleteWidth > 0 && mDeleteHeight <= 0) { drawWidth = mDeleteWidth; drawHeight = drawWidth * intrinsicHeight / intrinsicWidth; } else if (mDeleteWidth <= 0 && mDeleteHeight > 0) { drawHeight = mDeleteHeight; drawWidth = drawHeight * intrinsicWidth / intrinsicHeight; } else { drawWidth = intrinsicWidth; drawHeight = intrinsicHeight; } // 限制圖示的大小,防止圖示超出按鍵 if (drawWidth > key.width) { drawWidth = key.width; drawHeight = drawWidth * intrinsicHeight / intrinsicWidth; } if (drawHeight > key.height) { drawHeight = key.height; drawWidth = drawHeight * intrinsicWidth / intrinsicHeight; } // 獲取刪除圖示繪製的座標 int left = key.x + (key.width - drawWidth) / 2; int top = key.y + (key.height - drawHeight) / 2; mDeleteDrawRect = new Rect(left, top, left + drawWidth, top + drawHeight); } // 繪製刪除的圖示 if (mDeleteDrawRect != null && !mDeleteDrawRect.isEmpty()) { mDeleteDrawable.setBounds(mDeleteDrawRect.left, mDeleteDrawRect.top, mDeleteDrawRect.right, mDeleteDrawRect.bottom); mDeleteDrawable.draw(canvas); } } @Override public void onKey(int primaryCode, int[] keyCodes) { // 處理按鍵的點選事件 // 點選了刪除按鍵 if (primaryCode == Keyboard.KEYCODE_DELETE) { if (mOnKeyboardListener != null) mOnKeyboardListener.onDeleteKeyEvent(); } // 點選了數字按鍵 else if (primaryCode != KEYCODE_EMPTY) { if (mOnKeyboardListener != null) { mOnKeyboardListener.onInsertKeyEvent(Character.toString( (char) primaryCode)); } } } // 0-9 數字的 Character 值 private final List<Character> keyCodes = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); /** * 隨機打亂數字鍵盤上鍵位的排列順序。 */ public void shuffleKeyboard() { Keyboard keyboard = getKeyboard(); if (keyboard != null && keyboard.getKeys() != null && keyboard.getKeys().size() > 0) { Collections.shuffle(keyCodes); // 隨機排序數字 // 遍歷所有的按鍵 List<Keyboard.Key> keys = getKeyboard().getKeys(); int index = 0; for (Keyboard.Key key : keys) { // 如果按鍵是數字 if (key.codes[0] != KEYCODE_EMPTY && key.codes[0] != Keyboard.KEYCODE_DELETE) { char code = keyCodes.get(index++); key.codes[0] = code; key.label = Character.toString(code); } } setKeyboard(keyboard); } } @Override public void onPress(int primaryCode) { } @Override public void onRelease(int primaryCode) { } @Override public void onText(CharSequence text) { } @Override public void swipeLeft() { } @Override public void swipeRight() { } @Override public void swipeDown() { } @Override public void swipeUp() { } /** * 設定鍵盤的監聽事件。 * * @param listener 監聽事件 */ public void setIOnKeyboardListener(IOnKeyboardListener listener) { this.mOnKeyboardListener = listener; } /** * 鍵盤的監聽事件。 */ public interface IOnKeyboardListener { /** * 點選數字按鍵。 * * @param text 輸入的數字 */ void onInsertKeyEvent(String text); /** * 點選了刪除按鍵。 */ void onDeleteKeyEvent(); } }
自定義屬性檔案<com.shanlin.autostore.view.XNumberKeyboardView android:id="@+id/view_keyboard" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="#E1E1E1" android:focusable="true" android:focusableInTouchMode="true" android:keyBackground="@drawable/selector_key_bg" android:keyTextColor="#000000" android:shadowColor="@android:color/transparent" android:shadowRadius="0" app:xnkv_deleteBackgroundColor="#E0E0E0" app:xnkv_deleteDrawable="@mipmap/delete" app:xnkv_deleteWidth="22dp" />
在res 目錄下新建一個xml 資料夾,放軟鍵盤資原始檔 keyboard_num.xml<declare-styleable name="XNumberKeyboardView"> <!-- 刪除按鍵的圖示 --> <attr name="xnkv_deleteDrawable" format="reference"/> <!-- 刪除按鍵圖示的寬度 --> <attr name="xnkv_deleteWidth" format="dimension|reference"/> <!-- 刪除按鍵圖示的高度 --> <attr name="xnkv_deleteHeight" format="dimension|reference"/> <!-- 刪除按鍵圖示的顏色 --> <attr name="xnkv_deleteBackgroundColor" format="color|reference"/> </declare-styleable>
<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:keyIcon="@android:color/transparent" />
</Row>
</Keyboard>
程式碼裡面就是在鍵盤監聽下進行自己的操作就OK了;
然後是密碼輸入框控制元件GridPasswordView , 非常強大, Github地址;使用起來也很方便;
自定義屬性如下:
<declare-styleable name="gridPasswordView">
<attr name="gpvTextColor" format="color|reference"/>
<attr name="gpvTextSize" format="dimension"/>
<attr name="gpvLineColor" format="color"/>
<attr name="gpvGridColor" format="color"/>
<attr name="gpvLineWidth" format="dimension"/>
<attr name="gpvPasswordLength" format="integer"/>
<attr name="gpvPasswordTransformation" format="string"/>
<attr name="gpvPasswordType" format="enum">
<enum name="numberPassword" value="0"/>
<enum name="textPassword" value="1"/>
<enum name="textVisiblePassword" value="2"/>
<enum name="textWebPassword" value="3"/>
</attr>
</declare-styleable>