本篇文章将会介绍3种android自定义软键盘的应用场景以及代码编写,分别是:普通的自定义软键盘;每次弹出都会改变数字顺序的自定义密码键盘;能与webview交互的自定义密码键盘。以上说的这三种其实本质上没有太大区别,只是细节调用和写法上有略微区别,我们项目里用到是最后一种,但是网上对最后一种的介绍很少,这三种自定义软键盘的介绍顺序也是我的推导顺序,第一种是基础,有了基础后续推导会容易很多,如果你暂时用不到后面的可以只看第一种,有些印象就好。

一、普通基础自定义键盘

1.动态效果图:

2.设计思路:

  • 首先在res下创建xml目录,在xml中定义数字键盘和英文键盘;
  • 自定义EditText继承EditText并且实现KeyboardView.OnKeyboardActionListener接口用来监听软键盘的点击事件,从而控制软键盘的切换、预览以及输入框的内容变化;
  • 判断软键盘弹出是否会遮挡输入框,如果会则使得页面上移到不会遮挡为止,软键盘隐藏时注意页面下移相同距离。

3.软键盘的相关属性介绍:

  • key的相关属性:
  • row的相关属性:
  • KeyboardView的相关属性:
  • ASCII码对应表:

4.字母键盘的xml文件编写:

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="8%p"
    android:keyHeight="7.5%p"
    android:verticalGap="0px"
    android:horizontalGap="0px">
    <Row android:verticalGap="1%p">
        <Key
            android:codes="113"
            android:keyLabel="q"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="119"
            android:keyLabel="w"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="101"
            android:keyLabel="e"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="114"
            android:keyLabel="r"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="116"
            android:keyLabel="t"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="121"
            android:keyLabel="y"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="117"
            android:keyLabel="y"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="105"
            android:keyLabel="i"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="111"
            android:keyLabel="o"
            android:horizontalGap="1.81%p">

        </Key>
        <Key
            android:codes="112"
            android:keyLabel="p"
            android:horizontalGap="1.81%p">

        </Key>
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="97"
            android:keyLabel="a"
            android:keyWidth="9%p"
            android:horizontalGap="5.5%p">

        </Key>
        <Key
            android:codes="115"
            android:keyLabel="s"
            android:keyWidth="9%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="100"
            android:keyLabel="d"
            android:keyWidth="9%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="102"
            android:keyLabel="f"
            android:keyWidth="9%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="103"
            android:keyLabel="g"
            android:keyWidth="9%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="104"
            android:keyLabel="h"
            android:keyWidth="9%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="106"
            android:keyLabel="j"
            android:keyWidth="9%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="107"
            android:keyLabel="k"
            android:keyWidth="9%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="108"
            android:keyLabel="l"
            android:keyWidth="9%p"
            android:horizontalGap="1%p">

        </Key>
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="-1"
            android:keyLabel="大写"
            android:keyWidth="17%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="122"
            android:keyLabel="z"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="120"
            android:keyLabel="x"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="99"
            android:keyLabel="c"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="118"
            android:keyLabel="v"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="98"
            android:keyLabel="b"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="110"
            android:keyLabel="n"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="109"
            android:keyLabel="m"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="-5"
            android:isRepeatable="true"
            android:keyIcon="@mipmap/ic_delete"
            android:keyWidth="17%p"
            android:horizontalGap="1%p">

        </Key>
    </Row>
    <Row>
        <Key
            android:codes="-2"
            android:keyLabel="123"
            android:keyWidth="20%p"
            android:horizontalGap="1%p">

        </Key>
        <Key
            android:codes="32"
            android:keyLabel="space"
            android:keyWidth="48%p"
            android:horizontalGap="5%p">

        </Key>
        <Key
            android:codes="-4"
            android:keyLabel="完成"
            android:keyWidth="20%p"
            android:horizontalGap="5%p">

        </Key>
    </Row>
</Keyboard>

5.字母键盘的xml文件编写:

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="7.5%p"
    android:keyWidth="30%p">
    <Row android:verticalGap="1%p">
        <Key
            android:codes="49"
            android:keyLabel="1"
            android:horizontalGap="2%p">

        </Key>
        <Key
            android:codes="50"
            android:keyLabel="2"
            android:horizontalGap="2%p">

        </Key>
        <Key
            android:codes="51"
            android:keyLabel="3"
            android:horizontalGap="2%p">

        </Key>
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="52"
            android:keyLabel="4"
            android:horizontalGap="2%p">

        </Key>
        <Key
            android:codes="53"
            android:keyLabel="5"
            android:horizontalGap="2%p">

        </Key>
        <Key
            android:codes="54"
            android:keyLabel="6"
            android:horizontalGap="2%p">

        </Key>
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="55"
            android:keyLabel="7"
            android:horizontalGap="2%p">

        </Key>
        <Key
            android:codes="56"
            android:keyLabel="8"
            android:horizontalGap="2%p">

        </Key>
        <Key
            android:codes="57"
            android:keyLabel="9"
            android:horizontalGap="2%p">

        </Key>
    </Row>
    <Row>
        <Key
            android:codes="-2"
            android:keyLabel="abc"
            android:horizontalGap="2%p">

        </Key>
        <Key
            android:codes="48"
            android:keyLabel="0"
            android:horizontalGap="2%p">

        </Key>
        <Key
            android:codes="-5"
            android:isRepeatable="true"
            android:keyIcon="@mipmap/ic_delete"
            android:horizontalGap="2%p">

        </Key>
    </Row>
