自定义数字键盘类似于系统键盘

来源:互联网 发布:紫幽阁小说阅读软件 编辑:程序博客网 时间:2024/05/19 14:18

最近因为项目需求要自定义一个数字键盘,在网上查了些资料但很多功能不全,很多场景不能适应。今天就结合网上的一些资料打算自己写一个键盘。主要适应二种场景:
1、支付密码 需要随机键盘
2、点击EditText能自动向上顶布局
源码下载地址:http://git.oschina.net/shikh/CustomView-master
先看一下使用方法:

<expand.shikh.com.customview.keyboard.NumberKeyBoardEditText        android:layout_alignParentBottom="true"        android:id="@+id/etChar"        android:layout_width="match_parent"        android:layout_height="50dp"        android:layout_marginTop="10dp"        android:background="#ace"        android:gravity="center"        android:hint="数字键盘"        android:singleLine="true"        android:textColor="#ffffff"        android:textColorHint="#ffffff"        mykeyboard:xml="@xml/symbols"        mykeyboard:randomkeys="true"        />

只需引用我们自定义的editText 控件就欧了~
先看一下效果图
这里写图片描述
下面来说说我们的实现方式:
实现软键盘主要用到了系统的两个类Keyboard和KeyboardView:
Keyboard类源码的介绍是: Listener for virtual keyboard events.即用于监听虚拟键盘。至于Keyboard类的映射机制,这里就不需要说了,要分析源码请移驾http://blog.csdn.net/pi9nc/article/details/27304459
1、在res文件下,新建一个xml文件,下面放数字键盘的布局文件

<?xml version="1.0" encoding="utf-8"?><Keyboard xmlns:android="http://schemas.android.com/apk/res/android"    android:horizontalGap="1dp"    android:keyWidth="33.33333%p"    android:verticalGap="1dp">    <Row android:keyHeight="7%p">        <Key android:codes="-3" android:keyIcon="@mipmap/keyboard_back_img" android:keyWidth="100%p" />    </Row>    <Row  android:keyHeight="10%p">        <Key android:codes="55" android:keyLabel="7" />        <Key android:codes="56" android:keyLabel="8" />        <Key android:codes="57" android:keyEdgeFlags="right" android:keyLabel="9" />    </Row>    <Row  android:keyHeight="10%p">        <Key android:codes="52" android:keyLabel="4" />        <Key android:codes="53" android:keyLabel="5" />        <Key android:codes="54" android:keyEdgeFlags="right" android:keyLabel="6" />    </Row>    <Row  android:keyHeight="10%p">        <Key android:codes="49" android:keyLabel="1" />        <Key android:codes="50" android:keyLabel="2" />        <Key android:codes="51" android:keyEdgeFlags="right" android:keyLabel="3" />    </Row>    <Row  android:keyHeight="10%p">        <Key android:codes="4896" android:keyLabel="清空" />        <!--<Key            android:codes="46"            android:keyLabel="." />-->        <Key android:codes="48" android:keyLabel="0" />        <!--<Key android:codes="-3" android:keyEdgeFlags="right" android:keyLabel="OK"/>-->        <!--<key android:codes="4896" android:keylabel="清空" />-->        <Key android:codes="-5" android:keyEdgeFlags="right" android:keyIcon="@mipmap/keyboard_delete_img" />    </Row></Keyboard>

3、创建键盘的工具类KeyboardUtil(显示键盘的主要代码),如下:

