美文网首页
Android 自定义密码输入框,短信验证码输入

Android 自定义密码输入框,短信验证码输入

作者: 一个冬季 | 来源:发表于2019-09-25 19:50 被阅读0次
学习地址

Android仿支付宝淘宝 - 自定义密码输入框和键盘

密码模式.gif 短信验证码.gif
它可以干什么?

1、输入到了最大的个数后,会回调返回输入的值
2、可以自定义边框的颜色,边框弧度
3、可以自定义圆圈的颜色,半径
4、可以自定义个数
5、可以通过在XML里面定义 isPassword,true表示开启秘密模式,false关闭秘密模式,当为false的时候,我们可以拿去当验证码的输入,可以通过iTextSise控制文字大小

遇到的难点

1、如果我输入123,然后分别拆分到3个正方形的框框里
我们需要将123,进行分别拆分,拆分为1 2 3 这样的,在for循环里面通过canvas.drawText,绘画出每一个拆分的

代码展示
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".MainActivity">
    <com.example.myapplication.InputEditViewLayout
        android:id="@+id/inputEditView"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        app:passwordNumber="4"
        app:isPassword="false"//关闭密码模式
        app:iTextSise = "30"//设置文字大小,仅仅在isPassword=false有效
        app:passwordColor="@color/colorAccent"
        app:bgColor="@color/colorPrimary" />
</LinearLayout>
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final InputEditViewLayout inputEditViewLayout = this.findViewById(R.id.inputEditView);
        inputEditViewLayout.setOnInputPassworEditListener(new InputEditViewLayout.OnInputPassworEditListener() {
            @Override
            public void onFinishInput() {
                Toast.makeText(MainActivity.this,"密码是:"+  inputEditViewLayout.getText().toString(),Toast.LENGTH_LONG).show();
            }
        });
    }
}
/**
 * @date :2019/8/29 0029
 * @author : gaoxiaoxiong
 * @description: 密码框的输入
 **/
public class InputEditViewLayout extends androidx.appcompat.widget.AppCompatEditText implements View.OnKeyListener {
    private String TAG = InputEditViewLayout.class.getSimpleName();
    private Paint mPaint;
    // 一个密码所占的宽度
    private int mPasswordItemWidth;
    // 密码的个数默认为6位数
    private int mPasswordNumber = 6;
    // 背景边框颜色
    private int mBgColor = Color.parseColor("#999999");
    // 背景边框大小
    private int mBgSize = 1;
    // 背景边框圆角大小
    private int mBgCorner = 0;
    // 密码圆点的颜色
    private int mPasswordColor = mBgColor;
    // 密码圆点的半径大小
    private int mPasswordRadius = 4;
    private int itemDisTance = 0;//Item之间的间隔
    private int paddingTop = dip2px(10);
    private boolean isPassWord = true;//是否为密码模式,如果不是密码模式,就明文展示
    private int iTextSise = 14;
    private boolean isHaveNotice = false;//判断是否已经回调给前面了
    public InputEditViewLayout(Context context) {
        this(context, null);
    }

    public InputEditViewLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    private OnInputPassworEditListener onInputPassworEditListener;

