欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自定义密码输入框和安全键盘

程序员文章站 2022-05-29 22:26:16
...

自定义密码输入框和安全键盘


自定义密码输入框

  • 前言:

    前边我写过一个高仿微信密码支付框的文章,那篇也是一个仿照微信支付样式的,但是在编码上是通过布局堆出那个样式的,这次是自定义一个控件,可以灵活的定制背景,边框颜色,输入文字的颜色和大小以及可输入的位数。
  • 分析:

    首先来看一下密码框的样式
    自定义密码输入框和安全键盘
    n等分这个布局。明确我们输入的时候是在每个小框中显示的,所以edittext肯定不行。结合我上一篇的布局堆出的密码支付框样式来看。这里应该是水平分布的线性布局,n等分的n个textview和n-1个分割线线性分布。
  • 自定义viewgroup:

    自定义viewgroup继承LinearLayout,我们说了,要自己定义样式,颜色等等,那么我们就需要一个让用户自定义这些属性的方法。如下:

     // @param bgdrawable    背景drawable
     // @param pwdlength     密码长度
     // @param splilinewidth 分割线宽度
     // @param splilinecolor 分割线颜色
     // @param pwdcolor      密码字体颜色
     // @param pwdsize       密码字体大小
    
    public void initStyle(int bgdrawable, int pwdlength, float splilinewidth, int splilinecolor, int pwdcolor, int pwdsize) {
        this.pwdlength = pwdlength;
        this.activity = (Activity) context;
    
        //根据自定义的属性来添加密码框
        initShowInput(bgdrawable, pwdlength, splilinewidth, splilinecolor, pwdcolor, pwdsize);
    
    }
    

    public void initShowInput(int bgcolor, int pwdlength, float slpilinewidth, int splilinecolor, int pwdcolor, int pwdsize) {
    
    this.setOrientation(HORIZONTAL);
    this.setBackgroundResource(bgcolor);
    
    //根据长度来初始化tv数组
    textViews = new TextView[pwdlength];
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT);
    params.weight = 1;
    params.gravity = Gravity.CENTER;
    
    //分割线的LayoutParams
    LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(dip2px(context, slpilinewidth), LayoutParams.MATCH_PARENT);
    for (int i = 0; i < textViews.length; i++) {
        final int index = i;
        TextView textView = new TextView(context);
        textView.setGravity(Gravity.CENTER);
        textViews[i] = textView;
        textViews[i].setTextSize(pwdsize);
        textViews[i].setTextColor(context.getResources().getColor(pwdcolor));
        textViews[i].setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD | InputType.TYPE_CLASS_NUMBER);
        this.addView(textView, params);
    
    
        //设置分割线的宽高,并将其add
        if (i < textViews.length - 1) {
            View view = new View(context);
            view.setBackgroundColor(context.getResources().getColor(splilinecolor));
            this.addView(view, params2);
        }
    }
    }
    


以上代码通过我们需要的属性,定义出样式。注释比较详细,不难看懂。到这里,基本的样式出来了,我们可以在布局中使用了。但样式只是基础,后续的操作还有很多。

  • 对外暴露的一些基本操作的方法:

    a、输入的字符串的展示:

     * 根据输入字符,显示密码个数
     *
     * @param s
    
    public void initDatas(String s) {
    if (s.length() > 0) {
    
        int length = s.length();
        if(length<=pwdlength){
            for (int i = 0; i < pwdlength; i++) {
                if (i < length) {
                    for (int j = 0; j < length; j++) {
                        char ch = s.charAt(j);
                        textViews[j].setText(String.valueOf(ch));
                    }
                } else {
                    textViews[i].setText("");
                }
            }
            if(length == pwdlength){
                onTextFinishListener.onFinish(s);
            }
        }
    
    } else {
        for (int i = 0; i < pwdlength; i++) {
            textViews[i].setText("");
        }
    }
    }
    


    b、是否显示明文的控制:

     * 是否显示明文
     *
     * @param showPwd
    
    public void setShowPwd(boolean showPwd) {
        int length = textViews.length;
        for (int i = 0; i < length; i++) {
            if (showPwd) {
                textViews[i].setTransformationMethod(PasswordTransformationMethod.getInstance());
            } else {
                textViews[i].setTransformationMethod(HideReturnsTransformationMethod.getInstance());
            }
        }
    }
    


    c、清除文本

    public void clearText() {
        for (int i = 0; i < pwdlength; i++) {
            textViews[i].setText("");
        }
    }
    
  • 可供拓展的接口回调:比如输入完成的监听回调

    public interface OnTextFinishListener {
        void onFinish(String str);
    
    }
    


到这里我们基本完成了对其的样式定制和拓展使用。需要注意的是,我们这里边只有textview,并没有输入框,如何调取键盘呢?所以如果你们对键盘没有特殊要求,那就在这个自定义viewgroup中new一个edittext并add进去。我这里为什么没有写,我前边也说了,这是结合安全键盘使用的,结合安全键盘使用的时候有一个和自带键盘的冲突,所以我不能写这些带有焦点弹出键盘的控件,我需要自己来控制我的安全键盘,所以没有写edittext。所以edittext的作用其实就是调出键盘,获取输入的内容。使用安全键盘,那安全键盘也需要做这些工作了。

自定义安全键盘

