自定义带删除按钮的 Edittext 并伴随动画效果

本文介绍如何在Android应用中实现一个带有动画效果的删除按钮的EditText组件。该组件会在输入框内容变化时动态显示或隐藏一个旋转并渐显渐隐的删除图标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上效果图:
这里写图片描述
这个效果感觉一般在登录注册等场合的时候比较常见。今天来看看具体效果的实现。是几天前在掘金上看到的一个效果。当时觉得好玩,就看着敲,结果作者没有给源码,其中有一部分代码没有给出,无奈写到一半时突然有点小失落。不过已经做了一半了,怎么可能半途而废,况且这个也不是本人的一贯作风。哈哈。于是乎就自己从新研究最后经过总结和优化才有了现在的完美效果。
后面我会附上源码
由于我把实现思路和方法说明都都在代码中注释的相当清楚,这里就不多废话了,直接上代码:

1.iamge_rotate.xml

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/del"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="225">
    <!--旋转角度是从0转到225度,旋转的中心位置在图片X轴和Y轴的中心位置。-->

</rotate>

2.创建一个ClearAllEditText继承自EditText,其实里面第二个方法不用重写,但是由于本人习惯一般都把三个都写上了,没用就让他们放着就行。

**
 * 作者: NanFeiLong
 * 日期: 2017/3/22 21:56
 * 自定义带动画效果删除按钮的 Edittext
 */

public class ClearAllEditText extends android.support.v7.widget.AppCompatEditText {
    private RotateDrawable drawableRotate;
    //从无到有
    private ValueAnimator alphaAnimator = ValueAnimator.ofInt(0, 255);//透明度变化
    private ValueAnimator rotateAnimator = ValueAnimator.ofInt(0, 10000);//旋转角度
    //从有到无
    private ValueAnimator alphaAnimator2 = ValueAnimator.ofInt(255, 0);//通明度变化
    private ValueAnimator rotateAnimator2 = ValueAnimator.ofInt(10000, 0);//旋转角度

    public ClearAllEditText(Context context) {
        super(context);
    }

    public ClearAllEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ClearAllEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        setIconVisible(false, getCompoundDrawables());
    }


    /**
     * 设置右侧删除图标
     *
     * @param isShow 判断是否显示删除图标 true显示
     * @param compoundDrawables
     */
    private void setIconVisible(boolean isShow, Drawable[] compoundDrawables) {
        if (isShow) {
            //左上右下
            //若同时xml和java代码中都设置了,则以java中设置为准
            setCompoundDrawablesWithIntrinsicBounds(compoundDrawables[0], compoundDrawables[1],
                    getResources().getDrawable(R.drawable.iamge_rotate), compoundDrawables[3]);
            //getCompoundDrawables()返回的是一个drawable数组,长度是4,对应的图标位置是左上右下,
            // 即使你没有设置任何drawable,这时的四个值都为null。
            drawableRotate = (RotateDrawable) getCompoundDrawables()[2];
        } else {
            setCompoundDrawablesWithIntrinsicBounds(compoundDrawables[0], compoundDrawables[1], null, compoundDrawables[3]);
        }
    }

    /**
     * 当内容发生变化时
     *
     * @param text
     * @param start
     * @param lengthBefore
     * @param lengthAfter
     */
    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        if (text.length() == 0 && lengthBefore > 0) {
            //从有文字删除到无文字的时候
            startAnimatorSetResver();
            setAnimator(alphaAnimator2, rotateAnimator2);
            return;
        }
        if (start == 0 && text.length() > 0) {
            //从无文字到有文字
            setIconVisible(true, getCompoundDrawables());
            setAnimator(alphaAnimator, rotateAnimator);
            startAnimatorSet();
        }
    }

    /**
     * 从有文字删除到无文字的时候
     */
    private void startAnimatorSetResver() {
        AnimatorSet setVisible = new AnimatorSet();
        setVisible.playTogether(alphaAnimator2, rotateAnimator2);
        setVisible.start();
        setVisible.addListener(new Animator.AnimatorListener() {
            //开始
            @Override
            public void onAnimationStart(Animator animation) {

            }

            //结束
            @Override
            public void onAnimationEnd(Animator animation) {
                setIconVisible(false, getCompoundDrawables());
            }

            //取消
            @Override
            public void onAnimationCancel(Animator animation) {

            }

            //重复
            @Override
            public void onAnimationRepeat(Animator animation) {

            }

        });


    }

    /**
     * 将透明度 旋转角度 放在动画集合
     * 同时启动两个动画
     */
    private void startAnimatorSet() {
        AnimatorSet setVisible = new AnimatorSet();
        setVisible.playTogether(alphaAnimator, rotateAnimator);
        setVisible.start();
    }

    /**
     * 动画效果
     *
     * @param alphaAnimator  透明度变化
     * @param rotateAnimator 旋转角度变化
     */
    private void setAnimator(ValueAnimator alphaAnimator, ValueAnimator rotateAnimator) {
        //设置透明度变化
        alphaAnimator.setDuration(1000);
        alphaAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        alphaAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //setAlpha(),这个alpha就是透明度,范围是0-255。
                drawableRotate.setAlpha((Integer) animation.getAnimatedValue());
            }
        });

        //设置旋转角度变化
        rotateAnimator.setDuration(1000);
        rotateAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        rotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //setLevel(),这个level就是设置的旋转角度,范围是1-10000
                // 假如你是用的是ScaleDrawable,这个level控制就是你的图片的大小
                drawableRotate.setLevel((Integer) animation.getAnimatedValue());
            }
        });
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                //在手指离开屏幕时是否正在图片上的判断,然后将内容设置为空
                //判断手指离开屏幕的位置的方法是这样的:
                // api中有这样的方法:getWidth返回的是控件的宽度,
                // getTotalPadingRight返回的是空间右边的padding,
                // 包含了drawable,getPaddingRight返回的是view右边的padding,
                // 要是包含滚动条,滚动条的宽度也在pading内。
                //这里方便的话,自己找张纸按照这个思路画个草图就会一目了然 根据什么判断删除按钮的范围的
                if (getCompoundDrawables()[2] != null) {
                    if (getWidth() - getTotalPaddingRight() < event.getX() &&
                            getWidth() - getPaddingRight() > event.getX()) {
                        this.setText("");
                        Log.i("点到了删除图片", "删除图标");

                    }
                }
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }
}

3.最后是如何引用

public class MainActivity extends AppCompatActivity {
    private ClearAllEditText clearAllEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        clearAllEditText = (ClearAllEditText) findViewById(R.id.text);
    }
}

这个代码没什么解释了了,

源码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值