美文网首页编程知识点UIAndroid知识
Android自定义数字键盘(支持随机数字)

Android自定义数字键盘(支持随机数字)

作者: Android_Simon | 来源:发表于2017-09-06 15:58 被阅读175次

    前言

    也是最近想写个demo玩玩,不知道写哪个方面的好,就随便写了一个自定义的键盘,比较简单,但是做了封装,支持jitpack库依赖(这也是我第一次开源自己的库,比较水的一个开源项目,仅供学习使用)。

    概述

    主要完成了以下功能:
    1.自定义数字键盘
    2.切换到随机数字键盘
    3.自定义确定和删除等键(向外抛出接口,感觉设计的挺好)

    下面先看下运行效果吧

    效果图片

    使用方法

    1.在项目build.gradle文件中添加jitpack,添加jitpcak就够了。

    allprojects {
        repositories {
            jcenter()
            maven { url 'https://jitpack.io' }
        }
    }
    

    2.在module 的build.gradle文件添加依赖

      compile 'com.github.Simon986793021:NumberKeyboard:v1.0'
    

    3.在布局文件中添加布局

    <com.wind.keyboard.OfoKeyboardView
            android:id="@+id/keyboard_view"
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:focusable="true"
            android:paddingTop="0dp"
            android:focusableInTouchMode="true"
            android:keyBackground="@drawable/bg_keyboardview"
            android:keyPreviewOffset="0dp"
            android:keyTextColor="#000"
            android:shadowColor="#fff"
            android:shadowRadius="0.0"
            android:layout_alignParentBottom="true"
            />
    

    4.在MainActivity调用。

     editText= (EditText) findViewById(R.id.et_numberplate);
            changebutton= (Button) findViewById(R.id.bt_change_keyboard);
            final OfoKeyboard keyboard = new OfoKeyboard(MainActivity.this);//获取到keyboard对象
            changebutton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    keyboard.attachTo(editText,true);//eiditext绑定keyboard,true表示随机数字
                }
            });
            editText.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    keyboard.attachTo(editText,false);//eiditext绑定keyboard,false表示普通数字键盘
    
                }
            });
            /*
            确定按钮
             */
            keyboard.setOnOkClick(new OfoKeyboard.OnOkClick() {
                @Override
                public void onOkClick() {
                    Log.i(">>>>>>","点击了确定");
                    Toast.makeText(MainActivity.this,editText.getText().toString(),Toast.LENGTH_SHORT).show();
                }
            });
            //隐藏键盘按钮
            keyboard.setOnCancelClick(new OfoKeyboard.OnCancelClcik() {
                @Override
                public void onCancelClick() {
                    Toast.makeText(MainActivity.this,"隐藏键盘",Toast.LENGTH_SHORT).show();
                }
            });
    

    只需要这些简单的代码就能够实现一个自己定义的键盘了。

    实现过程

    1.新建一个keyboard布局

    在看这个代码之前需要了解keyboard的属性:
    不清楚属性,怎么画页面,不懂的请移步这篇博客

    Android键盘属性

    在 res 新建一个xml文件,然后在xml新建一个keyboard.xml

    里面代码如下

    <?xml version="1.0" encoding="utf-8"?>
    <Keyboard
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:keyHeight="9%p"
        android:keyWidth="25%p"
        android:horizontalGap="0dp">
        <Row>
            <Key
                android:codes="49"
                android:keyLabel="1"/>
            <Key
                android:codes="50"
                android:keyLabel="2"/>
            <Key
                android:codes="51"
                android:keyLabel="3"/>
            <Key
                android:codes="-5"
                android:keyHeight="18%p"
                android:keyEdgeFlags="right"
                android:isRepeatable="true"
                android:keyIcon="@drawable/icon_delete_32dp"/>
        </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"/>
            <Key
                android:codes="-4"
                android:keyLabel="确定"
                android:keyEdgeFlags="right"
                android:keyHeight="18%p"/>
        </Row>
        <Row>
            <Key
                android:codes="46"
                android:keyLabel="."/>
            <Key
                android:codes="48"
                android:keyLabel="0"/>
            <Key
                android:codes="-3"
                android:keyIcon="@drawable/icon_hide_keyboard"/>
        </Row>
    </Keyboard>
    

    这个布局就是自己自定义键盘的布局实现,有了布局,显然是不够的。

    2.自定义KeyboardView

    package com.wind.keyboard;
    
    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.util.AttributeSet;
    import android.util.Log;
    
    import java.lang.reflect.Field;
    import java.util.List;
    
    /**
     * Created by zhangcong on 2017/8/24.
     */
    
    public class OfoKeyboardView extends KeyboardView {
        private Context context;
        private Keyboard keyboard;
        public OfoKeyboardView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context=context;
            Log.i(">>>>>","构造函数被调用了");
        }
        /**
         * 重新画一些按键
         */
        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            keyboard = this.getKeyboard();
            List<Keyboard.Key> keys = null;
            if (keyboard != null) {
                keys = keyboard.getKeys();
            }
    
            if (keys != null) {
                for (Keyboard.Key key : keys) {
                    // 数字键盘的处理
                    if (key.codes[0] == -4) {
                        drawKeyBackground(R.drawable.bg_keyboardview_yes, canvas, key);
                        drawText(canvas, key);
                    }
                }
            }
        }
    
        private void drawKeyBackground(int drawableId, Canvas canvas, Keyboard.Key key) {
            Drawable npd = context.getResources().getDrawable(
                    drawableId);
            int[] drawableState = key.getCurrentDrawableState();
            if (key.codes[0] != 0) {
                npd.setState(drawableState);
            }
            npd.setBounds(key.x, key.y, key.x + key.width, key.y
                    + key.height);
            npd.draw(canvas);
        }
    
        private void drawText(Canvas canvas, Keyboard.Key key) {
            Rect bounds = new Rect();
            Paint paint = new Paint();
            paint.setTextAlign(Paint.Align.CENTER);
    
    
            paint.setAntiAlias(true);
    
            paint.setColor(Color.WHITE);
            if (key.label != null) {
                String label = key.label.toString();
    
                Field field;
    
                if (label.length() > 1 && key.codes.length < 2) {
                    int labelTextSize = 0;
                    try {
                        field = KeyboardView.class.getDeclaredField("mLabelTextSize");
                        field.setAccessible(true);
                        labelTextSize = (int) field.get(this);
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    paint.setTextSize(labelTextSize);
                    paint.setTypeface(Typeface.DEFAULT_BOLD);
                } else {
                    int keyTextSize = 0;
                    try {
                        field = KeyboardView.class.getDeclaredField("mLabelTextSize");
                        field.setAccessible(true);
                        keyTextSize = (int) field.get(this);
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    paint.setTextSize(keyTextSize);
                    paint.setTypeface(Typeface.DEFAULT);
                }
    
                paint.getTextBounds(key.label.toString(), 0, key.label.toString()
                        .length(), bounds);
                canvas.drawText(key.label.toString(), key.x + (key.width / 2),
                        (key.y + key.height / 2) + bounds.height() / 2, paint);
            } else if (key.icon != null) {
                key.icon.setBounds(key.x + (key.width - key.icon.getIntrinsicWidth()) / 2, key.y + (key.height - key.icon.getIntrinsicHeight()) / 2,
                        key.x + (key.width - key.icon.getIntrinsicWidth()) / 2 + key.icon.getIntrinsicWidth(), key.y + (key.height - key.icon.getIntrinsicHeight()) / 2 + key.icon.getIntrinsicHeight());
                key.icon.draw(canvas);
            }
    
        }
    }
    
    

    3.KeyBoard的对象的创建:

    package com.wind.keyboard;
    
    import android.app.Activity;
    import android.content.Context;
    import android.inputmethodservice.Keyboard;
    import android.inputmethodservice.KeyboardView;
    import android.os.Build;
    import android.text.Editable;
    import android.text.InputType;
    import android.util.Log;
    import android.view.View;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.EditText;
    
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Random;
    
    /**
     * Created by zhangcong on 2017/8/28.
     */
    
    public class    OfoKeyboard {
        private Activity activity;
        private Keyboard keyboard;
        private OfoKeyboardView keyboardView;
        private EditText editText;
        private boolean isRandom=false;
        public  OfoKeyboard (Activity activity )
        {
            this.activity=activity;
            keyboardView= (OfoKeyboardView) activity.findViewById(R.id.keyboard_view);
        }
        //点击事件触发
        public void attachTo(EditText editText,boolean isRandom){
    
            /*
            切换键盘需要重新new Keyboard对象,否则键盘不会改变,keyboardView放到构造函数里面,避免每次点击重新new 对象,提高性能
             */
            keyboard=new Keyboard(activity,R.xml.keyboard);
            this.isRandom=isRandom;
            Log.i(">>>>>","attachTo");
            this.editText=editText;
            hideSystemSofeKeyboard(activity,editText);
            showSoftKeyboard();
        }
    
    
        private void showSoftKeyboard() {
            if (keyboard == null) {
                keyboard = new Keyboard(activity, R.xml.keyboard);
            }
            if(keyboardView==null)
            {
                keyboardView= (OfoKeyboardView) activity.findViewById(R.id.keyboard_view);
            }
            if (isRandom)
            {
                randomKeyboardNumber();
            }
            else {
                keyboardView.setKeyboard(keyboard);
            }
                keyboardView.setEnabled(true);
                keyboardView.setPreviewEnabled(false);
                keyboardView.setVisibility(View.VISIBLE);
                keyboardView.setOnKeyboardActionListener(listener);
        }
    
        private KeyboardView.OnKeyboardActionListener listener=new KeyboardView.OnKeyboardActionListener() {
            @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();
                if (primaryCode==Keyboard.KEYCODE_DELETE)//key  codes 为-5
                {
                    if (editable!=null&&editable.length()>0)
                    {
                        if (start>0)
                        {
                            editable.delete(start-1,start);
                        }
                    }
                }
                else if (primaryCode==Keyboard.KEYCODE_CANCEL)
                {
                    hideKeyBoard();
                    if (mCancelClick!=null)
                    {
                        mCancelClick.onCancelClick();
                    }
                }
                else if (primaryCode==Keyboard.KEYCODE_DONE)
                {
                    hideKeyBoard();
                    if (mOkClick!=null)
                    {
                        mOkClick.onOkClick();
                    }
                }
               else {
                    Log.i(">>>>>>",primaryCode+"1");
                    Log.i(">>>>>>",(char) primaryCode+"2");
                    editable.insert(start,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() {
    
            }
        };
        public interface OnOkClick {
            void onOkClick();
        }
        public interface OnCancelClcik{
            void onCancelClick();
        }
        public OnOkClick mOkClick;
        public OnCancelClcik mCancelClick;
        public void setOnOkClick(OnOkClick onOkClick)
        {
            this.mOkClick=onOkClick;
        }
        public void setOnCancelClick (OnCancelClcik onCancelClick)
        {
            this.mCancelClick=onCancelClick;
        }
        private void hideKeyBoard() {
            int visibility=keyboardView.getVisibility();
            if (visibility==KeyboardView.VISIBLE)
            {
                keyboardView.setVisibility(KeyboardView.GONE);
            }
        }
        private boolean isNumber(String str) {
            String wordstr = "0123456789";
            return wordstr.contains(str);
        }
    
        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).label.toString())) {
                    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();
            }
         //   hideKeyBoard();
            keyboardView.setKeyboard(keyboard);
        }
    
        /**
         * 隐藏系统键盘
         *
         * @param editText
         */
        public static void hideSystemSofeKeyboard(Context context, EditText editText) {
            Log.i(">>>>>","hide");
            int sdkInt = Build.VERSION.SDK_INT;
            if (sdkInt >= 11) {
                try {
                    Class<EditText> cls = EditText.class;
                    Method setShowSoftInputOnFocus;
                    setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus", boolean.class);
                    setShowSoftInputOnFocus.setAccessible(true);
                    setShowSoftInputOnFocus.invoke(editText, false);
    
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                editText.setInputType(InputType.TYPE_NULL);
            }
            // 如果软键盘已经显示,则隐藏
            InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
        }
    }
    
    

    到这里,自定义键盘就全部完成了。

    总结

    自定义键盘就是通过自定义一个键盘布局,然后通过keyboardView来展示出来。个人感觉没什么需要掌握的,不过可以学习一下代码的封装技巧。

    Github地址

    自定义键盘是比较简单的,但是个人感觉可以看看里面的一些代码封装的技巧,如果你觉得对你有帮助,麻烦来个star吧。

    相关文章

      网友评论

        本文标题:Android自定义数字键盘(支持随机数字)

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