• Android自定义安全键盘


    在银行APP里经常要自定义键盘,例如实现下面这样的效果

     
     
     

    首先在xml文件里定义键盘

    <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
              android:keyWidth="30%p"
              android:horizontalGap="@dimen/keyboard_horizontalGap"
              android:verticalGap="@dimen/keyboard_verticalGap"
              android:keyHeight="47dp">
        <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="-2" android:keyLabel="ABC" />
            <Key android:codes="48" android:keyLabel="0" />
            <Key android:codes="-35"
                android:isRepeatable="true"/>
        </Row>
    </Keyboard>

    keyWidth:每一个按钮的宽度

    keyHeight每一个按钮高度,可以设置百分比

    horizontalGap:水平间隔

    verticalGap:竖直间隔

    Row:一行

    每一个按键都将会有一个 codes 值,代表键盘上的按键

    KhKeyboardView
    public class KhKeyboardView {
        private Activity mContext;
        private View parentView;
        private KeyboardView mLetterView;   //字母键盘view
        private KeyboardView mNumberView;   //数字键盘View
        private Keyboard mNumberKeyboard;   // 数字键盘
        private Keyboard mLetterKeyboard;   // 字母键盘
        private Keyboard mSymbolKeyboard;   // 符号键盘
    
        private boolean isNumber = true;    // 是否数字键盘
        public static   boolean isUpper = false;    // 是否大写
        private boolean isSymbol = false;   // 是否是符号
        private EditText mEditText;
        private View headerView;
    
        public void setEditText(EditText text) {
            mEditText = text;
        }
    
        public KhKeyboardView(Activity context, View view) {
            mContext = context;
            parentView = view;
    
            mNumberKeyboard = new Keyboard(mContext, R.xml.keyboard_numbers);
            mLetterKeyboard = new Keyboard(mContext, R.xml.keyboard_word);
            mSymbolKeyboard = new Keyboard(mContext, R.xml.keyboard_symbol);
            mNumberView = (KeyboardView) parentView.findViewById(R.id.keyboard_view);
            mLetterView = (KeyboardView) parentView.findViewById(R.id.keyboard_view_2);
    
            mNumberView.setKeyboard(mNumberKeyboard);
            mNumberView.setEnabled(true);
            mNumberView.setPreviewEnabled(false);
            mNumberView.setOnKeyboardActionListener(listener);
            mLetterView.setKeyboard(mLetterKeyboard);
            mLetterView.setEnabled(true);
            mLetterView.setPreviewEnabled(true);
            mLetterView.setOnKeyboardActionListener(listener);
            headerView = parentView.findViewById(R.id.keyboard_header);
    
        }
    
        private KeyboardView.OnKeyboardActionListener listener = new KeyboardView.OnKeyboardActionListener() {
            /**
             * 按下,在onKey之前,可以在这里做一些操作,这里让有的没有按下的悬浮提示
             * @param primaryCode
             */
            @Override
            public void onPress(int primaryCode) {
                Log.d("primaryCode","onPress--"+primaryCode);
                if (primaryCode == Keyboard.KEYCODE_SHIFT) {
                    mLetterView.setPreviewEnabled(false);
                } else if (primaryCode == Keyboard.KEYCODE_DELETE) {
                    mLetterView.setPreviewEnabled(false);
                } else if (primaryCode == 32) {
                    mLetterView.setPreviewEnabled(false);
                } else {
                    mLetterView.setPreviewEnabled(true);
                }
    
            }
    
            /**
             * 松开
             * @param primaryCode
             */
            @Override
            public void onRelease(int primaryCode) {
                Log.d("primaryCode","onRelease--"+primaryCode);
            }
    
            /**
             * 按下
             * @param primaryCode
             * @param keyCodes
             */
            @Override
            public void onKey(int primaryCode, int[] keyCodes) {
                Log.d("primaryCode","onKey--"+primaryCode);
                try {
                    if (mEditText == null)
                        return;
                    Editable editable = mEditText.getText();
                    int start = mEditText.getSelectionStart();
                    if (primaryCode == Keyboard.KEYCODE_CANCEL) {
                        // 隐藏键盘
                        hideKeyboard();
                    } else if (primaryCode == Keyboard.KEYCODE_DELETE || primaryCode == -35) {
    
                        // 回退键,删除字符
                        if (editable != null && editable.length() > 0) {
                            if (start > 0) {
                                editable.delete(start - 1, start);
                            }
                        }
                    } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
                        // 大小写切换
                        changeKeyboart();
                        mLetterView.setKeyboard(mLetterKeyboard);
    
                    } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
                        // 数字与字母键盘互换
                        if (isNumber) {
                            showLetterView();
                            showLetterView2();
                        } else {
                            showNumberView();
                        }
    
                    } else if (primaryCode == 90001) {
    //                  字母与符号切换
                        if (isSymbol) {
                            showLetterView2();
                        } else {
                            showSymbolView();
                        }
    
                    } else {
                        // 输入键盘值
                        editable.insert(start, Character.toString((char) primaryCode));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
            }
    
            @Override
            public void onText(CharSequence text) {
    
            }
    
            @Override
            public void swipeLeft() {
    
            }
    
            @Override
            public void swipeRight() {
    
            }
    
            @Override
            public void swipeDown() {
    
            }
    
            @Override
            public void swipeUp() {
    
            }
        };
    
        //  字母-符号,显示字母
        private void showLetterView2() {
            if (mLetterView != null) {
                isSymbol = false;
                mLetterView.setKeyboard(mLetterKeyboard);
            }
        }
    
        //  字母-符号,显示符号
        private void showSymbolView() {
            try {
                if (mLetterKeyboard != null) {
                    isSymbol = true;
                    mLetterView.setKeyboard(mSymbolKeyboard);
                }
            } catch (Exception e) {
            }
        }
    
        //  数字-字母,显示字母键盘
        private void showLetterView() {
            try {
                if (mLetterView != null && mNumberView != null) {
                    isNumber = false;
                    mLetterView.setVisibility(View.VISIBLE);
                    mNumberView.setVisibility(View.INVISIBLE);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        // 数字-字母, 显示数字键盘
        private void showNumberView() {
            try {
                if (mLetterView != null && mNumberView != null) {
                    isNumber = true;
                    mLetterView.setVisibility(View.INVISIBLE);
                    mNumberView.setVisibility(View.VISIBLE);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        /**
         * 切换大小写
         */
        private void changeKeyboart() {
            List<Keyboard.Key> keyList = mLetterKeyboard.getKeys();
            if (isUpper) {
                // 大写切换小写
                isUpper = false;
                for (Keyboard.Key key : keyList) {
                    Drawable icon = key.icon;
    
                    if (key.label != null && isLetter(key.label.toString())) {
                        key.label = key.label.toString().toLowerCase();
                        key.codes[0] = key.codes[0] + 32;
                    }
                }
            } else {
                // 小写切换成大写
                isUpper = true;
                for (Keyboard.Key key : keyList) {
                    if (key.label != null && isLetter(key.label.toString())) {
                        key.label = key.label.toString().toUpperCase();
                        key.codes[0] = key.codes[0] - 32;
                    }
                }
            }
        }
    
        /**
         * 判断是否是字母
         */
        private boolean isLetter(String str) {
            String wordStr = "abcdefghijklmnopqrstuvwxyz";
            return wordStr.contains(str.toLowerCase());
        }
    
        public void hideKeyboard() {
            try {
                int visibility = mLetterView.getVisibility();
                if (visibility == View.VISIBLE) {
                    headerView.setVisibility(View.GONE);
                    mLetterView.setVisibility(View.GONE);
                }
                visibility = mNumberView.getVisibility();
                if (visibility == View.VISIBLE) {
                    headerView.setVisibility(View.GONE);
                    mNumberView.setVisibility(View.GONE);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        /**
         * 显示键盘
         *
         * @param editText
         */
        public void showKeyboard(EditText editText) {
            try {
                this.mEditText = editText;
                int visibility = 0;
                int inputText = mEditText.getInputType();
                headerView.setVisibility(View.VISIBLE);
                switch (inputText) {
                    case InputType.TYPE_CLASS_NUMBER:
                        showNumberView();
                        break;
                    case InputType.TYPE_CLASS_PHONE:
                        showNumberView();
                        break;
                    case InputType.TYPE_NUMBER_FLAG_DECIMAL:
                        showNumberView();
                        break;
                    default:
                        showLetterView();
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    

     

    布局

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/rl_key"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        android:orientation="vertical">
    
        <View
            android:id="@+id/keyboard_back_hide"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#7d7d7d"
            android:orientation="vertical">
    
            <RelativeLayout
                android:id="@+id/keyboard_header"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:visibility="visible">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:text="智能安全加密键盘"
                    android:textColor="#bfbfbf"
                    android:textSize="15sp" />
    
                <TextView
                    android:id="@+id/keyboard_finish"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="10dp"
                    android:padding="14dp"
                    android:text="完成"
                    android:textColor="#ffffff"
                    android:textSize="15sp" />
            </RelativeLayout>
    
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginBottom="10dp"
                android:background="#555457" />
    
            <FrameLayout
                android:id="@+id/keyboard_layer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
    
                <com.kh.keyboard.CustomKeyboardView
                    android:id="@+id/keyboard_view"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#7d7d7d"
                    android:focusable="true"
                    android:focusableInTouchMode="true"
                    android:keyBackground="@drawable/keyboard_number_selector_bg"
                    android:keyPreviewLayout="@null"
                    android:keyTextColor="#ffffff"
                    android:visibility="gone" />
    
                <com.kh.keyboard.CustomKeyboardView
                    android:id="@+id/keyboard_view_2"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#7d7d7d"
                    android:focusable="true"
                    android:focusableInTouchMode="true"
                    android:keyBackground="@drawable/keyboard_selector_bg"
                    android:keyPreviewHeight="90dp"
                    android:keyPreviewLayout="@layout/keyboard_key_preview_layout"
                    android:keyPreviewOffset="45dp"
                    android:keyTextColor="#ffffff"
                    android:visibility="gone" />
            </FrameLayout>
    
        </LinearLayout>
    </RelativeLayout>
    

      

     
    keyPreviewLayout就是点击时键盘按键上的悬浮效果
     
    这里自定义了KeyboardView,因为我需要按钮的背景颜色不一样,而使用keyBackground都是一样的
    public class CustomKeyboardView extends KeyboardView {
        private Context context;
    
        public CustomKeyboardView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context = context;
        }
    
        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            try {
                List<Keyboard.Key> keys = getKeyboard().getKeys();
                for (Keyboard.Key key : keys) {
                    //   Log.e("KEY", "Drawing key with code " + key.codes[0]);
                    if (key.codes[0] == -5) {
                        Drawable dr = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_word_del_layerlist);
                        dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
                        dr.draw(canvas);
                    } else if (key.codes[0] == -35) {
                        Drawable dr = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_word_del_layerlist2);
                        dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
                        dr.draw(canvas);
                    } else if (key.codes[0] == -1) {
                        Drawable dr = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_word_shift_layerlist);
                        Drawable dr_da = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_word_shift_layerlist_da);
                        dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
                        dr_da.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
    
                        if (KhKeyboardView.isUpper) {
                            dr_da.draw(canvas);
                        } else {
                            dr.draw(canvas);
                        }
    
                    } else if (key.codes[0] == -2 || key.codes[0] == 90001) {
                        Drawable dr = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_selector_blue_bg);
                        dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
                        dr.draw(canvas);
                        drawText(canvas, key);
                    } else {
    
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
        private void drawText(Canvas canvas, Keyboard.Key key) {
            try {
                Rect bounds = new Rect();
                Paint paint = new Paint();
                paint.setTextAlign(Paint.Align.CENTER);
    
    
                paint.setAntiAlias(true);
    
                paint.setColor(Color.WHITE);
    
                if (key.label != null) {
                    String label = key.label.toString();
    
                    Field field;
    
                    if (label.length() > 1 && key.codes.length < 2) {
                        int labelTextSize = 0;
                        try {
                            field = KeyboardView.class.getDeclaredField("mLabelTextSize");
                            field.setAccessible(true);
                            labelTextSize = (int) field.get(this);
                        } catch (NoSuchFieldException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        paint.setTextSize(labelTextSize);
                        paint.setTypeface(Typeface.DEFAULT_BOLD);
                    } else {
                        int keyTextSize = 0;
                        try {
                            field = KeyboardView.class.getDeclaredField("mLabelTextSize");
                            field.setAccessible(true);
                            keyTextSize = (int) field.get(this);
                        } catch (NoSuchFieldException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        paint.setTextSize(keyTextSize);
                        paint.setTypeface(Typeface.DEFAULT);
                    }
    
                    paint.getTextBounds(key.label.toString(), 0, key.label.toString()
                            .length(), bounds);
                    canvas.drawText(key.label.toString(), key.x + (key.width / 2),
                            (key.y + key.height / 2) + bounds.height() / 2, paint);
                } else if (key.icon != null) {
                    key.icon.setBounds(key.x + (key.width - key.icon.getIntrinsicWidth()) / 2, key.y + (key.height - key.icon.getIntrinsicHeight()) / 2,
                            key.x + (key.width - key.icon.getIntrinsicWidth()) / 2 + key.icon.getIntrinsicWidth(), key.y + (key.height - key.icon.getIntrinsicHeight()) / 2 + key.icon.getIntrinsicHeight());
                    key.icon.draw(canvas);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
    
        }
    }
     
    最后
    还需要一个工具类来显示自定义的键盘,这里我使用了dialog
    public class KeyBoardDialogUtils implements View.OnClickListener {
        protected View view;
        protected Dialog popWindow;
        protected Activity mContext;
        private EditText contentView;
        private List<String> contentList;
        private KhKeyboardView keyboardUtil;
    
        public KeyBoardDialogUtils(Activity mContext) {
            try {
                this.mContext = mContext;
                if (contentList == null) {
                    contentList = new ArrayList<>();
                }
    
                if (popWindow == null) {
                    view = LayoutInflater.from(mContext).inflate(R.layout.keyboard_key_board_popu, null);
                    view.findViewById(R.id.keyboard_finish).setOnClickListener(this);
                    view.findViewById(R.id.keyboard_back_hide).setOnClickListener(this);
                }
                popWindow.setContentView(view);
                popWindow.setCanceledOnTouchOutside(true);
                Window mWindow = popWindow.getWindow();
                mWindow.setWindowAnimations(R.style.keyboard_popupAnimation);
                mWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
                mWindow.setGravity(Gravity.BOTTOM | Gravity.FILL_HORIZONTAL);
                mWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT);
                popWindow.setOnDismissListener(new DialogInterface.OnDismissListener() {
    
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        if (contentView != null && contentView.isFocused()) {
                            contentView.clearFocus();
                        }
                    }
                });
                initView();
    
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        private void initView() {
            try {
                if (keyboardUtil == null)
                    keyboardUtil = new KhKeyboardView(mContext, view);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
        
    
        public void show(final EditText editText) {
            editText.setFocusable(true);
            editText.setFocusableInTouchMode(true);
            editText.requestFocus();
            popWindow.show();
            keyboardUtil.showKeyboard(editText);
        }
    
        public void dismiss() {
            if (popWindow != null && popWindow.isShowing()) {
                popWindow.dismiss();
    
            }
    
        }
    
        @Override
        public void onClick(View v) {
            try {
                int i = v.getId();
                if (i == R.id.keyboard_finish) {
                    keyboardUtil.hideKeyboard();
                    dismiss();
    
                } else if (i == R.id.keyboard_back_hide) {
                    keyboardUtil.hideKeyboard();
                    dismiss();
    
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
    }
    

      

    使用

            et = (EditText) findViewById(R.id.et);
            keyBoardDialogUtils = new KeyBoardDialogUtils(this);
            et.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    keyBoardDialogUtils.show(et);
                }
            });
    注意这里点击会先弹出系统键盘,因为弹出键盘会先于keyBoardDialogUtils.show(et)执行,所以设置EditText的focusableInTouchMode="false",在keyutil里我们再把它设为true。
     
     
    项目源码:
     
     
     
  • 相关阅读:
    Hibernate配置
    Log4j 局部笔记
    有关接口 笔记 懒人版
    JAVA面向对象编程这本书的摘录~!(2016-5-23)
    关于关闭数据流
    安卓桌面开发小应用
    ACM Sdut 2158 Hello World!(数学题,排序) (山东省ACM第一届省赛C题)
    hdu 1573 A/B (扩展欧几里得)
    hdu 1788 Chinese remainder theorem again(最小公倍数)
    ACM hdu 1019 Least Common Multiple
  • 原文地址:https://www.cnblogs.com/sixrain/p/7793610.html
Copyright © 2020-2023  润新知