现在的安全键盘超级流行,一般是在输入密码,身份证等敏感信息的时候使用。
首先是布局,样式如下:
自定义密码输入框和安全键盘
看布局我们可以使用gridview,也可以自己写。这个根据需要自己选择。我是自己写的,这样控制起来和点击交互效果相对好点。

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:orientation="vertical"
        android:id="@+id/llCustomerKb"
        android:divider="@drawable/divider_horizontal"
        android:showDividers="beginning|middle">


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="16dp"
            android:layout_centerInParent="true"
            android:text="自定义安全键盘"/>

        <ImageView
            android:id="@+id/ivGlkHide"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:paddingBottom="10dp"
            android:paddingLeft="20dp"
            android:paddingRight="20dp"
            android:paddingTop="10dp"
            android:src="@mipmap/icon_glk_arrow_down"
            android:background="@drawable/press_style"/>
    </RelativeLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:divider="@drawable/divider_horizontal"
        android:showDividers="middle">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:divider="@drawable/divider_vertical"
            android:showDividers="middle">

            <Button
                android:id="@+id/btGlkNum1"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="1"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />

            <Button
                android:id="@+id/btGlkNum2"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="2"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />

            <Button
                android:id="@+id/btGlkNum3"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="3"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:divider="@drawable/divider_vertical"
            android:showDividers="middle" >

            <Button
                android:id="@+id/btGlkNum4"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="4"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />

            <Button
                android:id="@+id/btGlkNum5"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="5"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />

            <Button
                android:id="@+id/btGlkNum6"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="6"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:divider="@drawable/divider_vertical"
            android:showDividers="middle">

            <Button
                android:id="@+id/btGlkNum7"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="7"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />

            <Button
                android:id="@+id/btGlkNum8"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="8"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />

            <Button
                android:id="@+id/btGlkNum9"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="9"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:divider="@drawable/divider_vertical"
            android:showDividers="middle" >

            <Button
                android:id="@+id/btGlkNumDot"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="·"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />

            <Button
                android:id="@+id/btGlkNum0"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/selector_keyboard"
                android:gravity="center"
                android:text="0"
                android:textColor="@color/global_black_color"
                android:textSize="18sp" />

            <ImageView
                android:id="@+id/ivGlkDelete"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#f2f2f2"
                android:gravity="center"
                android:paddingTop="10dp"
                android:paddingBottom="10dp"
                android:src="@mipmap/icon_glk_delete" />
        </LinearLayout>
    </LinearLayout>

    </LinearLayout>

布局有了,include到我们需要的布局即可。接下来是对键盘的管理了。下一个keyBoardUtils来管理。明确一下需求,三种样式的,整数,小数和身份证的。左下角的按钮来匹配这三种形式。需要一个枚举类型来管理这三种样式。一个String类型的集合来管理输入的字符串。键盘显示隐藏时候的动画样式


代码解析:

首先构造方法里边,需要给出键盘的宽高。需要在这里管理每个键的点击,所以需要findViewById,因此需要给出键盘的parentView。需要知道键盘的显示样式,所以还需要枚举类型。

public KeyBoardUtils(Context context,View keyBoaardView,CUSTOME_KEYBOARD_TYPE type,int inputMaxLength) {

    this.mcontext = context;
    this.mkeyBoardView = keyBoaardView;
    this.inputMaxLength = inputMaxLength;
    this.mtype = type;
    forbidClick = false;

    //设置键盘的宽高
    baseWidth = ViewUtils.getScreenWidth(context);
    baseHeight = (int) (baseWidth*0.7);
    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) keyBoaardView.getLayoutParams();
    params.height = baseHeight;
    keyBoaardView.setLayoutParams(params);

    //findView
    findViews();

    setKeyBoardType();
    initListener();

}

我们点击的时候需要将当前点击的结果给view来展示,所以还需要拓展的接口回调

public interface KeyBoardClickInterface{
    void clickNums(String str);

}

键盘按钮的点击事件的处理:

@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.btGlkNum0:
            //根据点击的内容来操作集合
            addOrRemoveStrList(true,"0");
            将当前集合的数据拼成字符串回调到view
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum1:
            addOrRemoveStrList(true,"1");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum2:
            addOrRemoveStrList(true,"2");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum3:
            addOrRemoveStrList(true,"3");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum4:
            addOrRemoveStrList(true,"4");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum5:
            addOrRemoveStrList(true,"5");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum6:
            addOrRemoveStrList(true,"6");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum7:
            addOrRemoveStrList(true,"7");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum8:
            addOrRemoveStrList(true,"8");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.btGlkNum9:
            addOrRemoveStrList(true,"9");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.ivGlkDelete:
            addOrRemoveStrList(false,"");
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;
        case R.id.ivGlkHide:
            hideKeyboard(true);
            break;
        case R.id.btGlkNumDot:
            if(CUSTOME_KEYBOARD_TYPE.NUMBER != mtype){
                addOrRemoveStrList(true,btGlkNumDot.getText().toString());
            }
            keyBoardClickInterface.clickNums(getCurrentStr());
            break;


    }
}

在view层的回调方法中将str给我们前边自定义的输入框来进行绘制。基本效果就出来了。

@Override
public void clickNums(String str) {
    Log.e("TAG",str);
    etPwd.initDatas(str);
}

到这里基本的功能已经实现了。如果有需要拓展的功能可以留言或私信。如有错误,敬请指正!需要源码的私信。



ps:整合的一个aar,直接可以使用aar下载

特别说明:安全键盘和输入框必须使用相对布局包裹!