自定义View——仿支付宝支付弹窗界面

这里写图片描述
上面这个是采用自定view方式实现的一个仿支付宝支付弹窗的效果;

1、自定义view并初始化自定义属性

public class PasswordEditText extends EditText{
    //一个密码所占的宽度
    private int mPasswordItemWidth;
    //密码的个数默认6个
    private int mPasswordNumder=6;
    //背景边框颜色
    private int mBgColor= Color.parseColor("#d1d2d6");
    //背景边框的大小
    private int mBgSize=1;
    //背景边框圆角大小
    private int mBgCorner=0;
    //分割线的颜色
    private int mDivisionLineColor=mBgColor;
    //分割线的大小
    private int mDivisionLineSize=1;
    //密码圆点的颜色
    private int mPasswordColor=mDivisionLineColor;
    //密码圆点的半径大小
    private int mPasswordRadius=4;
    public PasswordEditText(Context context) {
        this(context,null);
    }
    public PasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttributeSet(context, attrs);

    }
    /**
     * 初始化属性
     * @param context
     * @param attrs
     */
    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,dip2px(mBgCorner));
        //获取颜色
        mBgColor=array.getColor(R.styleable.PasswordEditText_bgColor,mBgColor);
        mDivisionLineColor=array.getColor(R.styleable.PasswordEditText_divisionLineColor,mDivisionLineColor);
        mPasswordColor=array.getColor(R.styleable.PasswordEditText_passwordColor,mDivisionLineColor);
        array.recycle();
    }
}

继承自EditText的话可以用使用EditText中的一些属性和方法,在初始化完自定义属性后要记得调用recycle()方法进行回收;

2、初始化画笔

    /**
     * 初始化画笔
     */
    private void initPaint() {
        mPaint=new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
    }

在第三个构造函数中调用就可以了,

3、在onDraw()方法中进行绘制
在绘制的时候先要计算出一个密码所占的宽度

//一个密码的宽度
private int mPasswordItemWidth=(getWidth()-2*mBgSize-(mPasswordNumder-1)*mDivisionLineSize)/mPasswordNumder;
一个密码的宽度=(整个输入框的宽度-(最左边边框的宽度+最右边边框的宽度)-(密码个数-1)*密码之间分割线的宽度)/密码的个数

获取到一个密码的宽度后就可以进行绘制;
3.1、绘制密码输入框的背景

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);
        if(mBgCorner==0){
            canvas.drawRect(rect,mPaint);
        }else{
            canvas.drawRoundRect(rect,mBgCorner,mBgCorner,mPaint);
        }
    }

没有圆角的话,就调用canvas.drawRect(rect,mPaint);绘制矩形,第一个参数是RectF对象,第二个参数是Paint(画笔);

 /* @param left   The X coordinate of the left side of the rectangle
     * @param top    The Y coordinate of the top of the rectangle
     * @param right  The X coordinate of the right side of the rectangle
     * @param bottom The Y coordinate of the bottom of the rectangle
     */
    public RectF(float left, float top, float right, float bottom) {
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }

RectF源码对四个参数都有说明;

left=输入框边框的大小;
top=输入框边框的大小;
right=getWidth()-输入框边框的大小;
bottom=getHeight()-输入框边框的大小;

如果有圆角的话,就调用canvas.drawRoundRect(rect,mBgCorner,mBgCorner,mPaint);绘制圆角矩形,

  /**
     * @param rect  The rectangular bounds of the roundRect to be drawn
     * @param rx    The x-radius of the oval used to round the corners
     * @param ry    The y-radius of the oval used to round the corners
     * @param paint The paint used to draw the roundRect
     */
    public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
        drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
    }

drawRoundRect源码也对要传入的参数做了说明;
3.2、绘制密码输入框之间的分割线

private void drawDivisionLine(Canvas canvas) {
        mPaint.setStrokeWidth(mDivisionLineSize);
        mPaint.setColor(mDivisionLineColor);
        for (int i=0;i<mPasswordNumder-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);

        }
    }

