自定义密码输入框

先看 输入框的样式(换了电脑图都没了,就用我csdn上的图片了 - - .),

image

看到效果图,我们就在脑海里想到了几种实现方法, 可以用很多个editext进行实现,也可以自定义view实现,自定义毕竟听起来高大上,所以就他了吧。O 道理我都懂先上效果图。
image

思路

正常思路应该是先画一个带圆角的边框,然后根据密码的位数划线,写一个回调接口监听Editext的变化。

然而当我们用canvas.drawRoundRect( )方法画完之后。。。
image
仔细一看,四个角丑爆了,有木有。所以我们可以给我们自定义的view加上一个布局,然后给这个布局添加一个背景shape,就可以完美解决了。

特别注意

this.setCursorVisible(false); 隐藏光标。
//super.onDraw(canvas); 要注释掉,要不然edittext 会执行内部方法,绘制内容到view中
在xml文件中: android:background=”@null” 去掉下划线。

画中间线

 /**
     * 支付密码的样式
     *
     * @param canvas
     */
    private void drawWeChatBorder(Canvas canvas) {
        for (int i = 0; i < maxCount - 1; i++) {
            canvas.drawLine((i + 1) * divideLineWStartX,
                    0,
                    (i + 1) * divideLineWStartX,
                    height,
                    divideLinePaint);
        }

    }

画密码实心圆

 /**
     * 画密码实心圆
     *
     * @param canvas
     */
    private void drawPsdCircle(Canvas canvas) {
        for (int i = 0; i < textLength; i++) {
            canvas.drawCircle(startX + i * 2 * startX,
                    startY,
                    radius,
                    circlePaint);
        }
    }

完整代码

public class MyEditText extends EditText {
    private Context mContext;

    private  OnPayListener listener;

   /**
    * 最大输入位数
    */
   private int maxCount = 6;
    /**
     * 第一个圆开始绘制的圆心坐标
     */
    private float startX;
    private float startY;

    /**
     * 实心圆的半径
     */
    private int radius = 10;
    /**
     * view的高度
     */
    private int height;
    private int width;

    /**
     * 当前输入密码位数
     */
    private int textLength = 0;
    /**
     * 圆的颜色   默认BLACK
     */
    private int circleColor = Color.BLACK;

    /**
     * 分割线的颜色
     */
    private int borderColor = Color.GRAY;
    /**
     * 分割线的画笔
     */
    private Paint borderPaint;
    /**
     * 分割线开始的坐标x
     */
    private int divideLineWStartX;

    /**
     * 分割线的宽度  默认2
     */
    private int divideLineWidth = 0;
    /**
     * 竖直分割线的颜色
     */
    private int divideLineColor = Color.GRAY;
    private RectF rectF = new RectF();


    /**
     * 矩形边框的圆角
     */
    private int rectAngle = 0;
    /**
     * 竖直分割线的画笔
     */
    private Paint divideLinePaint;
    /**
     * 圆的画笔
     */
    private Paint circlePaint;


