自定义软键盘(Android)

去年因公司需要给电视盒子做一个自定义键盘,今天偶然想起来, 想趁此机会记录一下。
当时好像是下载了一个别人的例子,参考着改了一下。具体是哪个作者分享的demo已无法追寻了,先在此表示感谢。
此demo功能中,只能输入英文和常用字符,尚未兼顾输入中文功能。
效果图如下:


自定义软键盘(Android)_第1张图片

自定义软键盘(Android)_第2张图片

1.继承KeyboardView,重写onKeyDown方法:

public class CKeyboardView extends KeyboardView {

    private Keyboard currentKeyboard;
    private List keys = new ArrayList();
    private int lastKeyIndex = 0;
    private Key focusedKey;//当前获取焦点的key
    private Rect rect;//表示包裹当前获取焦点的key的方框

    private int nCurKeyboardKeyNums;//当前键盘的按键数量
    private Keyboard nCurrentKeyboard;
    private List nKeys;//按键集合
    private int nLastKeyIndex = 0;

    public CKeyboardView(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    @Override
    public void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        //获取当前键盘
        currentKeyboard = this.getKeyboard();
        keys = currentKeyboard.getKeys();
        //当前获取焦点的key画方框,表示选中的是当前key
        Paint p = new Paint();
        p.setColor(Color.parseColor("#33ffff"));
        p.setStyle(Style.STROKE);
        p.setStrokeWidth(3.75f);
        focusedKey = keys.get(lastKeyIndex);
        rect = new Rect(focusedKey.x, focusedKey.y + 4, focusedKey.x
                + focusedKey.width, focusedKey.y + focusedKey.height);
        canvas.drawRect(rect, p);
    }

    public int getLastKeyIndex() {
        return lastKeyIndex;
    }

    public void setLastKeyIndex(int lastKeyIndex) {
        this.lastKeyIndex = lastKeyIndex;
    }

