zoukankan      html  css  js  c++  java
  • 自定义 密码输入框+数字键盘

    实现了一个自定义的密码输入框和自定义数字键盘,用作用户支付密码设置界面。先上效果图如下,方格样式,以及点击空白处隐藏软键盘。
    这里写图片描述

    控件实现清单:
    1)集成于EditText的输入框控件:PasswordInputView.java
    2)数字键盘工具类:NumKeyboardUtil.java
    3)xml文件:number.xml
    4)attrs样式
    5)layout文件

    具体内容:
    PasswordInputView.java

    public class PasswordInputView extends EditText{
        private int textLength;
    
        private int borderColor;
        private float borderWidth;
        private float borderRadius;
    
        private int passwordLength;
        private int passwordColor;
        private float passwordWidth;
        private float passwordRadius;
    
        private Paint passwordPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    
        private final int defaultSplitLineWidth = 1;
    
        public PasswordInputView(Context context, AttributeSet attrs) {
            super(context, attrs);
            final Resources res = getResources();
    
            final int defaultBorderColor = res.getColor(R.color.line_color);
            final float defaultBorderWidth = res.getDimension(R.dimen.dimen_1px);
            final float defaultBorderRadius = res.getDimension(R.dimen.dimen_6);
    
            final int defaultPasswordLength = 6;
            final int defaultPasswordColor = res.getColor(R.color.normal_text_color);
            final float defaultPasswordWidth = res.getDimension(R.dimen.dimen_6);
            final float defaultPasswordRadius = res.getDimension(R.dimen.dimen_6);
    
            TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PasswordInputView, 0, 0);
            try {
                borderColor = a.getColor(R.styleable.PasswordInputView_borderColor, defaultBorderColor);
                borderWidth = a.getDimension(R.styleable.PasswordInputView_borderWidth, defaultBorderWidth);
                borderRadius = a.getDimension(R.styleable.PasswordInputView_borderRadius, defaultBorderRadius);
                passwordLength = a.getInt(R.styleable.PasswordInputView_passwordLength, defaultPasswordLength);
                passwordColor = a.getColor(R.styleable.PasswordInputView_passwordColor, defaultPasswordColor);
                passwordWidth = a.getDimension(R.styleable.PasswordInputView_passwordWidth, defaultPasswordWidth);
                passwordRadius = a.getDimension(R.styleable.PasswordInputView_passwordRadius, defaultPasswordRadius);
            } finally {
                a.recycle();
            }
    
            borderPaint.setStrokeWidth(borderWidth);
            borderPaint.setColor(borderColor);
            passwordPaint.setStrokeWidth(passwordWidth);
            passwordPaint.setStyle(Paint.Style.FILL);
            passwordPaint.setColor(passwordColor);
    
            setSingleLine(true);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            int width = getWidth();
            int height = getHeight();
    
            // 分割线
            borderPaint.setColor(borderColor);
            borderPaint.setStrokeWidth(defaultSplitLineWidth);
            for (int i = 1; i < passwordLength; i++) {
                float x = width * i / passwordLength;
                canvas.drawLine(x, 0, x, height, borderPaint);
            }
    
            // 密码
            float cx, cy = height/ 2;
            float half = width / passwordLength / 2;
            for(int i = 0; i < textLength; i++) {
                cx = width * i / passwordLength + half;
                canvas.drawCircle(cx, cy, passwordWidth, passwordPaint);
            }
        }
    
        @Override
        protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
            super.onTextChanged(text, start, lengthBefore, lengthAfter);
            this.textLength = text.toString().length();
            invalidate();
        }
    
        public int getBorderColor() {
            return borderColor;
        }
    
        public void setBorderColor(int borderColor) {
            this.borderColor = borderColor;
            borderPaint.setColor(borderColor);
            invalidate();
        }
    
        public float getBorderWidth() {
            return borderWidth;
        }
    
        public void setBorderWidth(float borderWidth) {
            this.borderWidth = borderWidth;
            borderPaint.setStrokeWidth(borderWidth);
            invalidate();
        }
    
        public float getBorderRadius() {
            return borderRadius;
        }
    
        public void setBorderRadius(float borderRadius) {
            this.borderRadius = borderRadius;
            invalidate();
        }
    
        public int getPasswordLength() {
            return passwordLength;
        }
    
        public void setPasswordLength(int passwordLength) {
            this.passwordLength = passwordLength;
            invalidate();
        }
    
        public int getPasswordColor() {
            return passwordColor;
        }
    
        public void setPasswordColor(int passwordColor) {
            this.passwordColor = passwordColor;
            passwordPaint.setColor(passwordColor);
            invalidate();
        }
    
        public float getPasswordWidth() {
            return passwordWidth;
        }
    
        public void setPasswordWidth(float passwordWidth) {
            this.passwordWidth = passwordWidth;
            passwordPaint.setStrokeWidth(passwordWidth);
            invalidate();
        }
    
        public float getPasswordRadius() {
            return passwordRadius;
        }
    
        public void setPasswordRadius(float passwordRadius) {
            this.passwordRadius = passwordRadius;
            invalidate();
        }
    }
    

    NumKeyboardUtil 数字软键盘工具类

    public class NumKeyboardUtil {
        private KeyboardView keyboardView;    
        private Keyboard k;// 数字键盘    
        private PasswordInputView ed;
    
        public NumKeyboardUtil(Activity act, Context ctx, PasswordInputView edit) {    
            this.ed = edit;  
            k = new Keyboard(ctx, R.xml.number);    
            keyboardView = (KeyboardView) act.findViewById(R.id.keyboard_view);    
            keyboardView.setKeyboard(k);    
            keyboardView.setEnabled(true);    
            keyboardView.setPreviewEnabled(true);  
            keyboardView.setOnKeyboardActionListener(listener);    
        }
    
        private OnKeyboardActionListener listener = new OnKeyboardActionListener() {    
            @Override    
            public void swipeUp() {    
            }    
    
            @Override    
            public void swipeRight() {    
            }    
    
            @Override    
            public void swipeLeft() {    
            }    
    
            @Override    
            public void swipeDown() {    
            }    
    
            @Override    
            public void onText(CharSequence text) {    
            }    
    
            @Override    
            public void onRelease(int primaryCode) {    
            }    
    
            @Override    
            public void onPress(int primaryCode) {    
            }    
            //一些特殊操作按键的codes是固定的比如完成、回退等  
            @Override    
            public void onKey(int primaryCode, int[] keyCodes) {    
                    Editable editable = ed.getText();    
                    int start = ed.getSelectionStart();    
                    if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退    
                            if (editable != null && editable.length() > 0) {    
                                    if (start > 0) {    
                                            editable.delete(start - 1, start);    
                                    }    
                            }    
                    }else if (primaryCode == Keyboard.KEYCODE_CANCEL) {// 完成 
                        hideKeyboard();
                    } else { //将要输入的数字现在编辑框中   
                            editable.insert(start, Character.toString((char) primaryCode));    
                    }    
            }    
        };
    
        public void showKeyboard() {    
            keyboardView.setVisibility(View.VISIBLE);    
        }
    
        public void hideKeyboard() {
            keyboardView.setVisibility(View.GONE);
        }
    
        public int getKeyboardVisible() {
            return keyboardView.getVisibility();
        }
    }
    

    number.xml
    注意该文件需要放在项目下的res目录下的xml目录(没有就建个)里面

    <?xml version="1.0" encoding="utf-8"?>
    <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
        android:horizontalGap="0px"
        android:keyHeight="42dip"
        android:keyWidth="31%p"
        android:verticalGap="0px" >
    
        <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="-3"
                android:keyLabel="完成" />
            <Key
                android:codes="48"
                android:keyLabel="0" />
            <Key
                android:codes="-5"
                android:keyIcon="@drawable/sym_keyboard_delete" />
        </Row>
    
    </Keyboard>
    

    attrs.xml里面的样式:

    <!-- 支付密码输入框 -->
        <declare-styleable name="PasswordInputView">
            <attr name="borderWidth" format="dimension"/>
            <attr name="borderColor" format="color"/>
            <attr name="borderRadius" format="dimension"/>
            <attr name="passwordLength" format="integer"/>
            <attr name="passwordWidth" format="dimension"/>
            <attr name="passwordColor" format="color"/>
            <attr name="passwordRadius" format="dimension"/>
        </declare-styleable>
    

    布局代码:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/main_bg_color" >
    
        <include
            android:id="@+id/title_ll"
            layout="@layout/common_actionbar"/>
    
        <TextView
            android:id="@+id/trader_pwd_set_tips_textview"
            style="@style/normal_text_style"
            android:layout_below="@+id/title_ll"
            android:layout_marginTop="25dip"
            android:layout_centerHorizontal="true"
            android:text="@string/trade_pwd_set_tips_text" />
    
        <ImageView
            android:id="@+id/line1_imageview"
            style="@style/line_horizontal_style"
            android:layout_below="@+id/trader_pwd_set_tips_textview"
            android:layout_marginTop="26dip"
            android:contentDescription="@string/content_description" />
    
        <com.acoe.demo.widget.PasswordInputView
            android:id="@+id/trader_pwd_set_pwd_edittext"
            android:layout_width="match_parent"
            android:layout_height="41dip"
            android:layout_below="@+id/line1_imageview"
            android:maxLength="6"
            android:background="@android:color/white" />
    
        <ImageView
            android:id="@+id/line2_imageview"
            style="@style/line_horizontal_style"
            android:layout_below="@+id/trader_pwd_set_pwd_edittext"
            android:contentDescription="@string/content_description" />
    
        <Button
            android:id="@+id/trader_pwd_set_next_button"
            style="@style/main_button_style"
            android:layout_below="@+id/line2_imageview"
            android:layout_marginTop="25dip"
            android:text="@string/trade_pwd_set_next_text" />
    
        <android.inputmethodservice.KeyboardView
            android:id="@+id/keyboard_view"    
            android:layout_width="match_parent"    
            android:layout_height="240dip"
            android:layout_alignParentBottom="true"
            android:paddingTop="30dip"
            android:paddingLeft="13dip"
            android:paddingRight="13dip"
            android:focusable="true"    
            android:focusableInTouchMode="true"   
            android:visibility="invisible"/>
    
    </RelativeLayout>
    

    Activity代码片段:

    //=======在Activity成员变量中声明部分代码=======
    /** 控件 */
        private PasswordInputView edtPwd;
    
    //=======在Activity实例化控件部分代码=======
    // 初始化控件
            edtPwd = (PasswordInputView) findViewById(R.id.trader_pwd_set_pwd_edittext);
            edtPwd.setInputType(InputType.TYPE_NULL); // 屏蔽系统软键盘
    // 自定义软键盘
            if (keyboardUtil == null) keyboardUtil = new NumKeyboardUtil(this, this, edtPwd);
            edtPwd.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    keyboardUtil.showKeyboard();
                    return false;
                }
            });
    
    //=======在Activity中重写onTouchEvent()方法,实现点击空白处隐藏软键盘=======
    @Override
        public boolean onTouchEvent(MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){  
                 if(getCurrentFocus()!=null && getCurrentFocus().getWindowToken()!=null){ 
                     keyboardUtil.hideKeyboard();
                 }
            }
            return super.onTouchEvent(event);
        }
    

    ps:如果把该密码输入框和其他类型输入框并用时要注意两者之间焦点变化时将系统软键盘和自定义的数字键盘隐藏,我的做法是给密码输入框绑定OnFacusChangeListener事件,来控制就好。如下:

    edtPwd.setOnFocusChangeListener(new OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        // 如果系统键盘是弹出状态,先隐藏
                        ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
                        .hideSoftInputFromWindow(getCurrentFocus()
                        .getWindowToken(),
                        InputMethodManager.HIDE_NOT_ALWAYS);
                        keyboardUtil.showKeyboard();
                    } else {
                        keyboardUtil.hideKeyboard();
                    }
                }
            });
    

      https://www.jianshu.com/p/be68facfc4b8

  • 相关阅读:
    redis 6379端口telnet不通的解决办法
    虚拟机centOS7 关闭防火墙后ping通 telnet不通 解决办法:disable seLinux
    oracle查询表名或字段查不到
    springcloud中feign使用的抗
    java分页使用本地线程方式
    PSS下载助手(PSX Download Helper)1.7.6.1发布
    Spring Cloud系列(四):Eureka源码解析之客户端
    Spring Cloud系列(三):Eureka源码解析之服务端
    Spring Cloud系列(二):Eureka应用详解
    Spring Cloud系列(一):微服务架构简介
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/7050660.html
Copyright © 2011-2022 走看看