Android 实现密码键盘的相关知识点

一、前言

       由于我们是做金融相关的,对账户的密码输入为了安全,实现相应的保护测试,决定自己实现密码键盘替代系统的自带输入键盘。为什么要使用密码安全键盘呢,出于以下几个原因:

       1. 第三方的键盘输入密码, 这个密码会被输入法缓存起来, 不安全,完全暴露给第三方。
       2. 由于android的root过后,可以通过读取系统驱动层dev/input/event1中的信息,获取手机触屏的位置坐标等信息,从而获取相应的信息。
       我们出于上面两个原因我们可以使用自定义view实现或者通过popwindow、dialog等实现密码键盘,这个看大家自由选择。虽然这种做法是自定义的软键盘,依然会在event1文件中写入触摸信息,因此为了保证输入更加安全,采用随机键盘。做出的一个样子大概是这样的,先给大家看看效果。

        这里写图片描述

       这个界面有点丑,不过今天的重点不是界面,而是功能。

二、实现密码键盘

1.关键问题

       实现密码键盘我们首先有以下几个问题解决,其它的问题都是小问题:
       1.实现0-9数字随机排列
       2.关闭系统键盘,在输入密码的时候禁止弹出
       3.如果输入框在下面,弹出的密码键盘挡住了输入框,如何像系统键盘一样将布局上移,键盘在输入框的下方

       我们先看看上面的几个问题,实现数字随机排列然后并赋值到按钮上,这个还是相对简单,我们取10个随机数,从0-9中取,并不能出现重复的数字,然后赋值即可:

 private int[] getRandomNum() {
        Random random = new Random();
        int[] data = new int[10];
        boolean b;
        boolean b2 = false;
        boolean b3 = true;
        int x;
        for (int i = 0; i < 10; i++) {
            b = true;
            while (b) {
                x = random.nextInt(10);
                if (x == 0 && b3) {
                    b3 = false;
                    b = false;
                }
                for (int y : data) {
                    if (y == x) {
                        b2 = false;
                        break;
                    } else {
                        b2 = true;
                    }
                }
                if (b2) {
                    data[i] = x;
                    b = false;
                    break;
                }
            }
        }
        return data;
    }

       上面就实现了0-9随机生成的数字,这个方法也有很多,我给出了一个大家参考。
       针对第二个问题禁止弹出系统键盘,我们可以这样设置:

setInputType(InputType.TYPE_NULL);

       这个方法意思是输入类型为没有指定明确的类型的特殊内容类型,系统键盘不会弹出,但是在android4.0以上光标不显示,在android4.0以上我们要用反射修改值,代码来源于网上:

public void hideSoftInputMethod(EditText ed) {
        if (android.os.Build.VERSION.SDK_INT <= 10) {//4.0以下
            ed.setInputType(InputType.TYPE_NULL);
        } else {
            activity.getWindow().setSoftInputMode(
                    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
            try {
                Class<EditText> cls = EditText.class;
                Method setShowSoftInputOnFocus;
                setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus",
                        boolean.class);
                setShowSoftInputOnFocus.setAccessible(true);
                setShowSoftInputOnFocus.invoke(ed, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

       现在这样就是有光标的,但是我们在设置popwindow相关属性的时候,this.setFocusable(false); 不然光标一直不闪烁,如果设置为true,点击外面直接关闭系统键盘,不过用户又点击输入框键盘又弹出来了,正确的做法是,当键盘弹出时,点击输入框应该是不弹出键盘,这种用户体验感觉也不是很好。通过判断popwindow是否显示在屏幕上来决定是否弹出密码键盘,这个感觉是可以的,但是我们popwindow设置焦点为false的时候,popwindow的keyPopwindow.isShowing() 在对输入框监听的时候、先判断keyPopwindow == null ,不为空再去判断popwindow是否显示在屏幕上,但是获取的是false,我想跟焦点有关系吧,我用的是setOnTouchListener监听,popwindow上没有焦点,判断就有问题。目前还没想到好的办法,就先让光标闪烁吧,点击外面popwindow直接消失。后面我会给出源码,大家可以测试。
       如果我们在输入用户名的时候,在去输入密码,系统键盘是没有自动关闭的,这个时候我们就需要去判断一下,如果有系统键盘显示就需要关闭系统键盘,通过如下两个方法就可以实现:

/**
     * 关闭系统键盘
     * @param mEditText
     * @param mContext
     */
    public void closeSoftKeybord(EditText mEditText, Context mContext) {
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
    }

    /**
     * 判断是否有系统键盘显示
     * @return
     */
    public boolean isSystemKeyboardVisible(){
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        return imm.isActive();
    }

       第三个问题其实也不难,我想的解决办法是scrollview来解决,我们计算输入框控件距离屏幕下方的距离如果小于密码键盘的高度,就要被遮住,这时候我们就需要在这个scrollview下添加一个view,这样点击布局就上移了,在关闭的时候,再把添加的view移除就好,关于这个计算涉及到android的坐标系计算,不熟悉的可以看看这篇博文:

http://blog.csdn.net/yanbober/article/details/50419117/

       我的实现后是这样的
这里写图片描述

       这个坐标计算我们先计算控件到屏幕view绘制的上方的距离,通过绝对坐标计算,数组下标0是宽度,下标1是高度,还有一个view.getLocationInWindow(location) 获取的是在父窗口的绝对坐标:

    int[] Location = new int[2];
    pw_et.getLocationOnScreen(Location);
    int y = Location[1];

       我们算出这个高度,然后通过获取整个view的绘制区域高度,然后通过rect.height()这个就可以获取高度:

      Rect rect = new Rect();
      getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);  

       这样我们就可以计算出到底部的距离,通过这个距离就可以判断是否显示密码键盘,不过计算popwindow的高度要这样计算,直接getHeight是获取不到的,一直为0,因为在实例化的时候绘制还没有完成:

keyPopwindow.getContentView().measure(0, 0);
int keyHeight = keyPopwindow.getContentView().getMeasuredHeight();

       这样就可以计算出来上移的距离了,不过我们还有一点要注意,如果scrollview的高度没有超过屏幕,那么我们加上上面计算的偏移量有可能还达不到scrollview滑动的条件,我们应该在加上scrollview距离屏幕低端的距离,这样就可以了,可以说就可以达到我们上面哪个效果。

2.实现键盘

       实现我们就可以通过editable = password_et.getEditableText(); 然后

    private void insert(Button btn) {
        int index = password_et.getSelectionStart();
        String str = btn.getText().toString();
        editable.insert(index, str);
    }

       通过这个就可以实现点击事件输入到输入框,我们在设置一个回调接口,在popwindow关闭的时候调整布局:

public static LayoutAdjustListener mLayoutAdjustListener;

    public interface LayoutAdjustListener {
        //键盘遮挡布局使用scroll调整布局
        void adjustKeyboard();
    }

    public static void setmLayoutAdjustListener(LayoutAdjustListener layoutAdjustListener) {
        KeyPopwindow.mLayoutAdjustListener = layoutAdjustListener;
    }

    this.setOnDismissListener(new OnDismissListener() {
            @Override
            public void onDismiss() {
                if (mLayoutAdjustListener != null) {
                    mLayoutAdjustListener.adjustKeyboard();
                }
            }
        });

       这样就基本上完成了,还有一些东西,大家看源码实现吧,我稍后上传下来,有问题的地方欢迎大家指出。

源码下载地址下载地址

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值