    private void setFields() {
        nCurrentKeyboard = this.getKeyboard();
        nKeys = nCurrentKeyboard.getKeys();
        nCurKeyboardKeyNums = nKeys.size();
        nLastKeyIndex = this.getLastKeyIndex();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //Toast.makeText(this.getContext(), "onKeyDown--"+keyCode, Toast.LENGTH_LONG).show();
        Log.d("tag", keyCode + "---" + event.getAction());
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:// 返回 4
                if (event.getRepeatCount() == 0) {
                    if (this.handleBack()) {
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:// 向下 20
                setFields();

                if (nLastKeyIndex >= nCurKeyboardKeyNums - 1) {
                    this.setLastKeyIndex(0);
                } else {
                    int x = nKeys.get(nLastKeyIndex).x;
                    int y = nKeys.get(nLastKeyIndex).y;
                    int[] nearestKeys = nCurrentKeyboard.getNearestKeys(x, y);

                    for (int index : nearestKeys) {
                        if (nLastKeyIndex < index) {
                            Key nearKey = nKeys.get(index);
                            Key lastKey = nKeys.get(nLastKeyIndex);
                            if (((lastKey.x >= nearKey.x) // left side compare
                                    && (lastKey.x < (nearKey.x + nearKey.width)))
                                    || (((lastKey.x + lastKey.width) > nearKey.x) // right
                                    // side
                                    // compare
                                    && ((lastKey.x + lastKey.width) <= (nearKey.x + nearKey.width)))) {
                                this.setLastKeyIndex(index);
                                break;
                            }
                        }
                    }

                }
                this.invalidate();
                return true;
            case KeyEvent.KEYCODE_DPAD_UP:// 向上19
                setFields();

                if (nLastKeyIndex <= 0) {
                    this.setLastKeyIndex(nCurKeyboardKeyNums - 1);
                } else {
                    int x = nKeys.get(nLastKeyIndex).x;
                    int y = nKeys.get(nLastKeyIndex).y;
                    int[] nearestKeys = nCurrentKeyboard.getNearestKeys(x, y);

                    for (int i = nearestKeys.length - 1; i >= 0; i--) {
                        int index = nearestKeys[i];
                        if (nLastKeyIndex > index) {
                            Key nearKey = nKeys.get(index);
                            Key nextNearKey = nKeys.get(index + 1);
                            Key lastKey = nKeys.get(nLastKeyIndex);
                            if ((lastKey.x >= nearKey.x && lastKey.x < (nearKey.x + nearKey.width))
                                    && ((lastKey.x + lastKey.width) <= (nextNearKey.x + nextNearKey.width) || lastKey.x
                                    + lastKey.width > nextNearKey.x)) {
                                this.setLastKeyIndex(index);
                                break;
                            }
                        }
                    }
                }
                this.invalidate();
                return true;
            case KeyEvent.KEYCODE_DPAD_LEFT:// 左21
                setFields();

                if (nLastKeyIndex <= 0) {
                    this.setLastKeyIndex(nCurKeyboardKeyNums - 1);
                } else {
                    nLastKeyIndex--;
                    this.setLastKeyIndex(nLastKeyIndex);
                }
                this.invalidate();
                return true;
            case KeyEvent.KEYCODE_DPAD_RIGHT:// 右22

                setFields();
                if (nLastKeyIndex >= nCurKeyboardKeyNums - 1) {
                    this.setLastKeyIndex(0);
                } else {
                    nLastKeyIndex++;
                    this.setLastKeyIndex(nLastKeyIndex);
                }
                this.invalidate();
                return true;
            case KeyEvent.KEYCODE_ENTER://66
            case KeyEvent.KEYCODE_DPAD_CENTER://23
                setFields();
                int currentKeyCode = nKeys.get(nLastKeyIndex).codes[0];

                switch (currentKeyCode) {
                    case Keyboard.KEYCODE_MODE_CHANGE:
                    case Keyboard.KEYCODE_CANCEL:
                    case Keyboard.KEYCODE_DELETE:
                    case Keyboard.KEYCODE_SHIFT:
                        getOnKeyboardActionListener().onKey(currentKeyCode, null);
                        return true;

                    default:
                        getOnKeyboardActionListener().onKey(currentKeyCode, null);
                        return true;
                }
        }
        return super.onKeyDown(keyCode, event);
    }
}

2.创建2个xml,表示字母键盘和符号数字键盘。
qwenty.xml



           
    
                       
        

        
                       
        
                       
        

        

        

        
                       
        
        
                       
        
    

    
        

        
                       
        

        
                       
        

        
                       
        
                       
        
                       
        
    

    
        

        
                       
        

        

        
                       
        

        
                       
        

        
               
    
           
    
                       
        

        

        
                       
        
                       
        
    


symbols.xml




    
        
        
 
        
        
  
        
        
        
        
        
        
    

    
        
        
        
        
        
        
        
        
        
        
    
    
        
        
        
        
        
        
        
        
        
        
    
    
        
                
        

        
        

        
        

        
    


3.创建KeyboardUtil,控制键盘

public class KeyboardUtil {

    private Context context;
    private KeyboardView keyboardView;
    private Keyboard kQwerty;//字母键盘
    private Keyboard kSymbols;//符号键盘
    private boolean isNum = false;//是否是数字
    private boolean isSupper = false;//是否大写
    private EditText editText;
    private boolean isShown = false;

    /**
     * 构造方法
     *
     * @param context  上下文
     * @param editText 需要输入的EditView
     * @param pView    KeyboardView所在的父控件
     */
    public KeyboardUtil(Context context, EditText editText, View pView) {
        this.context = context;
        this.editText = editText;
        //创建字母和符号键盘
        kQwerty = new Keyboard(context, R.xml.qwerty);
        kSymbols = new Keyboard(context, R.xml.symbols);
        //找到KeyboardView
        this.keyboardView = (KeyboardView) pView
                .findViewById(R.id.keyboard_view);
        this.keyboardView.setKeyboard(kQwerty);
        this.keyboardView.setEnabled(true);
        this.keyboardView.setPreviewEnabled(false);
        this.keyboardView.setOnKeyboardActionListener(listener);
    }