</Keyboard>

6.自定义软键盘相关代码及注释:

package com.example.mycustomkeyboard;

import android.content.Context;
import android.hardware.input.InputManager;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by zd on 2018/4/2.
 */

public class KeyBoardEditText extends AppCompatEditText implements KeyboardView.OnKeyboardActionListener {/**数字键盘*/
    private Keyboard keyboardNumber;
    /**字母键盘*/
    private Keyboard keyboardLetter;
    private ViewGroup viewGroup;
    private KeyboardView keyboardView;

    /**是否发生键盘切换*/
    private boolean changeLetter = false;
    /**是否为大写*/
    private boolean isCapital = false;
    private int[] arrays = new int[]{Keyboard.KEYCODE_SHIFT, Keyboard.KEYCODE_MODE_CHANGE,
            Keyboard.KEYCODE_CANCEL, Keyboard.KEYCODE_DONE, Keyboard.KEYCODE_DELETE,
            Keyboard.KEYCODE_ALT, 32};
    private List<Integer> noLists = new ArrayList<>();
    private OnKeyboardStateChangeListener listener;

    public KeyBoardEditText(Context context) {super(context);
        initEditView();
    }public KeyBoardEditText(Context context, AttributeSet attrs) {super(context, attrs);
        initEditView();
    }public KeyBoardEditText(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);
        initEditView();
    }/**初始化数字和字母键盘*/
    private void initEditView() {keyboardNumber = new Keyboard(getContext(), R.xml.keyboard_num);
        keyboardLetter = new Keyboard(getContext(), R.xml.keyboard_letter);

        for (int i=0; i<arrays.length; i++) {noLists.add(arrays[i]);
        }}/**
     * 设置软键盘刚弹出的时候显示字母键盘还是数字键盘
     * @param vg 包裹KeyboardView的ViewGroup
     * @param kv KeyboardView
     * @param keyboard_num 是否显示数字键盘
     */
    public void setKeyboardType (ViewGroup vg, KeyboardView kv, boolean keyboard_num) {viewGroup = vg;
        keyboardView = kv;
        if (keyboard_num) {keyboardView.setKeyboard(keyboardNumber);
            changeLetter = false;
        } else {keyboardView.setKeyboard(keyboardLetter);
            changeLetter = true;
        }//显示预览
        keyboardView.setPreviewEnabled(true);
        //为KeyboardView设置按键监听
        keyboardView.setOnKeyboardActionListener(this);
    }public void setOnKeyBoardStateChangeListener(OnKeyboardStateChangeListener listener) {this.listener = listener;
    }@Override
    public void onPress(int primaryCode) {canShowPreview(primaryCode);
    }/**
     * 判断是否需要预览Key
     *
     * @param primaryCode keyCode
     */
    private void canShowPreview(int primaryCode) {if (noLists.contains(primaryCode)) {keyboardView.setPreviewEnabled(false);
        } else {keyboardView.setPreviewEnabled(true);
        }}@Override
    public void onRelease(int primaryCode) {}@Override
    public void onKey(int primaryCode, int[] keyCodes) {Editable editable = getText();
        int start = getSelectionStart();
        switch (primaryCode) {case Keyboard.KEYCODE_DELETE://删除
                if (editable != null && editable.length() > 0 && start > 0) {editable.delete(start-1, start);
                }break;
            case Keyboard.KEYCODE_MODE_CHANGE://字母键盘与数字键盘切换
                changeKeyBoard(!changeLetter);
                break;
            case Keyboard.KEYCODE_DONE://完成
                keyboardView.setVisibility(View.GONE);
                viewGroup.setVisibility(GONE);
                if (listener != null) {listener.hide();
                }break;
            case Keyboard.KEYCODE_SHIFT://大小写切换
                changeCapital(!isCapital);
                keyboardView.setKeyboard(keyboardLetter);
                break;
            default:editable.insert(start, Character.toString((char)primaryCode));
                break;
        }}/**切换键盘大小写*/
    private void changeCapital(boolean b) {isCapital = b;
        List<Keyboard.Key> lists = keyboardLetter.getKeys();
        for (Keyboard.Key key: lists) {if (key.label != null && isKey(key.label.toString())) {if (isCapital) {key.label = key.label.toString().toUpperCase();
                    key.codes[0] = key.codes[0] - 32;
                } else  {key.label = key.label.toString().toLowerCase();
                    key.codes[0] = key.codes[0] + 32;
                }} else if (key.label != null && key.label.toString().equals("小写")) {key.label = "大写";
            } else if (key.label != null && key.label.toString().equals("大写")) {key.label = "小写";
            }}}/** * 判断此key是否正确,且存在 * * @param key * @return */
    private boolean isKey(String key) {String lowercase = "abcdefghijklmnopqrstuvwxyz";
        if (lowercase.indexOf(key.toLowerCase()) > -1) {return true;
        }return false;
    }/**切换键盘类型*/
    private void changeKeyBoard(boolean b) {changeLetter = b;
        if (changeLetter) {keyboardView.setKeyboard(keyboardLetter);
        } else {keyboardView.setKeyboard(keyboardNumber);
        }}@Override
    public void onText(CharSequence text) {}@Override
    public void swipeLeft() {}@Override
    public void swipeRight() {}@Override
    public void swipeDown() {}@Override
    public void swipeUp() {}public interface OnKeyboardStateChangeListener {void show();
        void hide();
    }@Override
    public boolean onTouchEvent(MotionEvent event) {hideSystemSoftInput();
        if (event.getAction() == MotionEvent.ACTION_UP) {if (keyboardView.getVisibility() != VISIBLE) {keyboardView.setVisibility(VISIBLE);
                viewGroup.setVisibility(VISIBLE);
                if (listener != null)listener.show();
            }}return true;
    }@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK && (viewGroup.getVisibility() != GONE
        || keyboardView.getVisibility() != GONE)) {viewGroup.setVisibility(GONE);
            keyboardView.setVisibility(GONE);
            if (listener != null)listener.hide();
            return true;
        }return super.onKeyDown(keyCode, event);
    }@Override
    protected void onAttachedToWindow() {super.onAttachedToWindow();
        hideSystemSoftInput();
    }@Override
    protected void onDetachedFromWindow() {super.onDetachedFromWindow();
        hideSystemSoftInput();
    }/**隐藏系统软键盘*/
    private void hideSystemSoftInput() {InputMethodManager manager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        manager.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

7.使用时的页面布局以及调用方法:

  • view_keyboard_preview.xml
  • <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:background="@android:color/holo_red_light"
        android:textColor="@android:color/white"
        android:gravity="center"
        android:textSize="24sp">
    
    </TextView>
  • content_keyboard.xml
  • <?xml version="1.0" encoding="utf-8"?>
    <android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/view_keyboard"
        android:background="#999999"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:keyBackground="@drawable/selector_keyboard_key"
        android:keyPreviewHeight="64dip"
        android:keyPreviewLayout="@layout/view_keyboard_preview"
        android:keyTextColor="@android:color/black"
        android:keyTextSize="24sp"
        android:labelTextSize="18sp"
        android:paddingTop="8dip"
        android:paddingBottom="8dip"
        android:shadowColor="#FFFFFF"
        android:shadowRadius="0.0"
        android:visibility="gone">
    
    </android.inputmethodservice.KeyboardView>
  • activity_main.xml
  • <?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:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:id="@+id/layout_root"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <View
                android:layout_width="match_parent"
                android:layout_height="400dip"></View>
            <com.example.mycustomkeyboard.KeyBoardEditText
                android:id="@+id/ed_main"
                android:layout_width="match_parent"
                android:layout_height="50dip"
                android:background="@android:color/holo_orange_dark"/>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/layout_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_alignParentBottom="true"
            android:background="#999999"
            android:visibility="gone">
            <include layout="@layout/content_keyboard"></include>
        </LinearLayout>
    </RelativeLayout>
    
  • 调用方法和键盘遮挡输入框时的移动内容代码:
  • public class MainActivity extends AppCompatActivity {private KeyBoardEditText text;
        private KeyboardView keyboardView;
        private LinearLayout layout;
        private LinearLayout root;
        private int height = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            text = (KeyBoardEditText) findViewById(R.id.ed_main);
            keyboardView = (KeyboardView) findViewById(R.id.view_keyboard);
            layout = (LinearLayout) findViewById(R.id.layout_main);
            root = (LinearLayout) findViewById(R.id.layout_root);
            text.setKeyboardType(layout, keyboardView, true);
            text.setOnKeyBoardStateChangeListener(new KeyBoardEditText.OnKeyboardStateChangeListener() {@Override
                public void show() {root.post(new Runnable() {@Override
                        public void run() {int[] pos = new int[2];
                            //获取编辑框在整个屏幕中的坐标
                            text.getLocationOnScreen(pos);
                            //编辑框的Bottom坐标和键盘Top坐标的差
                            height = (pos[1] + text.getHeight()) -(getScreenHeight(MainActivity.this) - keyboardView.getHeight());
                            if (height > 0) {root.scrollBy(0, height + dp2px(MainActivity.this, 16));
                            }}});
                }@Override
                public void hide() {if (height > 0) {root.scrollBy(0, -(height + dp2px(MainActivity.this, 16)));
                    }}});
    
            //Log.i("zhangdi", getLngAndLat(this));
        }/**
         * 获得屏幕高度
         *
         * @param context
         * @return
         */
        public static int getScreenHeight(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics displayMetrics = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(displayMetrics);
            return displayMetrics.heightPixels;
        }/**
         * dp转px
         *
         * @param context
         * @param dpVal
         * @return dip
         */
        public static int dp2px(Context context, float dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics());
        }

