美文网首页
Android 自定义软键盘

Android 自定义软键盘

作者: Double丨铁人 | 来源:发表于2019-03-19 15:52 被阅读0次
    一、 Android 自定义软键盘开发流程
    1. 建立软键盘样式
             即在项目res文件夹中创建所需要的各种软键盘的样式(比如说:字母、数字、符号 等)。
    2. 创建layout布局文件(非必须)
             在布局文件中给软键盘创建container,以便显示软键盘
    3. 自定义KeyboardView
             自定义一个KeyboardView 并继承自KeyboardView,在自定义的KeyboardView中绘制特殊按键,包括按键的点击背景,图片,文字 等。
    4. 自定义一个普通java类,一般取名为 **Keyboard.java
             把软键盘加载到container中,即在布局文件里预留的存放软键盘 的container。
             在类的内部实现软键盘的输入控制,键盘转换控制,软键盘的显示与隐藏控制 等。
             在需要用到软键盘的Activity中实例化该Keyboard 类,并传入必要的数据和信息。
    二、建立软键盘样式

           建立软键盘样式可以直接通过xml进行排版,在res/xml中创建一个根节点为Keyboard的xml就可以开始排版了
    这个xml中属性如下:

    Keyboard.Key 属性 介绍
    android:codes 此键输出的unicode值或逗号分隔值。
    android:horizontalGap 键之间的默认水平间隙。
    android:iconPreview 弹出预览中显示的图标。
    android:isModifier 这是否是修改键,如Alt或Shift。
    android:isRepeatable 是否长按此键会使其重复。
    android:isSticky 这是否是切换键。
    android:keyEdgeFlags 关键边缘标志。
    android:keyHeight 键的默认高度,以像素为单位或显示宽度的百分比。
    android:keyIcon 要在键上显示的图标而不是标签。
    android:keyLabel 要在键上显示的标签。
    android:keyOutputText 按下此键时要输出的字符串。
    android:keyWidth 键的默认宽度,以像素为单位或显示宽度的百分比。
    android:popupCharacters 要在弹出键盘中显示的字符。
    android:popupKeyboard 任何弹出键盘的XML键盘布局。

    实例代码:
    数字键盘

    <?xml version="1.0" encoding="utf-8"?>
    <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
        android:horizontalGap="2.5%p"
        android:keyHeight="6%p"
        android:keyWidth="30%p"
        android:verticalGap="10px">
        <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>
    

    英文键盘:

    <?xml version="1.0" encoding="utf-8"?>
    <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
        android:horizontalGap="1%p"
        android:keyHeight="6%p"
        android:keyWidth="10%p"
        android:verticalGap="10px">
        <Row>
            <Key android:codes="113" android:keyEdgeFlags="left" android:keyLabel="q" android:keyWidth="8.9%p" />
            <Key android:codes="119" android:keyLabel="w" android:keyWidth="8.9%p" />
            <Key android:codes="101" android:keyLabel="e" android:keyWidth="8.9%p" />
            <Key android:codes="114" android:keyLabel="r" android:keyWidth="8.9%p" />
            <Key android:codes="116" android:keyLabel="t" android:keyWidth="8.9%p" />
            <Key android:codes="121" android:keyLabel="y" android:keyWidth="8.9%p" />
            <Key android:codes="117" android:keyLabel="u" android:keyWidth="8.9%p" />
            <Key android:codes="105" android:keyLabel="i" android:keyWidth="8.9%p" />
            <Key android:codes="111" android:keyLabel="o" android:keyWidth="8.9%p" />
            <Key android:codes="112" android:keyEdgeFlags="right" android:keyLabel="p" android:keyWidth="8.9%p" />
        </Row>
        <Row>
            <Key android:codes="97" android:horizontalGap="5.5%p" android:keyEdgeFlags="left" android:keyLabel="a" android:keyWidth="9%p" />
            <Key android:codes="115" android:keyLabel="s" android:keyWidth="9%p" />
            <Key android:codes="100" android:keyLabel="d" android:keyWidth="9%p" />
            <Key android:codes="102" android:keyLabel="f" android:keyWidth="9%p" />
            <Key android:codes="103" android:keyLabel="g" android:keyWidth="9%p" />
            <Key android:codes="104" android:keyLabel="h" android:keyWidth="9%p" />
            <Key android:codes="106" android:keyLabel="j" android:keyWidth="9%p" />
            <Key android:codes="107" android:keyLabel="k" android:keyWidth="9%p" />
            <Key android:codes="108" android:keyEdgeFlags="right" android:keyLabel="l" android:keyWidth="9%p" />
        </Row>
        <Row>
            <Key android:codes="-1" android:isModifier="true" android:isSticky="true" android:keyEdgeFlags="left" android:keyWidth="13%p" />
            <Key android:codes="122" android:horizontalGap="1.5%p" android:keyLabel="z" android:keyWidth="9%p" />
            <Key android:codes="120" android:keyLabel="x" android:keyWidth="9%p" />
            <Key android:codes="99" android:keyLabel="c" android:keyWidth="9%p" />
            <Key android:codes="118" android:keyLabel="v" android:keyWidth="9%p" />
            <Key android:codes="98" android:keyLabel="b" android:keyWidth="9%p" />
            <Key android:codes="110" android:keyLabel="n" android:keyWidth="9%p" />
            <Key android:codes="109" android:keyLabel="m" android:keyWidth="9%p" />
            <Key android:codes="-5" android:horizontalGap="1.5%p" android:isRepeatable="true" android:keyWidth="13%p" />
        </Row>
        <Row android:rowEdgeFlags="bottom">
            <Key android:codes="-2" android:keyLabel="123" android:keyWidth="19%p" />
            <Key android:codes="32" android:isRepeatable="false" android:keyLabel="space" android:keyWidth="58%p" />
            <Key android:codes="100860" android:keyEdgeFlags="right" android:keyLabel="#+=" android:keyWidth="19%p" />
        </Row>
    </Keyboard>
    
    三、自定义KeyboardView

           如果你对KeyboardView的按键有特定的一些样式的话,那你就要自定义KeyboardView了。
           自定义KeyboardView最重要的就是重写onDraw方法,同时注意一定要写绘制背景再绘制文本。List<Keyboard.Key> keys = getKeyboard().getKeys();这个是获取所有按键信息Keyboard.Key,其中Key.codes是获取xml中设定的code,可以根据这个判定需要绘制的样式不同。

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.graphics.Typeface;
    import android.graphics.drawable.Drawable;
    import android.inputmethodservice.Keyboard;
    import android.inputmethodservice.KeyboardView;
    import android.support.annotation.DrawableRes;
    import android.util.AttributeSet;
    
    import java.lang.reflect.Field;
    import java.util.List;
    
    public class CustomKeyboardView extends KeyboardView {
    
        private Context context;
        private Paint paint;
        private Rect bounds;
    
        public CustomKeyboardView(Context context, AttributeSet attrs) {
            super(context, attrs);
            paint = new Paint();
            paint.setTextAlign(Paint.Align.CENTER);
            paint.setAntiAlias(true);
            paint.setColor(Color.BLACK);
            bounds = new Rect();
            this.context = context;
        }
    
        public CustomKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            paint = new Paint();
            paint.setTextAlign(Paint.Align.CENTER);
            paint.setAntiAlias(true);
            paint.setColor(Color.BLACK);
            bounds = new Rect();
            this.context = context;
        }
    
        /**
         * 重写这个方法是为了可以绘制一些特殊按键
         * @param canvas
         */
        @Override
        public void onDraw(Canvas canvas) {
            List<Keyboard.Key> keys = getKeyboard().getKeys();
            for (Keyboard.Key key : keys) {
                if(key.codes[0] != -5 && key.codes[0] != -4){
                    //绘制普通信息文本的背景
                    drawBackground(R.drawable.keyboard_bg,canvas,key);
                    //绘制普通信息的文本信息
                    drawText(canvas,key);
                }else{
                    //绘制特殊按键
                    drawSpecialKey(canvas,key);
                }
            }
        }
    
        private void drawSpecialKey(Canvas canvas, Keyboard.Key key) {
            if(key.codes[0] == -5){
                drawBackground(R.drawable.keyboard_bg,canvas,key);
                //绘制设置了icon的按钮
                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);
            }else if(key.codes[0] == -4){
                drawBackground(R.drawable.white,canvas,key);
            }
        }
    
        private void drawBackground(@DrawableRes int drawableId, Canvas canvas, Keyboard.Key key) {
            Drawable drawable = context.getResources().getDrawable(drawableId);
            int[] state = key.getCurrentDrawableState();
            if (key.codes[0] != 0) {
                drawable.setState(state);
            }
            drawable.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
            drawable.draw(canvas);
        }
    
        //绘制文本
        private void drawText(Canvas canvas, Keyboard.Key key) {
            if(key.label != null){
                String label = key.label.toString();
                Field field;
                int keyTextSize;
                try {
                    //获取KeyboardView设置的默认文本字体大小
                    field = KeyboardView.class.getDeclaredField("mLabelTextSize");
                    field.setAccessible(true);
                    keyTextSize = (int) field.get(this);
                    paint.setTextSize(keyTextSize);
                    paint.setTypeface(Typeface.DEFAULT);
                    paint.getTextBounds(label,0,label.length(),bounds);
                    canvas.drawText(label,key.x + (key.width / 2), (key.y + key.height / 2) + bounds.height() / 2, paint);
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    四、自定义一个KeyBoard的帮助类

    这个类里面主要的作用是使用我们自定义的KeyboardView代替系统自带的KeyboardView进行展示,这里的话主要是需要在EditText获取焦点时候讲弹出软键盘设定成自定义的。

    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.inputmethodservice.Keyboard;
    import android.inputmethodservice.KeyboardView;
    import android.os.Build;
    import android.text.Editable;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.EditText;
    
    public class KeyboardUtil {
    
        private Context mContext;
        private KeyboardView mKeyboardView;
        private EditText mEditText;
    
    
        @SuppressLint("ClickableViewAccessibility")
        public KeyboardUtil(Context context, KeyboardView keyboardView, EditText editText) {
            this.mContext = context;
            this.mKeyboardView = keyboardView;
            this.mEditText = editText;
            initKeyboard();
            mEditText.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        hideSystemKeyboard((EditText) v);
                        mKeyboardView.setVisibility(View.VISIBLE);
                    }
                    return false;
                }
            });
            mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (v instanceof EditText) {
                        if (!hasFocus) {
                            mKeyboardView.setVisibility(View.GONE);
                        } else {
                            hideSystemKeyboard((EditText) v);
                            mKeyboardView.setVisibility(View.VISIBLE);
                        }
                    }
    
                }
            });
        }
    
        private void hideSystemKeyboard(EditText v) {
            this.mEditText = v;
            InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
            if(imm == null){
                return;
            }
            boolean isOpen = imm.isActive();
            if (isOpen) {
                imm.hideSoftInputFromWindow(v.getWindowToken(),0);
            }
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
                v.setShowSoftInputOnFocus(false);
            }else{
                v.setInputType(0);
            }
        }
    
        private void initKeyboard() {
            Keyboard keyboard = new Keyboard(mContext,R.xml.number_keyboard);
            mKeyboardView.setKeyboard(keyboard);
            mKeyboardView.setEnabled(true);
            mKeyboardView.setOnKeyboardActionListener(listener);
        }
    
        private KeyboardView.OnKeyboardActionListener listener = new KeyboardView.OnKeyboardActionListener() {
            @Override
            public void onPress(int primaryCode) {
                if(primaryCode == -4 || primaryCode == -5){
                    mKeyboardView.setPreviewEnabled(false);
                }else{
                    mKeyboardView.setPreviewEnabled(true);
                }
            }
    
            @Override
            public void onRelease(int primaryCode) {
    
            }
    
            @Override
            public void onKey(int primaryCode, int[] keyCodes) {
                Editable editable = mEditText.getText();
                int start = mEditText.getSelectionStart();
                int end = mEditText.getSelectionEnd();
                if(primaryCode == Keyboard.KEYCODE_DONE){
                    mKeyboardView.setVisibility(View.GONE);
                }else if(primaryCode == Keyboard.KEYCODE_DELETE){
                    if(editable != null && editable.length() > 0){
                        if(start == end){
                            editable.delete(start -1, start);
                        }else{
                            editable.delete(start,end);
                        }
                    }
                }else{
                    editable.replace(start,end,Character.toString((char) primaryCode));
                }
            }
    
            @Override
            public void onText(CharSequence text) {
    
            }
    
            @Override
            public void swipeLeft() {
    
            }
    
            @Override
            public void swipeRight() {
    
            }
    
            @Override
            public void swipeDown() {
    
            }
    
            @Override
            public void swipeUp() {
    
            }
        };
    }
    

    以上就是自定义软件盘所有相关的操作,这个是比较简单的,如果要负责的话,就需要多研究下,如果有啥没写好的,见谅一下,第一次写。

    相关文章

      网友评论

          本文标题:Android 自定义软键盘

          本文链接:https://www.haomeiwen.com/subject/wlugmqtx.html