在绘制分割线的时候需要注意,假设密码的个数是6,只需要绘制5个分割线,调用canvas.drawLine(startX,startY,endX,endY,mPaint);方法进行绘制,

   /**
     * @param startX The x-coordinate of the start point of the line
     * @param startY The y-coordinate of the start point of the line
     * @param paint  The paint used to draw the line
     */
    public void drawLine(float startX, float startY, float stopX, float stopY,
            @NonNull Paint paint) {
        native_drawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
    }

上面是drawLine方法的源码,第一个参数是X的起始位置,第二个参数是Y的起始位置,第三个参数是X的终点位置,第四个参数是Y的终点位置;

startX=输入框边框的宽度+(每个密码的宽度)*当前绘制的位置(当前绘制第几个)+单个分割线的宽度*当前绘制的位置(当前绘制第几个);
startY=输入框边框的宽度;
stopX=startX;
stopY=getHeight()-输入框边框的宽度;

3.3、绘制密码

private void drawPassword(Canvas canvas) {
        //设置实心样式
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mPasswordColor);
        String text=getText().toString().trim();
        int passwordLength=text.length();
        for(int i=0;i<passwordLength;i++){
            int cx=mBgSize+i*mPasswordItemWidth+i*mDivisionLineSize+mPasswordItemWidth/2;
            int cy=getHeight()/2;
            canvas.drawCircle(cx,cy,mPasswordRadius,mPaint);
        }
    }

在绘制密码黑圆点之前先要获取到输入的字符的长度,根据长度遍历该字符串调用canvas.drawCircle(cx,cy,mPasswordRadius,mPaint);进行绘制,
drawCircle()源码:

  /**
     * @param cx     The x-coordinate of the center of the cirle to be drawn
     * @param cy     The y-coordinate of the center of the cirle to be drawn
     * @param radius The radius of the cirle to be drawn
     * @param paint  The paint used to draw the circle
     */
    public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
        native_drawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
    }

第一个参数是X的位置,第二个参数是Y的位置,第三个参数是圆的半径,第四个参数是画笔;

cx=输入框边框的宽度+单个分割线的宽度*当前绘制哪一个+密码框的宽度*当前绘制哪一个+密码框的宽度/2;
cy=getHeight()/2;

到这里输入框背景、分割线、密码都已经绘制完毕了,在这里面添加一个密码添加和删除的方法;

    /**
     * 设置密码
     * @param numder
     */
    public void addPassword(String numder) {
        //把之前的密码取出来
        String password=getText().toString().trim();
        //判断密码的长度,不能超过当前设置的密码的个数
        if(password.length()>=mPasswordNumder){
            return;
        }
        //密码叠加
        password+=numder;
        setText(password);
    }
    /**
     * 删除最后一位密码
     */
    public void deleteLastPassword() {
        //把之前的密码取出来
        String password=getText().toString().trim();
        //判断当前密码是否为空
        if(TextUtils.isEmpty(password)){
            return;
        }
        password=password.substring(0,password.length()-1);
        setText(password);
    }

剩下还有键盘没有弄好,键盘的实现是在xml布局里面写好,添加到LinearLayout中;

4、输入键盘的实现

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);
    }
}

添加进来后,设置相应的点击事件;

    /**
     * 设置点击事件
     * @param view
     */
    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 childView = viewGroup.getChildAt(i);
                setItemClickListener(childView);
            }
        }else{
            view.setOnClickListener(this);
        }
    }
   @Override
    public void onClick(View v) {
        if(v instanceof TextView){
            //点击的是文本
            String number=((TextView) v).getText().toString().trim();
            if(mListener!=null&&number.length()!=0){
                mListener.click(number);
            }
        }
        if(v instanceof ImageView){
            //点击的是删除
            if(mListener!=null){
                mListener.delete();
            }
        }
    }

差不多效果就实现了,在点击的地方调用就可以了;

//弹出dialog输入框
AlertDialog dialog=new AlertDialog.Builder(this).
     setContentView(R.layout.activity_main).
     fullWith().
     formBottom(true).
     setCancelable(true).
     show();
passwordEditText=dialog.getView(R.id.password);
        mCustomerKeyboard=dialog.getView(R.id.customer_keyboard);

        mCustomerKeyboard.setOnCustomerKeyboardClickListener(this);
        passwordEditText.setEnabled(false);
        passwordEditText.setOnPasswordFullListener(this);

源码地址:
http://download.csdn.net/download/wangwo1991/9894467

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值