二、每次弹出都会改变数字顺序的自定义密码键盘

1.动态效果图:

2.设计思路:

  • 在res下创建xml目录,在xml中定义数字键盘;
  • 自定义键盘继承KeyboardView并且实现KeyboardView.OnKeyboardActionListener接口,每次显示键盘的时候使键盘上的数字随机排列显示,用接口回调控制输入框显示;
  • 每次显示的时候判断软键盘是否会遮挡输入框,如果遮挡则使输入框所在部分内容上移,软键盘隐藏的时候把内容移回原位;

3,遇到的问题:

  • 软键盘左右不能都有空隙,如果软键盘左侧有空隙,软键盘宽度不能占满整个屏幕。解决办法:让软键盘左侧有空隙,在软键盘的布局文件外面嵌套一层viewgroup布局,为这个布局设置与软键盘布局相同的底色;
  • 如果在xml里设置‘自定义软键盘’和‘完成’,没办法使得‘自定义软键盘’这几个字居中,也控制不好‘完成’的位置。解决方法:把这两项不写在自定义数字键盘的xml文件里,而是写在页面布局嵌套软键盘布局的viewgroup中。

4.数字键盘的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="7.5%p"
    android:keyWidth="30%p">

    <Row android:verticalGap="1%p">
        <Key
            android:codes="49"
            android:keyLabel="1"
            android:horizontalGap="2.5%p">

        </Key>
        <Key
            android:codes="50"
            android:keyLabel="2"
            android:horizontalGap="2.5%p">

        </Key>
        <Key
            android:codes="51"
            android:keyLabel="3"
            android:horizontalGap="2.5%p">

        </Key>
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="52"
            android:keyLabel="4"
            android:horizontalGap="2.5%p">

        </Key>
        <Key
            android:codes="53"
            android:keyLabel="5"
            android:horizontalGap="2.5%p">

        </Key>
        <Key
            android:codes="54"
            android:keyLabel="6"
            android:horizontalGap="2.5%p">

        </Key>
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="55"
            android:keyLabel="7"
            android:horizontalGap="2.5%p">

        </Key>
        <Key
            android:codes="56"
            android:keyLabel="8"
            android:horizontalGap="2.5%p">

        </Key>
        <Key
            android:codes="57"
            android:keyLabel="9"
            android:horizontalGap="2.5%p">

        </Key>
    </Row>
    <Row android:verticalGap="1%p">
        <Key
            android:codes="-5"
            android:isRepeatable="true"
            android:keyIcon="@mipmap/ic_delete"
            android:horizontalGap="2.5%p">
        </Key>

        <Key
            android:codes="48"
            android:keyLabel="0"
            android:horizontalGap="2.5%p">

        </Key>

        <Key
            android:codes="-3"
            android:keyLabel="隐藏"
            android:horizontalGap="2.5%p">

        </Key>
    </Row>
