美文网首页
仿支付宝密码输入框

仿支付宝密码输入框

作者: migill | 来源:发表于2019-10-21 13:52 被阅读0次

1、定义6位密码输入View,PasswordEditText.java
思路:要绘制边框矩形,绘制分割线,绘制圆点。绘制圆的数目要与字符串的长度有关,添加或者删除都要修改字符串,输入6位后就是要关闭弹框,拿到密码,做判断工作了。
public class PasswordEditText extends AppCompatEditText {
    // 画笔
    private Paint mPaint;
    // 一个密码所占的宽度
    private int mPasswordItemWidth;
    // 密码的个数默认为6位数
    private int mPasswordNumber = 6;
    // 背景边框颜色
    private int mBgColor = Color.parseColor("#FFDDDDDD");
    // 背景边框大小
    private int mBgSize = 1;
    // 背景边框圆角大小
    private int mBgCorner = 8;
    // 分割线的颜色
    private int mDivisionLineColor = mBgColor;
    // 分割线的大小
    private int mDivisionLineSize = 1;
    // 密码圆点的颜色
    private int mPasswordColor = Color.parseColor("#FF000000");
    // 密码圆点的半径大小
    private int mPasswordRadius = 6;

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

    public PasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttributeSet(context, attrs);
        initPaint();
        // 默认只能够设置数字和字母
        setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        mPaint = new Paint();
        // 抗锯齿
        mPaint.setAntiAlias(true);
        // 防抖动
        mPaint.setDither(true);
    }

    /**
     * 初始化属性
     */
    private void initAttributeSet(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText);
        // 获取大小
        //分割线的大小
        mDivisionLineSize = (int) array.getDimension(R.styleable.PasswordEditText_divisionLineSize, dip2px(mDivisionLineSize));
        //圆点的半径
        mPasswordRadius = (int) array.getDimension(R.styleable.PasswordEditText_passwordRadius, dip2px(mPasswordRadius));
        //背景边框大小
        mBgSize = (int) array.getDimension(R.styleable.PasswordEditText_bgSize, dip2px(mBgSize));
        //背景边框圆角大小
        mBgCorner = (int) array.getDimension(R.styleable.PasswordEditText_bgCorner, mBgCorner);
        // 获取边框颜色
        mBgColor = array.getColor(R.styleable.PasswordEditText_bgColor, mBgColor);
        // 分割线颜色
        mDivisionLineColor = array.getColor(R.styleable.PasswordEditText_divisionLineColor, mDivisionLineColor);
        //圆点颜色
        mPasswordColor = array.getColor(R.styleable.PasswordEditText_passwordColor, mPasswordColor);
        array.recycle();
    }

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

    @Override
    protected void onDraw(Canvas canvas) {
        // 一个密码的宽度 [View宽度 - 边框的宽度(背景边框与分割线)]/6
        mPasswordItemWidth = (getWidth() - 2 * mBgSize - (mPasswordNumber - 1) * mDivisionLineSize) / mPasswordNumber;
        // 画背景
        drawBg(canvas);
        // 画分割线
        drawDivisionLine(canvas);
        // 画密码
        drawPassword(canvas);
        // 当前密码是不是满了
        if (mListener != null) {
            String password = getText().toString().trim();
            if (password.length() >= mPasswordNumber) {
                mListener.passwordFull(password);
            }
        }
    }

    /**
     * 绘制密码
     */
    private void drawPassword(Canvas canvas) {
        // 密码绘制是实心
        mPaint.setStyle(Paint.Style.FILL);
        // 设置密码的颜色
        mPaint.setColor(mPasswordColor);
        // 获取当前text
        String text = getText().toString().trim();
        // 获取密码的长度
        int passwordLength = text.length();
        // 不断的绘制密码
        for (int i = 0; i < passwordLength; i++) {
            int cy = getHeight() / 2;
            int cx = mBgSize + i * mPasswordItemWidth + i * mDivisionLineSize + mPasswordItemWidth / 2;
            canvas.drawCircle(cx, cy, mPasswordRadius, mPaint);
        }
    }

    /**
     * 绘制分割线
     */
    private void drawDivisionLine(Canvas canvas) {
        // 给画笔设置大小
        mPaint.setStrokeWidth(mDivisionLineSize);
        // 设置分割线的颜色
        mPaint.setColor(mDivisionLineColor);
        //画竖线,x值不变
        for (int i = 0; i < mPasswordNumber - 1; i++) {
            int startX = mBgSize + (i + 1) * mPasswordItemWidth + i * mDivisionLineSize;
            int startY = mBgSize;
            int endX = startX;
            int endY = getHeight() - mBgSize;
            canvas.drawLine(startX, startY, endX, endY, mPaint);
        }
    }

    /**
     * 绘制背景
     */
    private void drawBg(Canvas canvas) {
        //背景矩形
        RectF rect = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight() - mBgSize);
        // 给画笔设置大小
        mPaint.setStrokeWidth(mBgSize);
        // 设置背景的颜色
        mPaint.setColor(mBgColor);
        // 画空心
        mPaint.setStyle(Paint.Style.STROKE);

        // 绘制背景  drawRect , drawRoundRect  ,
        // 如果有圆角那么就绘制drawRoundRect,否则绘制drawRect
        if (mBgCorner == 0) {
            canvas.drawRect(rect, mPaint);
        } else {
            //rx:x方向上的圆角半径。ry:y方向上的圆角半径。
            canvas.drawRoundRect(rect, mBgCorner, mBgCorner, mPaint);
        }
    }

    /**
     * 添加一个密码
     */
    public void addPassword(String number) {
        // 把之前的密码取出来
        String password = getText().toString().trim();
        if (password.length() >= mPasswordNumber) {
            // 密码不能超过当前密码个输
            return;
        }
        // 密码叠加
        password += number;
        setText(password);
    }

    /**
     * 删除最后一位密码
     */
    public void deleteLastPassword() {
        String password = getText().toString().trim();
        // 判断当前密码是不是空
        if (TextUtils.isEmpty(password)) {
            return;
        }
        password = password.substring(0, password.length() - 1);
        setText(password);
    }

    // 设置当前密码是否已满的接口回掉
    private PasswordFullListener mListener;

    public void setOnPasswordFullListener(PasswordFullListener listener) {
        this.mListener = listener;
    }

    public void clear() {
        setText("");
    }

    /**
     * 密码已经全部填满
     */
    public interface PasswordFullListener {
        public void passwordFull(String password);
    }

}