    @Override
    public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
        if(keyCode == KeyEvent.KEYCODE_DEL) {
            isHaveNotice = false;
        }
        return false;
    }

    public interface OnInputPassworEditListener {
        void onFinishInput();
    }

    public void setOnInputPassworEditListener(OnInputPassworEditListener onInputPassworEditListener) {
        this.onInputPassworEditListener = onInputPassworEditListener;
    }

    public InputEditViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //初始化一些布局必须参数
        initAttributeSet(context, attrs);
        //初始化画笔 + 个数计算
        init();
        // 设置输入模式是密码
        if (isPassWord){
            setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
        }else {
            setInputType(EditorInfo.TYPE_CLASS_NUMBER);
        }
        // 不显示光标
        setCursorVisible(false);
        //获取焦点
        this.setFocusable(true);
        this.setFocusableInTouchMode(true);
        this.requestFocus();
        setOnKeyListener(this);
    }

    private void initAttributeSet(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.InputEditViewLayout);
        mBgSize = typedArray.getInteger(R.styleable.InputEditViewLayout_bgSize, 1);
        mPasswordNumber = typedArray.getInteger(R.styleable.InputEditViewLayout_passwordNumber, 6);
        mBgCorner = typedArray.getInteger(R.styleable.InputEditViewLayout_bgCorner, 5);
        mPasswordRadius = typedArray.getInteger(R.styleable.InputEditViewLayout_passwordRadius, 4);
        mPasswordColor = typedArray.getColor(R.styleable.InputEditViewLayout_passwordColor, mBgColor);
        mBgColor = typedArray.getColor(R.styleable.InputEditViewLayout_bgColor, mBgColor);
        isPassWord = typedArray.getBoolean(R.styleable.InputEditViewLayout_isPassword, true);
        iTextSise = typedArray.getInteger(R.styleable.InputEditViewLayout_iTextSise,16);
        typedArray.recycle();
        mBgSize = dip2px(mBgSize);
        mBgCorner = dip2px(mBgCorner);
        mPasswordRadius = dip2px(mPasswordRadius);
        iTextSise = sp2px(context,iTextSise);
        this.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mPasswordNumber)});
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(mBgColor);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mPasswordItemWidth = getMeasuredHeight() - paddingTop;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        itemDisTance = (getWidth() - (mPasswordNumber * mPasswordItemWidth)) / (mPasswordNumber + 1);//平均下来的距离
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //绘制背景
        drawBg(itemDisTance, canvas);
        drawHidePassword(canvas);
    }

    /**
     * @date :2019/8/29 0029
     * @author : gaoxiaoxiong
     * @description:绘制背景
     **/
    private void drawBg(int startX, Canvas canvas) {
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(mBgColor);
        mPaint.setStrokeWidth(mBgSize);
        for (int i = 0; i < mPasswordNumber; i++) {
            RectF rectF = new RectF(startX, paddingTop / 2, startX + mPasswordItemWidth, mPasswordItemWidth + paddingTop / 2);
            canvas.drawRoundRect(rectF, mBgCorner, mBgCorner, mPaint);
            startX = startX + mPasswordItemWidth + itemDisTance;
        }

    }

    /**
     * @date :2019/8/29 0029
     * @author : gaoxiaoxiong
     * @description:绘制密码
     **/

    private void drawHidePassword(Canvas canvas) {
        int passwordLength = getText().toString().trim().length();
        mPaint.setColor(mPasswordColor);
        mPaint.setStyle(Paint.Style.FILL);
        if (!isPassWord) {//不是密码模式
            mPaint.setTextSize(iTextSise);
            String text = getText().toString();//1  2  3
            for (int i = 0; i < passwordLength; i++) {
                int cx = itemDisTance + i * mPasswordItemWidth + mPasswordItemWidth / 2 + i * itemDisTance;
                String aaa = text.substring(i, i + 1);
                //文字处理
                TextPaint paint = this.getPaint();
                //计算baseLine
                int center = getMeasuredHeight() / 2 + paddingTop / 2;
                int baseLine = (int) (center + (paint.getFontMetrics().bottom - paint.getFontMetrics().top) / 2 - paint.getFontMetrics().bottom);
                int fontWidth = (int) mPaint.measureText(aaa);
                canvas.drawText(aaa, cx - fontWidth / 2, baseLine, mPaint);
            }
        } else {
            //密码处理
            for (int i = 0; i < passwordLength; i++) {
                int cx = itemDisTance + i * mPasswordItemWidth + mPasswordItemWidth / 2 + i * itemDisTance;
                canvas.drawCircle(cx, getHeight() / 2, mPasswordRadius, mPaint);
            }
        }

        if (passwordLength == mPasswordNumber && !isHaveNotice) {
            if (onInputPassworEditListener != null) {
                onInputPassworEditListener.onFinishInput();
                isHaveNotice = true;
            }
        }
    }

 /**
     * @date :2019/9/24 0024
     * @author : gaoxiaoxiong
     * @description:清除数据
     **/
    public void cleanData(){
        this.setText("");
        isHaveNotice = false;
    }

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

    /**
     * 将px值转换为sp值,保证文字大小不变
     *
     * @param pxValue
     * @return
     */
    public int px2sp(Context context, float pxValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }



    /**
     * 将sp值转换为px值,保证文字大小不变
     *
     * @param spValue
     * @return
     */
    public int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

}


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="InputEditViewLayout">
        <!-- 密码的个数 -->
        <attr name="passwordNumber" format="integer"/>
        <!-- 密码圆点的半径 -->
        <attr name="passwordRadius" format="integer" />
        <!-- 密码圆点的颜色 -->
        <attr name="passwordColor" format="color" />
        <!-- 分割线的颜色 -->
        <attr name="divisionLineColor" format="color" />
        <!-- 分割线的大小 -->
        <attr name="divisionLineSize" format="color" />
        <!-- 背景边框的颜色 -->
        <attr name="bgColor" format="color" />
        <!-- 背景边框的大小 -->
        <attr name="bgSize" format="integer" />
        <!-- 背景边框的圆角大小 -->
        <attr name="bgCorner" format="integer"/>
        <!--是否为密码模式-->
        <attr name="isPassword" format="boolean"/>
        <!--文字大小,仅仅对,明文模式有效-->
        <attr name="iTextSise" format="integer"/>
    </declare-styleable>
</resources>

相关文章

网友评论

      本文标题:Android 自定义密码输入框,短信验证码输入

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