</Keyboard>

5.自定义数字键盘代码和注释:

package com.example.mycustomkeyboard;

import android.content.Context;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.text.Editable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * Created by zd on 2018/4/24.
 * 自定义键盘在布局文件中须确保在整体布局的底部,不要和输入框在相同的根布局内
 */

public class MyKeyBoardView extends KeyboardView implements KeyboardView.OnKeyboardActionListener {//数字键盘
    private Keyboard keyboard;
    //对应的输入框
    private EditText editText;
    //为防止自定义键盘覆盖输入框,根布局向上的移动高度
    private int height = 0;
    //输入框所在的根布局
    private ViewGroup root;
    //自定义软键盘所在的根布局
    private ViewGroup keyBoardRoot;
    //完成按钮
    private TextView complete;

    public MyKeyBoardView(Context context, AttributeSet attrs) {super(context, attrs);
    }public MyKeyBoardView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);
    }/**
     * 关联自定义键盘与输入框,以及输入框所在的根布局
     * 需要注意此方法需要在输入框的OnTouchListener中当MotionEvent为MotionEvent.ACTION_UP时调用,
     * 否则无法正确阻止系统软键盘的弹出
     * @param et 输入框
     * @param root 输入框所在的根布局
     */
    public void setAttachToEditText(EditText et, ViewGroup root, ViewGroup keyBoardRoot) {if (keyboard == null) {keyboard = new Keyboard(getContext(), R.xml.keyboard_random_num);
        }this.editText = et;
        this.root = root;
        this.keyBoardRoot = keyBoardRoot;
        complete = keyBoardRoot.findViewById(R.id.complete);
        complete.setOnClickListener(new OnClickListener() {@Override
            public void onClick(View v) {hideKeyBoard();
            }});
        editText.requestFocus();
        hideSystemSoftInput();
        showMyKeyBoard();
    }/**显示自定随机数键盘*/
    private void showMyKeyBoard() {randomKeyboardNumber();
        setKeyboard(keyboard);
        setEnabled(true);
        setPreviewEnabled(false);
        showResize();
        keyBoardRoot.setVisibility(VISIBLE);
        setVisibility(VISIBLE);
        setOnKeyboardActionListener(this);
    }/**根据输入框的底部坐标与自定义键盘的顶部坐标之间的差值height,
     * 判断自定义键盘是否覆盖住了输入框,如果覆盖则使输入框所在的根布局移动height*/
    private void showResize() {root.post(new Runnable() {@Override
            public void run() {int[] pos = new int[2];
                //获取编辑框在整个屏幕中的坐标
                editText.getLocationOnScreen(pos);
                //编辑框的Bottom坐标和键盘Top坐标的差
                height = (pos[1] + editText.getHeight()) -(getScreenHeight(getContext()) - keyBoardRoot.getHeight());
                if (height > 0) {root.scrollBy(0, height + dp2px(getContext(), 16));
                }}});
    }/**自定义键盘隐藏时,判断输入框所在的根布局是否向上移动了height,如果移动了则需再移回来*/
    private void hideResize() {if (height > 0) {root.scrollBy(0, -(height + dp2px(getContext(), 16)));
        }}/**获取手机屏幕高度*/
    public static int getScreenHeight(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.heightPixels;
    }/**将px转换成dp*/
    public static int dp2px(Context context, float dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics());
    }/**打乱数字键盘顺序*/
    private void randomKeyboardNumber() {List<Keyboard.Key> keyList = keyboard.getKeys();
        // 查找出0-9的数字键
        List<Keyboard.Key> newkeyList = new ArrayList<Keyboard.Key>();
        for (int i = 0; i < keyList.size(); i++) {if (keyList.get(i).label != null
                    && isNumber(keyList.get(i))) {newkeyList.add(keyList.get(i));
            }}// 数组长度
        int count = newkeyList.size();
        // 结果集
        List<KeyModel> resultList = new ArrayList<KeyModel>();
        // 用一个LinkedList作为中介
        LinkedList<KeyModel> temp = new LinkedList<KeyModel>();
        // 初始化temp
        for (int i = 0; i < count; i++) {temp.add(new KeyModel(48 + i, i + ""));
        }// 取数
        Random rand = new Random();
        for (int i = 0; i < count; i++) {int num = rand.nextInt(count - i);
            resultList.add(new KeyModel(temp.get(num).getCode(),
                    temp.get(num).getLable()));
            temp.remove(num);
        }for (int i = 0; i < newkeyList.size(); i++) {newkeyList.get(i).label = resultList.get(i).getLable();
            newkeyList.get(i).codes[0] = resultList.get(i).getCode();
        }}private class KeyModel {private int code;
        private String lable;

        public KeyModel(int code, String lable) {this.code = code;
            this.lable = lable;
        }public int getCode() {return code;
        }public void setCode(int code) {this.code = code;
        }public String getLable() {return lable;
        }public void setLable(String lable) {this.lable = lable;
        }}/**判断key是数字键还是完成键*/
    private boolean isNumber(Keyboard.Key key) {if (key.codes[0] < 0) {return false;
        }return true;
    }/**隐藏系统键盘*/
    private void hideSystemSoftInput() {InputMethodManager manager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        manager.hideSoftInputFromWindow(editText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }@Override
    public void onPress(int primaryCode) {}@Override
    public void onRelease(int primaryCode) {}@Override
    public void onKey(int primaryCode, int[] keyCodes) {Editable editable = editText.getText();
        //获取焦点光标的所在位置
        int start = editText.getSelectionStart();

        switch (primaryCode) {case Keyboard.KEYCODE_DELETE://删除
                if (editable != null && editable.length() > 0 && start > 0) {editable.delete(start-1, start);
                }break;
            case Keyboard.KEYCODE_DONE://完成
                break;
            case Keyboard.KEYCODE_CANCEL://取消、隐藏
                hideKeyBoard();
                break;
            default://插入数字
                editable.insert(start, Character.toString((char)primaryCode));
        }}/**隐藏键盘*/
    private void hideKeyBoard() {if (getVisibility() == VISIBLE) {keyBoardRoot.setVisibility(GONE);
            setVisibility(GONE);
            hideResize();
        }}@Override
    public void onText(CharSequence text) {}@Override
    public void swipeLeft() {}@Override
    public void swipeRight() {}@Override
    public void swipeDown() {}@Override
    public void swipeUp() {}
}