2、键盘View
思路:主要是点击数字后,拿到数字,在给PasswordEditText它。点击删除后,删除PasswordEditText里面的一个字符。逻辑都是在Dialog里面控制的。

public class CustomerKeyboard extends LinearLayout implements View.OnClickListener {
    public CustomerKeyboard(Context context) {
        this(context, null);
    }

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

    public CustomerKeyboard(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 直接加载布局
        inflate(context, R.layout.ui_customer_keyboard, this);
        setItemClickListener(this);
    }

    /**
     * 设置子View的ClickListener
     */
    private void setItemClickListener(View view) {
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            int childCount = viewGroup.getChildCount();
            for (int i = 0; i < childCount; i++) {
                //不断的递归给里面所有的View设置OnClickListener
                View childView = viewGroup.getChildAt(i);
                setItemClickListener(childView);
            }
        } else {
            view.setOnClickListener(this);
        }
    }

    @Override
    public void onClick(View v) {
        if (v instanceof TextView) {
            if ("删除".equals(((TextView) v).getText().toString().trim())) {
                // 点击的是删除
                if (mListener != null) {
                    mListener.delete();
                }
            } else {
                // 点击的是数字
                String number = ((TextView) v).getText().toString().trim();
                if (mListener != null) {
                    mListener.click(number);
                }
            }
        }
    }

    // 设置点击回掉监听
    private CustomerKeyboardClickListener mListener;

    public void setOnCustomerKeyboardClickListener(CustomerKeyboardClickListener listener) {
        this.mListener = listener;
    }

    /**
     * 点击键盘的回调监听
     */
    public interface CustomerKeyboardClickListener {
        public void click(String number);

        public void delete();
    }
}

3、对话框

/**
 * 支付密码对话框
 */
public class PayPWDialogFragment extends DialogFragment implements CustomerKeyboard.CustomerKeyboardClickListener, PasswordEditText.PasswordFullListener {

    private PasswordEditText mPasswordEt;


    private OnCompleteListener mOnCompleteListener;
    private OnCancelListener mOnCancelListener;

    private static PayPWDialogFragment payPWDialogFragment;