    //Keyboard监听
    OnKeyboardActionListener listener = new OnKeyboardActionListener() {

        @Override
        public void swipeUp() {
            // TODO Auto-generated method stub

        }

        @Override
        public void swipeRight() {
            // TODO Auto-generated method stub

        }

        @Override
        public void swipeLeft() {
            // TODO Auto-generated method stub

        }

        @Override
        public void swipeDown() {
            // TODO Auto-generated method stub

        }

        @Override
        public void onText(CharSequence text) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onRelease(int primaryCode) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onPress(int primaryCode) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onKey(int primaryCode, int[] keyCodes) {
            // Toast.makeText(context, "onKey--"+primaryCode,
            // Toast.LENGTH_LONG).show();

            Editable editable = editText.getText();
            int start = editText.getSelectionStart();

            if (primaryCode == Keyboard.KEYCODE_CANCEL) {
                // 取消,隐藏键盘
                hideKeyboard();
            } else if (primaryCode == Keyboard.KEYCODE_DELETE) {
                // 删除回退
                if (editable != null && editable.length() > 0) {
                    if (start > 0) {
                        editable.delete(start - 1, start);
                    }
                }
            } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
                // 大小写切换
                changeKey();
                keyboardView.setKeyboard(kQwerty);
            } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
                ((CKeyboardView) keyboardView).setLastKeyIndex(0);
                // 数字键盘切换
                if (isNum) {
                    keyboardView.setKeyboard(kQwerty);
                } else {
                    keyboardView.setKeyboard(kSymbols);
                }
                isNum = !isNum;
            } else {
                editable.insert(start, Character.toString((char) primaryCode));
            }

        }
    };

    public KeyboardView getKeyboardView() {
        return keyboardView;
    }

    public EditText getEditText() {
        return editText;
    }

    public void setEditText(EditText editText) {
        this.editText = editText;
    }

    //变换大小写
    private void changeKey() {
        List keys = kQwerty.getKeys();

        for (Key key : keys) {
            if (key.label != null && isWord(String.valueOf(key.label))) {
                if (isSupper) {// up to low
                    key.label = key.label.toString().toLowerCase();
                    key.codes[0] = key.codes[0] + 32;
                } else {
                    key.label = key.label.toString().toUpperCase();
                    key.codes[0] = key.codes[0] - 32;
                }
            }
        }

        isSupper = !isSupper;

    }

    private boolean isWord(String s) {
        String reg = "[a-zA-Z]{1}";
        return s.matches(reg);
    }
    //显示键盘
    public void showKeyboard() {
        int visibility = keyboardView.getVisibility();
        if (visibility == View.GONE || visibility == View.INVISIBLE) {
            keyboardView.setVisibility(View.VISIBLE);
            setShown(true);
        }
    }
    //隐藏键盘
    public void hideKeyboard() {
        if (keyboardView.getVisibility() == View.VISIBLE) {
            keyboardView.setVisibility(View.GONE);
            setShown(false);
        }
    }

    public boolean isShown() {
        return isShown;
    }

    public void setShown(boolean isShown) {
        this.isShown = isShown;
    }

}

4.在布局中使用KeyboardView,在Activity中调用



    

    

        
        
    


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private KeyboardUtil keyboardUtil;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View view = LayoutInflater.from(this).inflate(R.layout.activity_main, null);
        setContentView(view);
        EditText editText = (EditText) findViewById(R.id.edit);
        editText.setOnClickListener(this);

        keyboardUtil = new KeyboardUtil(this, editText, view);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.edit:
                if (keyboardUtil.isShown()
                        && keyboardUtil.getEditText().getId() == v.getId()) {
                    keyboardUtil.hideKeyboard();
                } else {
                    keyboardUtil.setEditText((EditText) v);
                    keyboardUtil.showKeyboard();
                }
                break;
        }
    }

    @Override
    public void onBackPressed() {
        // 如果输入法显示,则隐藏输入法,不关闭PopupWindow
        if (keyboardUtil != null && keyboardUtil.isShown()) {
            keyboardUtil.hideKeyboard();
        } else {
            super.onBackPressed();
        }
    }
}

demo地址

你可能感兴趣的:(自定义软键盘(Android))