6.使用时的布局文件和调用方法:

my_keyboard_view.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mykeyboard_root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#999999"
    android:layout_alignParentBottom="true"
    android:visibility="gone">

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="自定义软键盘"
        android:gravity="center"
        android:textSize="18sp"
        android:textColor="@android:color/white"
        android:paddingTop="10dp"/>

    <TextView
        android:id="@+id/complete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="完成"
        android:textSize="18sp"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:textColor="@color/colorPrimary"/>

    <com.example.mycustomkeyboard.MyKeyBoardView
        android:id="@+id/mykeyboard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#999999"
        android:layout_marginTop="10dp"
        android:keyBackground="@drawable/key_drawable"
        android:keyTextColor="@android:color/black"
        android:layout_below="@id/title"
        android:visibility="gone"/>

</RelativeLayout>

activity_main2.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.mycustomkeyboard.Main2Activity">

    <LinearLayout
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <EditText
            android:id="@+id/et1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"/>

        <EditText
            android:id="@+id/et2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"/>

        <EditText
            android:id="@+id/et3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"/>

        <EditText
            android:id="@+id/et4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"/>

        <EditText
            android:id="@+id/et"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"/>

    </LinearLayout>

    <include layout="@layout/my_keyborad_view"/>
</RelativeLayout>

使用方法:

package com.example.mycustomkeyboard;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class Main2Activity extends AppCompatActivity implements View.OnTouchListener {private EditText et;
    private EditText et1;
    private EditText et2;
    private EditText et3;
    private EditText et4;
    private MyKeyBoardView keyBoardView;
    private LinearLayout root;
    private RelativeLayout keyboardRoot;

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        et = (EditText) findViewById(R.id.et);
        et1 = (EditText) findViewById(R.id.et1);
        et2 = (EditText) findViewById(R.id.et2);
        et3 = (EditText) findViewById(R.id.et3);
        et4 = (EditText) findViewById(R.id.et4);
        root = (LinearLayout) findViewById(R.id.root);
        keyBoardView = (MyKeyBoardView) findViewById(R.id.mykeyboard);
        keyboardRoot = (RelativeLayout) findViewById(R.id.mykeyboard_root);
        et.setOnTouchListener(this);
        et1.setOnTouchListener(this);
        et2.setOnTouchListener(this);
        et3.setOnTouchListener(this);
        et4.setOnTouchListener(this);

    }@Override
    public boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_UP) {keyBoardView.setAttachToEditText((EditText) v, root, keyboardRoot);
        }return true;
    }
}

三、能与webview交互的自定义密码键盘

1.动态效果图:

2.设计思路:

  • 与第二种的密码键盘设计思路基本一致,数字键盘的xml文件直接用第二种的就可以,不过软键盘按键控制输入框显示的时候需要调用html中的方法进行显示;
  • 判断软件盘是否遮挡输入框时也需要html传递输入框所在位置参数载进行计算,需要注意的是html中传递的输入框位置是相对于页面左上角的,所以需要减去webview的滑动距离,才能计算出输入框相对于屏幕左上角的位置,才能计算出软键盘是否会遮挡输入框。

3.自定义数字键盘代码以及注释:

package com.example.mycustomkeyboard;

import android.app.Activity;
import android.content.Context;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.text.Editable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * Created by zd on 2018/4/24.
 * 自定义键盘在布局文件中须确保在整体布局的底部,不要和输入框在相同的根布局内
 */

public class MyKeyBoardViewWeb extends KeyboardView implements KeyboardView.OnKeyboardActionListener {//数字键盘
    private Keyboard keyboard;
    //为防止自定义键盘覆盖输入框,根布局向上的移动高度
    private int height = 0;
    //输入框所在的根布局
    private ViewGroup root;
    //自定义软键盘所在的根布局
    private ViewGroup keyBoardRoot;
    //完成按钮
    private TextView complete;
    private WebView web;

    public MyKeyBoardViewWeb(Context context, AttributeSet attrs) {super(context, attrs);
    }public MyKeyBoardViewWeb(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);
    }/**
     * 关联自定义键盘与输入框,以及输入框所在的根布局
     * @param root 输入框所在的根布局
     */
    public void setAttach(WebView web, int height, ViewGroup root, ViewGroup keyBoardRoot) {if (keyboard == null) {keyboard = new Keyboard(getContext(), R.xml.keyboard_random_num);
        }this.web = web;
        this.keyBoardRoot = keyBoardRoot;
        this.root = root;
        complete = keyBoardRoot.findViewById(R.id.complete);
        complete.setOnClickListener(new OnClickListener() {@Override
            public void onClick(View v) {hideKeyBoard();
            }});
        hideSystemSoftInput();
        showMyKeyBoard(height);
    }/**显示自定随机数键盘*/
    private void showMyKeyBoard(int height) {randomKeyboardNumber();
        setKeyboard(keyboard);
        setEnabled(true);
        setPreviewEnabled(false);
        showResize(height);
        keyBoardRoot.setVisibility(VISIBLE);
        setVisibility(VISIBLE);
        setOnKeyboardActionListener(this);
    }/**根据输入框的底部坐标与自定义键盘的顶部坐标之间的差值height,
     * 判断自定义键盘是否覆盖住了输入框,如果覆盖则使输入框所在的根布局移动height*/
    private void showResize(final int h) {root.post(new Runnable() {@Override
            public void run() {//获取屏幕高度
                int screenHeight = getScreenHeight(getContext());
                //获取软键盘高度
                int keyHeight = keyBoardRoot.getMeasuredHeight();
                //获取编辑框底部距离页面顶部的高度
                int etHeight = dp2px(getContext(), h);
                //获取webview的内容滚动距离
                int scrollY = web.getScrollY();
                //编辑框底部高度去除webview内容滚动距离获取编辑框底部与屏幕顶部之间的高度
                // ,与软键盘与屏幕顶部之间的高度差,如果差值大于0则证明软键盘覆盖住编辑框了,需要内容上移。
                height = etHeight - scrollY - (screenHeight - keyHeight);
                if (height > 0) {root.scrollBy(0, height + dp2px(getContext(), 32));
                }}});
    }/**自定义键盘隐藏时,判断输入框所在的根布局是否向上移动了height,如果移动了则需再移回来*/
    private void hideResize() {if (height > 0) {root.scrollBy(0, -(height + dp2px(getContext(), 32)));
        }}/**获取手机屏幕高度*/
    public static int getScreenHeight(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.heightPixels;
    }/**将px转换成dp*/
    public static int dp2px(Context context, float dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics());
    }public static int px2dp(Context context, float dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, dpVal, context.getResources().getDisplayMetrics());
    }/**打乱数字键盘顺序*/
    private void randomKeyboardNumber() {List<Keyboard.Key> keyList = keyboard.getKeys();
        // 查找出0-9的数字键
        List<Keyboard.Key> newkeyList = new ArrayList<Keyboard.Key>();
        for (int i = 0; i < keyList.size(); i++) {if (keyList.get(i).label != null
                    && isNumber(keyList.get(i))) {newkeyList.add(keyList.get(i));
            }}// 数组长度
        int count = newkeyList.size();
        // 结果集
        List<KeyModel> resultList = new ArrayList<KeyModel>();
        // 用一个LinkedList作为中介
        LinkedList<KeyModel> temp = new LinkedList<KeyModel>();
        // 初始化temp
        for (int i = 0; i < count; i++) {temp.add(new KeyModel(48 + i, i + ""));
        }// 取数
        Random rand = new Random();
        for (int i = 0; i < count; i++) {int num = rand.nextInt(count - i);
            resultList.add(new KeyModel(temp.get(num).getCode(),
                    temp.get(num).getLable()));
            temp.remove(num);
        }for (int i = 0; i < newkeyList.size(); i++) {newkeyList.get(i).label = resultList.get(i).getLable();
            newkeyList.get(i).codes[0] = resultList.get(i).getCode();
        }}private class KeyModel {private int code;
        private String lable;

        public KeyModel(int code, String lable) {this.code = code;
            this.lable = lable;
        }public int getCode() {return code;
        }public void setCode(int code) {this.code = code;
        }public String getLable() {return lable;
        }public void setLable(String lable) {this.lable = lable;
        }}/**判断key是数字键还是完成键*/
    private boolean isNumber(Keyboard.Key key) {if (key.codes[0] < 0) {return false;
        }return true;
    }/**隐藏系统键盘*/
    public void hideSystemSoftInput() {InputMethodManager manager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        manager.hideSoftInputFromWindow(((Activity)getContext()).getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }@Override
    public void onPress(int primaryCode) {}@Override
    public void onRelease(int primaryCode) {}@Override
    public void onKey(int primaryCode, int[] keyCodes) {switch (primaryCode) {case Keyboard.KEYCODE_DELETE://删除
                web.loadUrl("javascript:del()");
                break;
            case Keyboard.KEYCODE_DONE://完成
                break;
            case Keyboard.KEYCODE_CANCEL://取消、隐藏
                hideKeyBoard();
                break;
            default://插入数字
                String content = Character.toString((char)primaryCode);
                web.loadUrl("javascript:insert("+content+")");
        }}/**隐藏键盘*/
    private void hideKeyBoard() {if (getVisibility() == VISIBLE) {keyBoardRoot.setVisibility(GONE);
            setVisibility(GONE);
            hideResize();
        }}@Override
    public void onText(CharSequence text) {}@Override
    public void swipeLeft() {}@Override
    public void swipeRight() {}@Override
    public void swipeDown() {}@Override
    public void swipeUp() {}
}

