Android自定义EditText密码框,自定义EditText的hint不显示问题

在开发中,某些机型和系统输入密码会先明文显示,不安全。可通过自定义属性实现密码直接密文显示,步骤包括在res - values目录创建attrs.xml文件、新建类继承EditText、在xml文件引用控件、在activity页面调用。此外,还可借助第三方框架实现键盘数字和字母随机排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在开发中发现在某些机型某些系统中输入密码时会发现密码会明文显示一会然后再显示成密文,如下图所示:

这是不安全的。这时需要自定义密码输入框,输入密码时直接就是密文显示。这个需要自定义属性。不了解自定义属性的可以先查查,这里只写步骤。

1、自定义输入框密码属性。在项目res-values目录下创建attrs.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="PasswordEditText">
        <!--密码圆点半径-->
        <attr name="pwdRadius" format="dimension"></attr>
        <!--密码圆点颜色-->
        <attr name="pwdColor" format="color"></attr>
    </declare-styleable>
</resources>

2、创建自定义控件。新建一个类继承EditText。

/**
 * @author PanBM
 * @description 自定义密码框
 * @date 2019/6/27
 */
@SuppressLint("AppCompatCustomView")
public class PasswordEditText extends EditText {
    private Paint paint;//画笔
    private int pwdColor= Color.parseColor("#FFFFFF");//密码的颜色
    private int pwdRadius=2;//密码圆点半径大小
    private int pwdItemWidth;//一个密码所占的宽度
    private int paddingLeft=14;//字符距离左边框的距离
    private int pwdLength;//密码的长度
    private int pwdMaxLength=10;//密码最长的长度
    private long cursorFlashTime=500;//光标闪动间隔时间
    private int cursorPosition;//光标位置
    private int cursorWidth;//光标粗细
    private int cursorHeight;//光标高度
    private int cursorColor=Color.WHITE;//光标颜色
    private boolean isCursorShowing=false;//光标是否正在显示
    private boolean isCursorEnable=true;//是否开启光标
    private CharSequence hint;
    private int hintTextColor=Color.GRAY;

    private Timer timer;
    private TimerTask timerTask;

    public PasswordEditText(Context context) {
        super(context);
    }

    public PasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
        //初始化属性
        initAttributeSet(context,attrs);
        //设置输入模式是密码
        setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
        //显示光标。不起作用,需要自己画光标
//        setCursorVisible(true);
    }

    private void initAttributeSet(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText);
        pwdRadius = (int) typedArray.getDimension(R.styleable.PasswordEditText_pwdRadius, dip2px(pwdRadius));
        pwdColor = typedArray.getColor(R.styleable.PasswordEditText_pwdColor,pwdColor);
        typedArray.recycle();
    }

    private void initPaint() {
        paint=new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);

        timerTask=new TimerTask() {
            @Override
            public void run() {
                isCursorShowing=!isCursorShowing;
                postInvalidate();
            }
        };
        timer=new Timer();

        hint=getHint();//获取hint文字
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        timer.scheduleAtFixedRate(timerTask,0,cursorFlashTime);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        timer.cancel();
    }

    private int dip2px(int dip){
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dip,getResources().getDisplayMetrics());
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(text, type);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        pwdItemWidth=dip2px(7);
        //绘制密码
        drawPwd(canvas);
        //绘制光标
        drawCursor(canvas);
        //绘制hint。xml页面引用自定义密码控件发现设置hint内容不显示,这个需要自己绘制才会显示。
        drawHint(canvas);
    }

    private void drawHint(Canvas canvas) {
        if(TextUtils.isEmpty(hint) || !TextUtils.isEmpty(getText())) {
            return;
        }
        canvas.save();

        paint.setColor(hintTextColor);
        paint.setStyle(Paint.Style.FILL);
        paint.setTextSize(dip2px(18));

        Paint.FontMetricsInt fontMetricsInt=paint.getFontMetricsInt();
        int baseLine=(getHeight()-fontMetricsInt.bottom+fontMetricsInt.top)/2-fontMetricsInt.top;
        canvas.drawText(hint,0,hint.length(),getPaddingLeft(),
                baseLine,
                paint);
        canvas.restore();
    }

    private void drawCursor(Canvas canvas) {
        paint.setColor(cursorColor);
        paint.setStrokeWidth(cursorWidth);
        paint.setStyle(Paint.Style.FILL);
        //光标未显示&&开启光标&&获得焦点
        if(!isCursorShowing && isCursorEnable && hasFocus()) {
            //起始点x=paddingLeft+单个密码占用宽度*光标下标
            //起始点y=paddingTop+(单个密码占用宽度-光标高度)/2
            //终止点x=起始点x
            //终止点y=起始点y+光标高度
            canvas.drawLine(getPaddingLeft()+pwdItemWidth*pwdLength,
                    getPaddingTop()+(pwdItemWidth-cursorHeight)/2+dip2px(7),
                    getPaddingLeft()+pwdItemWidth*pwdLength,
                    getPaddingTop()+cursorHeight,
                    paint);
        }
    }

    private void drawPwd(Canvas canvas) {
        pwdLength = getText().length();
//        if(pwdLength>pwdMaxLength) {
//            pwdLength=pwdMaxLength;
//        }
        paint.setColor(pwdColor);
        //设置笔画为实心
        paint.setStyle(Paint.Style.FILL);
        for (int i=0;i<pwdLength;i++){
            int cx=dip2px(paddingLeft)+i*pwdItemWidth+pwdItemWidth/2;
            canvas.drawCircle(cx,getHeight()/2,pwdRadius,paint);
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //光标宽度
        cursorWidth=dip2px(1);
        //光标长度
        cursorHeight=dip2px(23);
    }

3、定义完成后在xml文件中引用该控件

<--控件路径-->
<com.example.view.PasswordEditText
        android:id="@+id/et_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/et_username"
        android:layout_centerInParent="true"
        android:layout_marginLeft="@dimen/normal_match_40"
        android:layout_marginRight="@dimen/normal_match_40"
        android:layout_marginTop="@dimen/normal_padding"
        android:background="@drawable/shape_et"
        android:hint="@string/password"
        android:ellipsize="end"
        android:textColor="@color/white"
        android:textSize="@dimen/text_size_18"/>

4、在activity页面调用就行了。

另外,有的时候输入密码时需要键盘数字和字母随机排列,这个有个第三方框架不错自定义加密键盘 支持输入乱序

 

参考文章:

Android 自定义密码输入框实现代码_Android

Android 处理EditText光标显示在hint文字之前的问题

Android自定义View之密码输入框

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值