public class KeyboardUtil {    private KeyboardView keyboardView;    private Keyboard k;// 数字键盘    private EditText ed;    private Context mContext;    private PopupWindow mKeyboardWindow;    public Keyboard getK() {        return k;    }    public KeyboardView getKeyboardView() {        return keyboardView;    }    public void setmKeyboardWindow(PopupWindow mKeyboardWindow) {        this.mKeyboardWindow = mKeyboardWindow;    }    /**     * 键盘置于布局文件中     * @author shikh     * @time 2016/12/8 上午10:19     */    public KeyboardUtil(Activity atx, EditText edit,int keyId,int xmlId){        this.ed = edit;        this.mContext = atx;        k = new Keyboard(atx, xmlId == 0?R.xml.symbols:xmlId);        keyboardView = (KeyboardView) atx.findViewById(keyId);        initKeyBoard();    }    /**     * 键盘用popwindow 形式打开 结合 numberKeyBoardEditText 使用 具有向上顶布局的功能     * @author shikh     * @time 2016/12/8 上午10:22     */    public KeyboardUtil(Context ctx, EditText edit, int xmlId) {        this.ed = edit;        this.mContext = ctx;        k = new Keyboard(ctx, xmlId == 0?R.xml.symbols:xmlId);        keyboardView = (KeyboardView) View.inflate(ctx,R.layout.layout_keyboard_view,null);    }    public void initKeyBoard(){        keyboardView.setKeyboard(k);        keyboardView.setEnabled(true);        keyboardView.setPreviewEnabled(false);        keyboardView.setVisibility(View.VISIBLE);        keyboardView.setOnKeyboardActionListener(listener);    }    private KeyboardView.OnKeyboardActionListener listener = new KeyboardView.OnKeyboardActionListener() {        @Override        public void swipeUp() {}        @Override        public void swipeRight() {}        @Override        public void swipeLeft() {}        @Override        public void swipeDown() {}        @Override        public void onText(CharSequence text) {}        @Override        public void onRelease(int primaryCode) {}        @Override        public void onPress(int primaryCode) {}        //一些特殊操作按键的codes是固定的比如完成、回退等        @Override        public void onKey(int primaryCode, int[] keyCodes) {            Editable editable = ed.getText();            int start = ed.getSelectionStart();            if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退                if (editable != null && editable.length() > 0) {                    if (start > 0) {                        editable.delete(start - 1, start);                    }                }            } else if (primaryCode == 4896) {// 清空                editable.clear();            } else if (primaryCode == Keyboard.KEYCODE_CANCEL) {//                hideKeyboard();            } else if (primaryCode == 46) { // 小数点                String text = ed.getText().toString();                if (!text.contains(".") && text.length() >0) {                    editable.insert(start, Character.toString((char) primaryCode));                }            } else { //将要输入的数字现在编辑框中                editable.insert(start, Character.toString((char) primaryCode));            }        }    };    /**     * 实应于 键盘布局放置在activity 布局文件中     * @author shikh     * @time 2016/12/8 上午10:08     */    public boolean isShow() {        int visibility = keyboardView.getVisibility();        if (visibility == View.VISIBLE) {            return true;        }        return false;    }    public void showKeyboard() {        int visibility = keyboardView.getVisibility();        if (visibility == View.GONE || visibility == View.INVISIBLE) {            keyboardView.setVisibility(View.VISIBLE);        }    }    public void hideKeyboard() {        if (null != mKeyboardWindow) {            if (mKeyboardWindow.isShowing()) {                mKeyboardWindow.dismiss();            }        }else {            int visibility = keyboardView.getVisibility();            if (visibility == View.VISIBLE) {                keyboardView.setVisibility(View.GONE);            }        }    }    /**     * 隐藏系统键盘     * @author shikh     * @time 2016/12/8 下午3:19     */    public void hideSoftInputMethod(Window mWindow) {        mWindow.setSoftInputMode(                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);        int currentVersion = android.os.Build.VERSION.SDK_INT;        String methodName = null;        if (currentVersion >= 16) {            // 4.2            methodName = "setShowSoftInputOnFocus";        } else if (currentVersion >= 14) {            // 4.0            methodName = "setSoftInputShownOnFocus";        }        if (methodName == null) {            ed.setInputType(InputType.TYPE_NULL);        } else {            Class<EditText> cls = EditText.class;            Method setShowSoftInputOnFocus;            try {                setShowSoftInputOnFocus = cls.getMethod(methodName,                        boolean.class);                setShowSoftInputOnFocus.setAccessible(true);                setShowSoftInputOnFocus.invoke(ed, false);            } catch (NoSuchMethodException e) {                ed.setInputType(InputType.TYPE_NULL);                e.printStackTrace();            } catch (IllegalAccessException e) {                e.printStackTrace();            } catch (IllegalArgumentException e) {                e.printStackTrace();            } catch (InvocationTargetException e) {                e.printStackTrace();            }        }    }}

4、自定义EditText 控件NumberKeyBoardEditText ,实现触摸弹出自定义键盘,先要创建一个 KeyBoardView 布局供 popupWindow使用

<?xml version="1.0" encoding="utf-8"?><android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/keyboard_view"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:layout_alignParentBottom="true"    android:background="#dddddd"    android:focusable="true"    android:focusableInTouchMode="true"    android:keyBackground="@drawable/bg_keyboard_btn"    android:keyTextColor="@color/keyTextColor"    android:keyTextSize="24sp"    android:paddingTop="1dp"    android:shadowRadius="0.0"    android:visibility="gone" />

NumberKeyBoardEditText 类的主要代码