4.使用的html相关代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0 , maximum-scale=1.0, user-scalable=0">

    <title>Show.html</title>

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
<script type="text/javascript">
var name;
function init(s) {name = s;setLoseFocus();sub();
}function setFocus() {//设置焦点var et = document.getElementById(name);et.focus();
}function setLoseFocus() {//取消焦点var et = document.getElementById(name);et.blur();
}function sub(){var et = document.getElementById(name);var height = getPos(et);console.info(height);window.demo.showInput(height);//调用android方法,弹出软键盘<!--console.info("哈哈");-->
}function getPos(o) //取元素坐标
{var y = o.offsetTop;y += o.offsetHeight;return y;
}function del() {//删除var str = document.getElementById(name).value;var strNew = str.substring(0,str.length-1);document.getElementById(name).value = strNew;
}function insert(str) {//插入var s = document.getElementById(name).value;var strNew = s + str;document.getElementById(name).value = strNew;
}
</script>
  </head>

  <body>
  <br/>
  <br/>
  <br/>
  <input type="text" id="txt1" οnclick="init('txt1')" value="">
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <input type="text" id="txt2" οnclick="init('txt2')" value="">
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <input type="text" id="txt" οnclick="init('txt')" value="">
  </body>
</html>

5.使用时的布局以及调用方法:

my_keyboard_view_web.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mykeyboard_root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#999999"
    android:layout_alignParentBottom="true"
    android:visibility="gone">

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="自定义软键盘"
        android:gravity="center"
        android:textSize="18sp"
        android:textColor="@android:color/white"
        android:paddingTop="10dp"/>

    <TextView
        android:id="@+id/complete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="完成"
        android:textSize="18sp"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:textColor="@color/colorPrimary"/>

    <com.example.mycustomkeyboard.MyKeyBoardViewWeb
        android:id="@+id/mykeyboard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#999999"
        android:layout_marginTop="10dp"
        android:keyBackground="@drawable/key_drawable"
        android:keyTextColor="@android:color/black"
        android:layout_below="@id/title"
        android:visibility="gone"/>

</RelativeLayout>

activity_webview.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.mycustomkeyboard.WebviewActivity">

    <RelativeLayout
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <WebView
            android:id="@+id/web"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </RelativeLayout>

    <include layout="@layout/my_keyborad_view_web"/>

</RelativeLayout>

调用方法:

package com.example.mycustomkeyboard;

