Android自定义view,PasswordView,交易密码输入框

1、效果图:

这里写图片描述

2、代码:

attr.xml

<declare-styleable name="PasswordView">
        <attr name="pv_color" format="color|reference" />
        <attr name="pv_background_color" format="color|reference" />
        <attr name="pv_stroke_color" format="color|reference" />
        <attr name="pv_stroke_width" format="dimension" />
        <attr name="pv_password_length" format="integer|reference" />
    </declare-styleable>

view源码:

package exam.org.jsc.password.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import exam.org.jsc.password.R;

/**
 * Created by Justin Qin on 3/25/2017.
 */

public class PasswordView extends View {
    Paint mPaint;
    int color;
    int backgroundColor;
    int strokeColor;
    int strokeWidth;

    String password = "";
    int passwordLength;

    OnPasswordChangedListener changedListener;

    public PasswordView(Context context) {
        this(context, null);
    }

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

    public PasswordView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PasswordView);
        color = array.getColor(R.styleable.PasswordView_pv_color, Color.BLACK);
        backgroundColor = array.getColor(R.styleable.PasswordView_pv_background_color, Color.WHITE);
        strokeColor = array.getColor(R.styleable.PasswordView_pv_stroke_color, Color.BLACK);
        strokeWidth = array.getDimensionPixelSize(R.styleable.CloseView_cv_stroke_width, 1);
        passwordLength = array.getInt(R.styleable.PasswordView_pv_password_length, 6);
        array.recycle();
        init();
    }

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

    public void addOnPasswordChangedListener(OnPasswordChangedListener changedListener) {
        this.changedListener = changedListener;
    }

    public void input(String txt){
        if (password.length() >= passwordLength)
            return;

        password += txt;
        postInvalidate();

        if (changedListener == null)
            return;

        changedListener.onPasswordChanged(password);
        if (password.length() >= passwordLength)
            changedListener.onPasswordFinish(password);
    }

    public void delete(){
        if (password.length() <= 0)
            return;

        password = password.substring(0, password.length() -1);
        postInvalidate();
        if (changedListener != null)
            changedListener.onPasswordChanged(password);
    }

    public void clearPassword(){
        password = "";
        postInvalidate();
        if (changedListener != null)
            changedListener.onPasswordChanged(password);
    }

    public String getPassword() {
        return password;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
        int widthSize = getMeasuredWidth();
        int heightSize = getMeasuredHeight();
        //把宽度分成passwordLength等份
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize  / passwordLength, MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        int stepWidth = width / passwordLength;

        mPaint.setColor(backgroundColor);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawRect(0, 0, width, height, mPaint);

        mPaint.setColor(strokeColor);
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(0, 0, width - strokeWidth, height - strokeWidth, mPaint);
        for (int i = 1; i < passwordLength; i++) {
            canvas.drawLine(stepWidth * i, 0, stepWidth * i, height, mPaint);
        }

        mPaint.setColor(color);
        mPaint.setStyle(Paint.Style.FILL);
        int radius = stepWidth / 8;
        int len = password.length() > passwordLength ? passwordLength : password.length();
        for (int i = 0; i < len; i++) {
            canvas.drawCircle(stepWidth / 2 + stepWidth * i, height / 2, radius, mPaint);
        }
    }

    public interface OnPasswordChangedListener {
        void onPasswordChanged(String password);
        void onPasswordFinish(String password);
    }
}

3、使用:

layout.xml

<?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:id="@+id/activity_main2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="exam.org.jsc.password.activity.AboutActivity">

    <include layout="@layout/title_bar" />

    <exam.org.jsc.password.view.PasswordView
        android:id="@+id/et_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:layout_marginLeft="40dp"
        android:layout_marginRight="40dp"
        app:pv_color="@color/colorAccent" />

    <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:layout_gravity="center_horizontal"
        android:columnCount="4"
        android:orientation="horizontal"
        android:rowCount="3">
          
        <Button
            android:id="@+id/btn_01"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="1" />
          
        <Button
            android:id="@+id/btn_02"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="2" />
           
        <Button
            android:id="@+id/btn_03"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="3" />

        <Button
            android:id="@+id/btn_04"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="4" />

        <Button
            android:id="@+id/btn_05"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="5" />
          
        <Button
            android:id="@+id/btn_06"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="6" />
           
        <Button
            android:id="@+id/btn_07"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="7" />

        <Button
            android:id="@+id/btn_08"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="8" />
          
        <Button
            android:id="@+id/btn_09"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="9" />

        <Button
            android:id="@+id/btn_00"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="0" />

        <Button
            android:id="@+id/btn_10"
            android:layout_columnSpan="2"
            android:layou`
_gravity="fill"
            android:text="delete" />
    </GridLayout>


</LinearLayout>

Activity

package exam.org.jsc.password.activity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import exam.org.jsc.password.R;
import exam.org.jsc.password.view.PasswordView;

public class InputPasswordActivity extends BaseActivity {

    private final int[] ids = {
            R.id.btn_00,
            R.id.btn_01,
            R.id.btn_02,
            R.id.btn_03,
            R.id.btn_04,
            R.id.btn_05,
            R.id.btn_06,
            R.id.btn_07,
            R.id.btn_08,
            R.id.btn_09,
            R.id.btn_10
    };
    PasswordView mPasswordView;
    private Button[] buttons = new Button[ids.length];

    private View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (v.getId() == R.id.btn_10){
                mPasswordView.delete();
            } else {
                Button button = (Button) v;
                String input = button.getText().toString();
                mPasswordView.input(input);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_input_password);
        setStatusBarBackground();
        initTitleBar("InputPassword", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        mPasswordView = (PasswordView) findViewById(R.id.et_password);
        mPasswordView.addOnPasswordChangedListener(new PasswordView.OnPasswordChangedListener() {
            @Override
            public void onPasswordChanged(String password) {

            }

            @Override
            public void onPasswordFinish(String password) {
                showShortToast(password);
            }
        });
        for (int i = 0; i < ids.length; i++) {
            buttons[i] = (Button) findViewById(ids[i]);
            buttons[i].setOnClickListener(listener);
        }
    }

}

谢谢您的惠顾,code有不足的地方请在评论里回复(或者联系我)。
QQ1006368252

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值