    //写一个静态方法产生实例
    public static PayPWDialogFragment newInstance() {
        if (payPWDialogFragment == null) {
            payPWDialogFragment = new PayPWDialogFragment();
        }
        return payPWDialogFragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.pay_password_dialog_layout, container, false);
        mPasswordEt = (PasswordEditText) view.findViewById(R.id.password_et);
        CustomerKeyboard mCustomerKeyboard = view.findViewById(R.id.custom_key_board);
        mCustomerKeyboard.setOnCustomerKeyboardClickListener(this);
        mPasswordEt.setEnabled(false);
        mPasswordEt.setOnPasswordFullListener(this);

        return view;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) { //此处可以设置Dialog的style等等
        super.onCreate(savedInstanceState);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = new Dialog(getActivity(), R.style.CustomDialog);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(R.layout.pay_password_dialog_layout);
        dialog.setCanceledOnTouchOutside(false);

        /**
         * 设置宽度全屏,要设置在show的后面
         */
        WindowManager.LayoutParams layoutParams = dialog.getWindow().getAttributes();
        layoutParams.gravity = Gravity.BOTTOM;
        layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

        dialog.getWindow().getDecorView().setPadding(0, 0, 0, 0);

        dialog.getWindow().setAttributes(layoutParams);
        return dialog;
    }


    @Override
    public void click(String number) {
        mPasswordEt.addPassword(number);
    }

    @Override
    public void delete() {
        mPasswordEt.deleteLastPassword();
    }

    @Override
    public void passwordFull(String password) {
        if (mOnCompleteListener != null)
            mOnCompleteListener.onComplete(password);
        dismiss();
        mPasswordEt.clear();
    }

    public interface OnCompleteListener {
        void onComplete(String content);
    }

    public interface OnCancelListener {
        void onCancel();
    }

    public PayPWDialogFragment setOnCompleteListener(OnCompleteListener listener) {
        this.mOnCompleteListener = listener;
        return this;
    }

    public PayPWDialogFragment setOnCancelListener(OnCancelListener listener) {
        this.mOnCancelListener = listener;
        return this;
    }
}

4、使用

PayPWDialogFragment.newInstance()
.setOnCompleteListener(new PayPWDialogFragment.OnCompleteListener() {
                    @Override
                    public void onComplete(String content) {

                    }
                })
.show(getFragmentManager(), "payPWDialogFragment");

配置:

    <style name="CustomDialog" parent="@android:style/Theme.Dialog">
        <!--这个说明提示框是否有边框-->
        <item name="android:windowFrame">@null</item>
        <!--这个说明提示框是否是浮动-->
        <item name="android:windowIsFloating">true</item>
        <!--是否有遮盖-->
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
    </style>

ui_customer_keyboard.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FFE6E6E6"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dp">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="1"
            android:textColor="#ff444444"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="2"
            android:textColor="#ff444444"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="3"
            android:textColor="#ff444444"
            android:textSize="30sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dp">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="4"
            android:textColor="#ff444444"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="5"
            android:textColor="#ff444444"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="6"
            android:textColor="#ff444444"
            android:textSize="30sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dp">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="7"
            android:textColor="#ff444444"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="8"
            android:textColor="#ff444444"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="9"
            android:textColor="#ff444444"
            android:textSize="30sp" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="8dp"
            android:textColor="#ff444444"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:background="#FFFFFF"
            android:gravity="center"
            android:padding="8dp"
            android:text="0"
            android:textColor="#ff444444"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="8dp"
            android:text="删除"
            android:textColor="#ff444444" />
    </LinearLayout>
</LinearLayout>

pay_password_dialog_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"
    xmlns:ver="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FFFFFFFF"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:paddingTop="18dp"
        android:paddingBottom="18dp"
        android:text="请输入支付密码"
        android:textColor="#ff252525"
        android:textSize="16sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#FFEEEEEE" />

    <com.example.paybox.PasswordEditText
        android:id="@+id/password_et"
        android:layout_width="match_parent"
        android:layout_height="47dp"
        android:layout_marginTop="20dp"
        android:layout_marginStart="15dp"
        android:layout_marginEnd="15dp"
        android:layout_marginBottom="40dp"
        android:background="@null" />

    <com.example.paybox.CustomerKeyboard
        android:id="@+id/custom_key_board"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

相关文章

网友评论

      本文标题:仿支付宝密码输入框

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