  public NumberKeyBoardEditText(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initAttributes(context);        initKeyBoard(context, attrs);        initPopWindow();    }    private void initKeyBoard(Context context, AttributeSet attrs) {        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.keyboard);        if (a.hasValue(R.styleable.keyboard_xml)) {            needcustomkeyboard = true;            int xmlid = a.getResourceId(R.styleable.keyboard_xml, 0);            keyboardUtil = new KeyboardUtil(context, this, xmlid);        } else {            keyboardUtil = new KeyboardUtil(context, this, 0);        }        if (a.hasValue(R.styleable.keyboard_randomkeys)) {            randomkeys = a.getBoolean(R.styleable.keyboard_randomkeys, false);        }        mKeyboardView = keyboardUtil.getKeyboardView();        mKeyboard = keyboardUtil.getK();        if (randomkeys) {//随机键盘            randomdigkey(mKeyboard);        }        keyboardUtil.initKeyBoard();        a.recycle();    }    private void initPopWindow() {        mKeyboardWindow = new PopupWindow(keyboardUtil.getKeyboardView(), ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);        mKeyboardWindow.setAnimationStyle(R.style.AnimationFade);//设置动画效果,文件在资源里面,这里就不贴出来。</span></strong>        // mKeyboardWindow.setBackgroundDrawable(new BitmapDrawable());        // mKeyboardWindow.setOutsideTouchable(true);        keyboardUtil.setmKeyboardWindow(mKeyboardWindow);        mKeyboardWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {            @Override            public void onDismiss() {                // TODO Auto-generated method stub                if (scrolldis > 0) {                    int temp = scrolldis;                    scrolldis = 0;                    if (null != mContentView) {                        //使布局整体向上顶的关键代码,使用布局的scrollBy重新滚动位置                        mContentView.scrollBy(0, -temp);                    }                }            }        });    }
// 暂时未使用到,为了实现随机键盘布局    private void randomdigkey(Keyboard mKeyboard) {        if (mKeyboard == null) {            return;        }        List<Keyboard.Key> keyList = mKeyboard.getKeys();        // 查找出0-9的数字键        List<Keyboard.Key> newkeyList = new ArrayList<Keyboard.Key>();        for (int i = 0, size = keyList.size(); i < size; i++) {            Keyboard.Key key = keyList.get(i);            CharSequence label = key.label;            if (label != null && isNumber(label.toString())) {                newkeyList.add(key);            }        }        int count = newkeyList.size();        List<KeyModel> resultList = new ArrayList<KeyModel>();        LinkedList<KeyModel> temp = new LinkedList<KeyModel>();        for (int i = 0; i < count; i++) {            temp.add(new KeyModel(48 + i, i + ""));        }        Random rand = new SecureRandom();        rand.setSeed(SystemClock.currentThreadTimeMillis());        for (int i = 0; i < count; i++) {            int num = rand.nextInt(count - i);            KeyModel model = temp.get(num);            resultList.add(new KeyModel(model.getCode(), model.getLable()));            temp.remove(num);        }        for (int i = 0, size = newkeyList.size(); i < size; i++) {            Keyboard.Key newKey = newkeyList.get(i);            KeyModel resultmodle = resultList.get(i);            newKey.label = resultmodle.getLable();            newKey.codes[0] = resultmodle.getCode();        }    }
@Override    public boolean onTouchEvent(MotionEvent event) {        super.onTouchEvent(event);        requestFocus();        requestFocusFromTouch();//        if (needcustomkeyboard) {            hideSysInput();            showKeyboard();//        }        return true;    }    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        if (keyCode == KeyEvent.KEYCODE_BACK) {            if (null != mKeyboardWindow) {                if (mKeyboardWindow.isShowing()) {                    mKeyboardWindow.dismiss();                    return true;                }            }        }        return super.onKeyDown(keyCode, event);    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        this.mWindow = ((Activity) getContext()).getWindow();        this.mDecorView = this.mWindow.getDecorView();        this.mContentView = this.mWindow.findViewById(Window.ID_ANDROID_CONTENT);//        hideSysInput();    }    @Override    public void onDetachedFromWindow() {        super.onDetachedFromWindow();        hideKeyboard();        mKeyboardWindow = null;        mKeyboardView = null;        mKeyboard = null;        mDecorView = null;        mContentView = null;        mWindow = null;    }
0 0
原创粉丝点击