zoukankan      html  css  js  c++  java
  • 自定义EditText 实现带清空按钮的输入框

    注:本文转载自csdn,其中实现清除功能所采用的方案比较可取。

    原文如下:

    项目要求:做出包含根据情况可变色的下划线,左侧有可变图标,右侧有可变删除标志的edittext,如图

    记录制作过程:

    第一版本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    public class LineEditText extends EditText {
        private Paint mPaint;
        private int color;
        public static final int STATUS_FOCUSED = 1;
        public static final int STATUS_UNFOCUSED = 2;
        public static final int STATUS_ERROR = 3;
        private int status = 2;
        private Drawable del_btn;
        private Drawable del_btn_down;
        private int focusedDrawableId = R.drawable.user_select;// 默认的
        private int unfocusedDrawableId = R.drawable.user;
        private int errorDrawableId = R.drawable.user_error;
        Drawable left = null;
        private Context mContext;
        public LineEditText(Context context) {
            super(context);
            mContext = context;
            init();
        }
        public LineEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            init();
        }
        public LineEditText(Context context, AttributeSet attrs, int defStryle) {
            super(context, attrs, defStryle);
            mContext = context;
            TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.lineEdittext, defStryle, 0);
            focusedDrawableId = a.getResourceId(
                    R.styleable.lineEdittext_drawableFocus, R.drawable.user_select);
            unfocusedDrawableId = a.getResourceId(
                    R.styleable.lineEdittext_drawableUnFocus, R.drawable.user);
            errorDrawableId = a.getResourceId(
                    R.styleable.lineEdittext_drawableError, R.drawable.user_error);
            a.recycle();
            init();
        }
        /**
         * 2014/7/31
         *
         * @author Aimee.ZHANG
         */
        private void init() {
            mPaint = new Paint();
            // mPaint.setStyle(Paint.Style.FILL);
            mPaint.setStrokeWidth(3.0f);
            color = Color.parseColor("#bfbfbf");
            setStatus(status);
            del_btn = mContext.getResources().getDrawable(R.drawable.del_but_bg);
            del_btn_down = mContext.getResources().getDrawable(R.drawable.del_but_bg_down);
            addTextChangedListener(new TextWatcher() {
                @Override
                public void onTextChanged(CharSequence arg0, int arg1, int arg2,
                        int arg3) {
                }
                @Override
                public void beforeTextChanged(CharSequence arg0, int arg1,
                        int arg2, int arg3) {
                }
                @Override
                public void afterTextChanged(Editable arg0) {
                    setDrawable();
                }
            });
            setDrawable();
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPaint.setColor(color);
            canvas.drawLine(0, this.getHeight() - 1, this.getWidth(),
                    this.getHeight() - 1, mPaint);
        }
        // 删除图片
        private void setDrawable() {
            if (length() < 1) {
                setCompoundDrawablesWithIntrinsicBounds(left, null, del_btn, null);
            } else {
                setCompoundDrawablesWithIntrinsicBounds(left, null, del_btn_down,null);
            }
        }
        // 处理删除事件
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (del_btn_down != null && event.getAction() == MotionEvent.ACTION_UP) {
                int eventX = (int) event.getRawX();
                int eventY = (int) event.getRawY();
                Log.e("eventXY", "eventX = " + eventX + "; eventY = " + eventY);
                Rect rect = new Rect();
                getGlobalVisibleRect(rect);
                rect.left = rect.right - 50;
                if (rect.contains(eventX, eventY))
                setText("");
            }
            return super.onTouchEvent(event);
        }
        public void setStatus(int status) {
            this.status = status;
                                                                                                                                                  
            if (status == STATUS_ERROR) {
                try {
                    left = getResources().getDrawable(errorDrawableId);
                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
                setColor(Color.parseColor("#f57272"));
            } else if (status == STATUS_FOCUSED) {
                try {
                    left = getResources().getDrawable(focusedDrawableId);
                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
                setColor(Color.parseColor("#5e99f3"));
            } else {
                try {
                    left = getResources().getDrawable(unfocusedDrawableId);
                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
                setColor(Color.parseColor("#bfbfbf"));
            }
            if (left != null) {
    //          left.setBounds(0, 0, 30, 40);
    //          this.setCompoundDrawables(left, null, null, null);
                setCompoundDrawablesWithIntrinsicBounds(left,null,del_btn,null);
            }
            postInvalidate();
        }
        public void setLeftDrawable(int focusedDrawableId, int unfocusedDrawableId,
                int errorDrawableId) {
            this.focusedDrawableId = focusedDrawableId;
            this.unfocusedDrawableId = unfocusedDrawableId;
            this.errorDrawableId = errorDrawableId;
            setStatus(status);
        }
        @Override
        protected void onFocusChanged(boolean focused, int direction,
                Rect previouslyFocusedRect) {
            super.onFocusChanged(focused, direction, previouslyFocusedRect);
            if (focused) {
                setStatus(STATUS_FOCUSED);
            } else {
                setStatus(STATUS_UNFOCUSED);
            }
        }
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
        };
        public void setColor(int color) {
            this.color = color;
            this.setTextColor(color);
            invalidate();
        }
    }

    效果图:



    代码解释:

    变量名 STATUS_FOCUSED,STATUS_UNFOCUSED,STATUS_ERROR 标示了三种状态,选中状况为蓝色,未选中状态为灰色,错误状态为红色。focusedDrawableId   unfocusedDrawableId  errorDrawableId 存放三种状态的图片,放置于最左侧。
     
    canvas.drawLine(0, this.getHeight() - 1, this.getWidth(),this.getHeight() - 1, mPaint);    //画editText最下方的线
    setCompoundDrawablesWithIntrinsicBounds(left, null, del_btn, null);  //放置左边的和右边的图片(左,上,右,下)
    相当于 android:drawableLeft=""  android:drawableRight=""  
     

    onTouchEvent  当手机点击时,第一个先走的函数,当点击右侧删除图标是清空edittext

    setStatus  更具不同的状态,左边的图片不一样

    存在的问题:

    这版本虽然基本功能已经实现,但是不符合需求,设计中要求文本框中无文字时,右侧删除按钮不显示,不点击删除按钮,删除按钮要保持灰色,点击时才可以变蓝色。因此有了第二个版本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    public class LineEditText extends EditText  implements TextWatcher,
    OnFocusChangeListener{
        private Paint mPaint;
        private int color;
        public static final int STATUS_FOCUSED = 1;
        public static final int STATUS_UNFOCUSED = 2;
        public static final int STATUS_ERROR = 3;
        private int status = 2;
        private Drawable del_btn;
        private Drawable del_btn_down;
        private int focusedDrawableId = R.drawable.user_select;// 默认的
        private int unfocusedDrawableId = R.drawable.user;
        private int errorDrawableId = R.drawable.user_error;
        Drawable left = null;
        private Context mContext;
        /**
         * 是否获取焦点,默认没有焦点
         */
        private boolean hasFocus = false;
        /**
         * 手指抬起时的X坐标
         */
        private int xUp = 0;
        public LineEditText(Context context) {
            super(context);
            mContext = context;
            init();
        }
        public LineEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            init();
        }
        public LineEditText(Context context, AttributeSet attrs, int defStryle) {
            super(context, attrs, defStryle);
            mContext = context;
            TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.lineEdittext, defStryle, 0);
            focusedDrawableId = a.getResourceId(
                    R.styleable.lineEdittext_drawableFocus, R.drawable.user_select);
            unfocusedDrawableId = a.getResourceId(
                    R.styleable.lineEdittext_drawableUnFocus, R.drawable.user);
            errorDrawableId = a.getResourceId(
                    R.styleable.lineEdittext_drawableError, R.drawable.user_error);
            a.recycle();
            init();
        }
        /**
         * 2014/7/31
         *
         * @author Aimee.ZHANG
         */
        private void init() {
            mPaint = new Paint();
            // mPaint.setStyle(Paint.Style.FILL);
            mPaint.setStrokeWidth(3.0f);
            color = Color.parseColor("#bfbfbf");
            setStatus(status);
            del_btn = mContext.getResources().getDrawable(R.drawable.del_but_bg);
            del_btn_down = mContext.getResources().getDrawable(R.drawable.del_but_bg_down);
            addListeners();
            setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPaint.setColor(color);
            canvas.drawLine(0, this.getHeight() - 1, this.getWidth(),
                    this.getHeight() - 1, mPaint);
        }
        // 删除图片
    //  private void setDrawable() {
    //      if (length() < 1) {
    //          setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
    //      } else {
    //          setCompoundDrawablesWithIntrinsicBounds(left, null, del_btn,null);
    //      }
    //  }
        // 处理删除事件
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (del_btn != null && event.getAction() == MotionEvent.ACTION_UP) {
                // 获取点击时手指抬起的X坐标
                xUp = (int) event.getX();
                Log.e("xUp", xUp+"");
                /*Rect rect = new Rect();
                getGlobalVisibleRect(rect);
                rect.left = rect.right - 50;*/
                  // 当点击的坐标到当前输入框右侧的距离小于等于getCompoundPaddingRight()的距离时,则认为是点击了删除图标
                if ((getWidth() - xUp) <= getCompoundPaddingRight()) {
                    if (!TextUtils.isEmpty(getText().toString())) {
                        setText("");
                    }
                }
            }else if(del_btn != null && event.getAction() == MotionEvent.ACTION_DOWN && getText().length()!=0){
                setCompoundDrawablesWithIntrinsicBounds(left,null,del_btn_down,null);
            }else if(getText().length()!=0){
                setCompoundDrawablesWithIntrinsicBounds(left,null,del_btn,null);
            }
            return super.onTouchEvent(event);
        }
        public void setStatus(int status) {
            this.status = status;
                                                                                                                                          
            if (status == STATUS_ERROR) {
                try {
                    left = getResources().getDrawable(errorDrawableId);
                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
                setColor(Color.parseColor("#f57272"));
            } else if (status == STATUS_FOCUSED) {
                try {
                    left = getResources().getDrawable(focusedDrawableId);
                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
                setColor(Color.parseColor("#5e99f3"));
            } else {
                try {
                    left = getResources().getDrawable(unfocusedDrawableId);
                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
                setColor(Color.parseColor("#bfbfbf"));
            }
            if (left != null) {
    //          left.setBounds(0, 0, 30, 40);
    //          this.setCompoundDrawables(left, null, null, null);
                setCompoundDrawablesWithIntrinsicBounds(left,null,null,null);
            }
            postInvalidate();
        }
        public void setLeftDrawable(int focusedDrawableId, int unfocusedDrawableId,
                int errorDrawableId) {
            this.focusedDrawableId = focusedDrawableId;
            this.unfocusedDrawableId = unfocusedDrawableId;
            this.errorDrawableId = errorDrawableId;
            setStatus(status);
        }
         private void addListeners() {
                try {
                    setOnFocusChangeListener(this);
                    addTextChangedListener(this);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        @Override
        protected void onFocusChanged(boolean focused, int direction,
                Rect previouslyFocusedRect) {
            super.onFocusChanged(focused, direction, previouslyFocusedRect);
            this.hasFocus=focused;
            if (focused) {
                setStatus(STATUS_FOCUSED);
            } else {
                setStatus(STATUS_UNFOCUSED);
                setCompoundDrawablesWithIntrinsicBounds(left,null,null,null);
            }
        }
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
        };
        public void setColor(int color) {
            this.color = color;
            this.setTextColor(color);
            invalidate();
        }
                                                                                                                                      
        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub
            postInvalidate();
        }
        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {
            // TODO Auto-generated method stub
             if (TextUtils.isEmpty(arg0)) {
                 // 如果为空,则不显示删除图标
                 setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
             } else {
                 // 如果非空,则要显示删除图标
                 setCompoundDrawablesWithIntrinsicBounds(left, null, del_btn, null);
             }
        }
        @Override
         public void onTextChanged(CharSequence s, int start, int before, int after) {
           if (hasFocus) {
               if (TextUtils.isEmpty(s)) {
                   // 如果为空,则不显示删除图标
                   setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
               } else {
                   // 如果非空,则要显示删除图标
                   setCompoundDrawablesWithIntrinsicBounds(left, null, del_btn, null);
               }
           }
       }
        @Override
        public void onFocusChange(View arg0, boolean arg1) {
            // TODO Auto-generated method stub
            try {
                this.hasFocus = arg1;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    效果图:

    比较关键的方法是:onTouchEvent

    当进入界面,点击输入框,要判断输入框中是否已有文字,如果有则显示灰色的删除按钮,如果没有则不显示,如果点击了删除按钮,删除按钮变蓝色

    存在的问题:

    这个版本依旧存在问题,就是输入长度超过输入框,所画的线不会延伸,如图

    解决办法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPaint.setColor(color);
            int x=this.getScrollX();
            int w=this.getMeasuredWidth();
            canvas.drawLine(0, this.getHeight() - 1, w+x,
                    this.getHeight() - 1, mPaint);
        }

    w:获取控件长度

    X:延伸后的长度

    最终效果:

    原文地址:http://blog.csdn.net/zwx622/article/details/38340991

  • 相关阅读:
    并发编程学习笔记(七、Thread源码分析)
    并发编程学习笔记(六、线程组)
    并发编程学习笔记(五、线程中常用的方法)
    并发编程学习笔记(四、线程的优先级)
    并发编程学习笔记(三、如何安全地终止线程)
    sql server登陆账号时遇到233错误
    github上传shh公匙问题
    mysql简单复习
    idea导入jstl标签库
    山高有攀头,路远有奔头~
  • 原文地址:https://www.cnblogs.com/shanzei/p/3907557.html
Copyright © 2011-2022 走看看