import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class WebviewActivity extends Activity {private WebView web;
    private MyKeyBoardViewWeb keyBoardView;
    private RelativeLayout root;
    private RelativeLayout keyboardRoot;

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);

        root = (RelativeLayout) findViewById(R.id.root);
        keyBoardView = (MyKeyBoardViewWeb) findViewById(R.id.mykeyboard);
        keyboardRoot = (RelativeLayout) findViewById(R.id.mykeyboard_root);

        web = findViewById(R.id.web);
        web.getSettings().setJavaScriptEnabled(true);
        web.getSettings().setDomStorageEnabled(true);
        web.addJavascriptInterface(new DemoJavaScriptInterface(),"demo");
        web.loadUrl("file:///android_asset/index.html");
    }public class DemoJavaScriptInterface {@JavascriptInterface
        public void showInput(final int height) {runOnUiThread(new Runnable() {@Override
                public void run() {if (keyBoardView.getVisibility() != View.VISIBLE) {keyBoardView.setAttach(web, height, root, keyboardRoot);
                    }}});
        }}
}

最后附上demo下载地址,使用android studio添加moudle可以直接运行看看效果: 下载demo

android自定义软键盘相关推荐

  1. android自定义系统键盘,Android自定义软键盘

    [实例简介] Android自定义软键盘 [实例截图] [核心代码] keydemo └── keydemo ├── AndroidManifest.xml ├── bin │   ├── class ...

  2. Android 自定义软键盘实现 数字九宫格

    前言 最近项目在对接美团外卖功能 实现外面小哥凭取货码取货 对接完功能后 用户反馈 弹出的软键盘 很难输入 数字太小了 大概是下面这种显示方式 需求 组长说 要不搞一个自定义软键盘吧 数字搞大点 方便 ...

  3. Android自定义软键盘输入法,隐藏系统输入法显示光标的实现

    android实现自定义软键盘,先上图看效果,效果基本上是仿ios输入法实现的 这里是实现隐藏系统输入法,同时让EditText能获取光标的代码部分(通过反射调用): <span style=& ...

  4. Android自定义软键盘样式:字母、数字、标点三种切换

    先看效果图: 1.在需要的调用软键盘的activity_mian.xml中加入键盘控件 <!--自定义键盘控件--> <RelativeLayoutandroid:layout_wi ...

  5. android自动软键盘,Android自定义软键盘

    MyKeyboard Android自定义键盘的使用 实现步骤 第一步: 1.新建一个xml文件夹放在res目录下面,然后新建xml文件:money_keyboard.xml 2.然后在XML文件中添 ...

  6. Android 自定义软键盘实现 数字九宫格,2021年Android常见面试题目

    实现效果GIF 实现代码 自定义View 一个NineNumericKeyboardView /** Author by Lyu Date on 2021/5/26-19:55 Description ...

  7. Android 自定义软键盘实现

    module链接:https://download.csdn.net/download/meixi_android/10652565 compile project(':edlibrary') , ' ...

  8. android 自定义软键盘

    哦然间发现了android.inputmethodservice.Keyboard类,即android可以自定义键盘类,做了一个简单例子供大家参考, 首先看看效果图: 键盘内容布局:keyconten ...

  9. android自定义键盘开源,Android自定义软键盘的设计与实现代码

    偶然间发现了Android.inputmethodservice.Keyboard类,即android可以自定义键盘类,做了一个简单例子供大家参考. 效果如下: 先看界面布局文件 android:la ...

  10. Android自定义软键盘的实现

    先看界面布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:and ...

最新文章

  1. IOS的钥匙串,确保本地隐私数据的安全
  2. valgrind——hisi平台valgrind
  3. Android 高级自定义View实战
  4. 八城联动丨神策 2020 数据驱动用户大会「合肥站」邀您免费参会!
  5. Vue 2017 现状与展望 | 视频+PPT+速记快速回顾
  6. 用vim写php,Vim/Neovim中配置PHP的代码调试
  7. 获取项目中的文件流InputStream
  8. java8的新特性详解-----------Lamda表达式
  9. 标题决胜武器:标题常用的14个套路
  10. Mybatis之分表设计与分表插入
  11. 面试中的字符串问题 (1)
  12. Visual studio2010 编写dll 及 使用dll
  13. 全新SQL Server教程
  14. AT89C51单片机8位竞赛抢答器_倒计时可调仿真设计
  15. 深度卷积神经网络(AlexNet)
  16. 新版游戏陪玩约玩APP源码 多人连麦聊天/语音直播社交双端APP源代码 附搭建教程文档
  17. PDF导出图片-python
  18. Linux RHEL/Ubuntu安装教程
  19. echarts将x轴展示在图标上方
  20. matlab通过数据进行曲线拟合 导出公式

热门文章

  1. 学生信息管理系统(附运行效果图和源码下载)分页技术(后台封装json数据传递到前端显示,动态分页等)(Mybatis,json,ajax,jQuery实用整合示例)
  2. Javascript:模拟ztree侧边栏的回收
  3. java 数据库按钮跳转_java,数据库的连接及基本操作
  4. 华为算法精英赛(题3:概率计算)
  5. ubuntu16.04 安装完显卡驱动后分辨率固定640x480 解决
  6. 吴恩达教授机器学习课程笔记【九】- k均值聚类算法
  7. DB2 DatabaseMetadata类的使用
  8. 论文阅读笔记(四)——ESPNetV2:A Light-weight Power Efficient and General Purpose Convolutional Neural Network
  9. Single-Shot Calibration:基于全景基础设施的多相机和多激光雷达之间的外参标定(ICRA2021)...
  10. opencv鼠标回调函数实现ROI区域像素值相同化