    public MyEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        getAtt(attrs);
        initPaint();
         this.setCursorVisible(false);
        this.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxCount)});
    }

    private void getAtt(AttributeSet attrs) {
        TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.MyEditText);
        maxCount = typedArray.getInt(R.styleable.MyEditText_maxCount, maxCount);
        circleColor = typedArray.getColor(R.styleable.MyEditText_circleColor, circleColor);
        radius = typedArray.getDimensionPixelOffset(R.styleable.MyEditText_radius, radius);
        divideLineWidth = typedArray.getDimensionPixelSize(R.styleable.MyEditText_divideLineWidth, divideLineWidth);
        divideLineColor = typedArray.getColor(R.styleable.MyEditText_divideLineColor, divideLineColor);
        rectAngle = typedArray.getDimensionPixelOffset(R.styleable.MyEditText_rectAngle, rectAngle);
        typedArray.recycle();
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {

        circlePaint = getPaint(5, Paint.Style.FILL, circleColor);


        borderPaint = getPaint(3, Paint.Style.STROKE, borderColor);

   divideLinePaint = getPaint(divideLineWidth, Paint.Style.STROKE,R.color.line );
//        divideLinePaint = new Paint();
//        divideLinePaint.setStrokeWidth(divideLineWidth);
//        divideLinePaint.setStyle(Paint.Style.FILL);
//        divideLinePaint.setColor(getResources().getColor(R.color.line));
//        divideLinePaint.setAntiAlias(true);
    }
    /**
     * 设置画笔
     *
     * @param strokeWidth 画笔宽度
     * @param style       画笔风格
     * @param color       画笔颜色
     * @return
     */
    private Paint getPaint(int strokeWidth, Paint.Style style, int color) {
        Paint paint = new Paint(ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(strokeWidth);
        paint.setStyle(style);
        paint.setColor(color);
        paint.setAntiAlias(true);

        return paint;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
        divideLineWStartX = w / maxCount;
        startX = w / maxCount / 2;
        startY = h / 2;

        rectF.set(0, 0, width, height);


    }

    @Override
    protected void onDraw(Canvas canvas) {
       //super.onDraw(canvas);
        drawWeChatBorder(canvas);
        drawPsdCircle(canvas);
    }

    /**
     * 画微信支付密码的样式
     *
     * @param canvas
     */
    private void drawWeChatBorder(Canvas canvas) {

        //canvas.drawRoundRect(rectF, rectAngle, rectAngle, borderPaint);
        for (int i = 0; i < maxCount - 1; i++) {
            canvas.drawLine((i + 1) * divideLineWStartX,
                    0,
                    (i + 1) * divideLineWStartX,
                    height,
                    divideLinePaint);
        }

    }


    /**
     * 画密码实心圆
     *
     * @param canvas
     */
    private void drawPsdCircle(Canvas canvas) {
        for (int i = 0; i < textLength; i++) {
            canvas.drawCircle(startX + i * 2 * startX,
                    startY,
                    radius,
                    circlePaint);
        }
    }


    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        textLength = text.toString().length();
        if (textLength == maxCount){
        if (null != listener)listener.onGo(getPasswordString());
        }
        invalidate();

    }

    @Override
    protected void onSelectionChanged(int selStart, int selEnd) {
        super.onSelectionChanged(selStart, selEnd);

        //保证光标始终在最后
        if (selStart == selEnd) {
            setSelection(getText().length());
        }
    }
    public interface OnPayListener {
        void onGo(String pas);
    }

    public  void  setListener(OnPayListener mlistener){
        this.listener = mlistener;
    }
    /**
     * 获取输入的密码
     *
     * @return
     */
    public String getPasswordString() {
        return getText().toString().trim();
    }

}

attr文件

<declare-styleable name="MyEditText">
        <attr name="maxCount" format="integer" />
        <attr name="circleColor" format="color" />
        <attr name="bottomLineColor" format="color" />
        <attr name="radius" format="dimension" />
        <attr name="divideLineWidth" format="dimension" />
        <attr name="divideLineColor" format="color" />
        <attr name="rectAngle" format="dimension" />
    </declare-styleable>

布局shape

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="5dp"/>
    <stroke
        android:width="0.5dp"
        android:color="#aaa"/>
    <solid android:color="#FBFBFB"/>
</shape>

csdn:http://download.csdn.net/download/qq_38367802/10172775
github:https://github.com/liuzhenhang/myview

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容

  • 效果 自定义密码输入框,项目的一个界面需求,我把这个自定义的输入框提取出来作为这次内容的题目。输入前: 输入后: ...
    cgrass阅读 3,402评论 3 31
  • 1.概述 最近有人在问我要所有项目的代码,我在这里声明一下我不是这几个项目公司内部人员,之所以录视频和写博客也是喜...
    红橙Darren阅读 9,856评论 7 46
  • 1.公司最近要做一款钱包支付类的APP,由于系统键盘和支付方式都是自家的,不能使用系统自定义的,因此对这两款功能进...
    LeafRead阅读 1,275评论 0 1
  • 先看最终效果图可在布局文件中配置各种属性,如密码框个数,密码框圆角半径,颜色,中间圆半径和大小,padding值也...
    shada阅读 1,647评论 7 3
  • 我跟朋友正在坐飞毯飞向普宁,当时正是大晚上的十二点多,一路空中飞,谁知迷路了,只知道一直往直线的开,三点了还在路上...
    CUANGY阅读 172评论 0 0