【Android】EditText之DrawableRight清

作者: 吾非言 | 来源:发表于2017-08-29 21:00 被阅读277次

    作者:邹峰立,微博:zrunker,邮箱:zrunker@yahoo.com,微信公众号:书客创作,个人平台:www.ibooker.cc

    本文选自书客创作平台第33篇文章。阅读原文

    书客创作

    常常会在一些APP当中看到,当输入框输入内容之后,在输入框的右侧会显示一个清空的按钮,点击清空按钮,输入框的内容将会被清空。像这样的功能该如何实现呢?
    今天就使用EditText的DrawableRight实现清空输入值功能。

    应用场景

    DrawableRight实现清空EditText输入框内容,是一个比较常见的功能,一般用于搜索框。

    主要重难点

    1、自定义EditText。通过继承EditText,在构造方法中实现DrawableRight初始化,以及设置View.OnFocusChangeListener, TextWatcher监听。

    2、对DrawableRight的点击事件构造。EditText没有单独的一个实现DrawableRight点击事件,所以我们通过点击的位置判断DrawableRight是否被点击。即当按下的位置 在EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 与 EditText的宽度 - 图标到控件右边的间距之间,算点击了DrawableRight。

    代码实现

    在代码实现之前,首先要了解以下几个方法的含义:

    drawable.setBounds(int, int, int, int);
    

    该方法是Drawable类中的一个方法,表示设置图片边界,左上右下。

    setCompoundDrawables(leftDrawable, topDrawable, rightDrawable, bottomDrawable);
    

    该方法是设置EditText的Drawable,四个参数分别表示左上右下。

    getCompoundDrawables()[i]
    

    该方法是获取EditText的Drawable,获取的是一个数组,该数组有四个值,从0到3分别表示EditText左上右下的Drawable,没有的话则为null。
    了解这几个方法之后,接下来分两步实现DrawableRight清空输入值功能。

    1、自定义EditText

    在cc.ibooker.ibooker目录下创建ClearEditText,让其继承EditText,并实现构造方法。

    // 带清空功能的EditText-DrawableRight,监听焦点和输入值改变状态
    public class ClearEditText extends android.support.v7.widget.AppCompatEditText implements View.OnFocusChangeListener, TextWatcher {
        /**
         * 删除Drawable引用
         */
        private Drawable mClearDrawable;
        /**
         * 控件是否有焦点
         */
        private boolean hasFocus;
    
        // 构造方法 1->2->3
        public ClearEditText(Context context) {
            this(context, null);
        }
    
        public ClearEditText(Context context, AttributeSet attrs) {
            this(context, attrs, android.R.attr.editTextStyle);
        }
    
        public ClearEditText(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        // 初始化方法
        private void init() {
            // Drawable顺序左上右下,0123
            // 获取DrawRight内容
            mClearDrawable = getCompoundDrawables()[2];
            if (mClearDrawable == null) {
                // 未设置默认DrawableRight
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    mClearDrawable = getResources().getDrawable(R.mipmap.icon_clear, null);
                } else {
                    mClearDrawable = getResources().getDrawable(R.mipmap.icon_clear);
                }
            }
            // 设置Drawable大小和位置
            mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
            // 添加焦点改变监听
            setOnFocusChangeListener(this);
            // 添加输入内容改变监听
            addTextChangedListener(this);
        }
    
        // 焦点改变事件
        // 当焦点在时,通过判断输入值,实现隐藏和现实DrawableRight
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            this.hasFocus = hasFocus;
            if (hasFocus) {
                // 焦点存在,而且有输入值
                setDrawableRightightVisible(getText().length() > 0);
            } else {
                // 焦点不存在时候,隐藏DrawableRight
                setDrawableRightightVisible(false);
            }
        }
    
        /**
         * 隐藏或显示DrawableRight
         *
         * @param visible true=显示,false=隐藏
         */
        private void setDrawableRightightVisible(boolean visible) {
            // 控件setCompoundDrawables设置Drawable,隐藏则设置null,左上右下
            Drawable drawableRight = visible ? mClearDrawable : null;
            setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], drawableRight, getCompoundDrawables()[3]);
        }
    
        // 触摸事件-实现ClearDrawable清空功能
        // 1、如何判断Drawable被点击?——通过判断点击的位置
        // 2、什么时候实现清空?——当ClearDrawable不为空且被点击
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            // 判断手指是否触摸
            if (event.getAction() == MotionEvent.ACTION_UP) {
                // 判断ClearDrawable(DrawableRight)是否为空
                if (getCompoundDrawables()[2] != null) {
                    // 当按下的位置 在EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 与 EditText的宽度 - 图标到控件右边的间距之间,算点击了图标,竖直方向不用考虑
                    // getTotalPaddingRight获取右侧图标以及右侧Padding和
                    // getPaddingRight获取右侧Padding值
                    boolean isTouchRight = event.getX() > (getWidth() - getTotalPaddingRight()) && (event.getX() < ((getWidth() - getPaddingRight())));
                    if (isTouchRight) {
                        this.setText("");
                    }
                }
            }
            return super.onTouchEvent(event);
        }
    
        // 输入内容变化前
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            if (onTextChangedListener != null)
                onTextChangedListener.beforeTextChanged(s, start, count, after);
        }
    
        // 输入内容变化时,判断是否有输入值=有 并且焦点=存在 则显示ClearDrawable
        @Override
        public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
            if (hasFocus) {
                setDrawableRightightVisible(text.length() > 0);
            }
            if (onTextChangedListener != null)
                onTextChangedListener.onTextChanged(text, start, lengthBefore, lengthAfter);
        }
    
        // 输入内容变化后
        @Override
        public void afterTextChanged(Editable s) {
            if (onTextChangedListener != null)
                onTextChangedListener.afterTextChanged(s);
        }
    
        // 文本改变接口监听
        public interface OnTextChangedListener {
            void beforeTextChanged(CharSequence s, int start, int count, int after);
    
            void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter);
    
            void afterTextChanged(Editable s);
        }
    
        private OnTextChangedListener onTextChangedListener;
    
        public void setOnTextChangedListener(OnTextChangedListener onTextChangedListener) {
            this.onTextChangedListener = onTextChangedListener;
        }
    }
    

    2、在布局文件中引入自定义EditText

    直接将自定义的ClearEditText,引入布局XML文件即可。

    <cc.ibooker.ibooker.ClearEditText
      android:id="@+id/ed_clear"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      android:drawableEnd="@mipmap/icon_clear"
      android:drawableRight="@mipmap/icon_clear"
      android:inputType="text"
      android:padding="10dp" />
    

    3、程序结构图

    程序结构图

    Github地址
    阅读原文


    微信公众号:书客创作

    相关文章

      网友评论

        本文标题:【Android】EditText之DrawableRight清

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