Android 點選波紋擴散動畫

VIjolie發表於2019-03-04

前言

 國際慣例先放圖

Android 點選波紋擴散動畫

gif動畫將就看吧,要啥自行車,真機上效果還可以。

大體思路

通過繼承Drawable重寫draw()方法,通過ValueAnimator不斷改變圓的半徑,實現波紋效果。注意的一點是波紋要從手機點選抬起的位置為中心向倆邊擴散。看下程式碼:

public class WaveDrawable extends Drawable {
    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private int mViewWidth;
    private int mViewHeight;
    private ValueAnimator mValueAnimator;
    private int mRadius;

    private int mEndColor;
    private int mStartColor;
    private float mClickX;
    private float mClickY;

    public WaveDrawable(@ColorInt int originColor, @ColorInt int targetColor, int clickX, int clickY) {
        mStartColor = originColor;
        mEndColor = targetColor;
        mClickX = clickX;
        mClickY = clickY;
    }


    public void setClickXY(float clickX, float clickY) {
        mClickX = clickX;
        mClickY = clickY;
    }
    public void setColors(int startColor, int endColor) {
        mStartColor = startColor;
        mEndColor = endColor;
    }


    @Override
    public void draw(@NonNull Canvas canvas) {
        canvas.drawColor(mStartColor);
        mPaint.setColor(mEndColor);
        canvas.drawCircle(mClickX, mClickY, mRadius, mPaint);
    }

    @Override
    public void setAlpha(int alpha) {

    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {

    }

    @Override
    public int getOpacity() {
        return PixelFormat.UNKNOWN;
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        mViewWidth = Math.abs(bounds.width());
        mViewHeight = Math.abs(bounds.height());
        int maxRadius = (int) Math.sqrt((mViewWidth * mViewWidth + mViewHeight * mViewHeight));

        mValueAnimator = ValueAnimator.ofInt(0, maxRadius);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //改變波紋半徑
                mRadius = (int) animation.getAnimatedValue();
                invalidateSelf();
            }
        });
        mValueAnimator.setDuration(500);
    }

    /**
     * 波紋擴散動畫開始
     */
    public void start() {
        if (mValueAnimator != null) {
            mValueAnimator.start();
        }
    }


}複製程式碼

在 onBoundsChange()中,計算了最大半徑,並初始化了mValueAnimator ,實現半徑的不斷變化,通過invalidateSelf(),不斷呼叫draw()繪製半徑不斷增大的圓,形成波紋擴散效果。

那麼問題來了,怎麼獲取當前手指點選的位置呢?其實很簡單隻要在對應的View中重寫dispatchTouchEvent(),那麼event.getAction() == MotionEvent.ACTION_UP的時候,獲取當前事件的座標就行了看下程式碼:

public class WaveTextView extends android.support.v7.widget.AppCompatTextView {
    private int mStartColor = Color.parseColor("#FF5555");
    private int mEndColor = Color.parseColor("#23C865");
    private WaveDrawable mWaveDrawable = new WaveDrawable(mStartColor, mEndColor, 0, 0);
    private boolean mIsSwitch;

    public WaveTextView(Context context) {
        this(context, null);
    }

    public WaveTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WaveTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setClickable(true);
        setBackground(mWaveDrawable);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            //為了測試方便看效果加的
            if (mIsSwitch) {
                mWaveDrawable.setColors(mEndColor, mStartColor);
            } else {
                mWaveDrawable.setColors(mStartColor, mEndColor);
            }
            mWaveDrawable.setClickXY(event.getX(), event.getY());
            mWaveDrawable.start();
            mIsSwitch = !mIsSwitch;

        }
        return super.dispatchTouchEvent(event);
    }

}複製程式碼

注意 setClickable(true)最好設定下,要不然對於TextView這種View的話如果沒有setOnClickListener()是預設收不到MotionEvent.ACTION_UP事件。

後記

這種效果實現起來很簡單,但是細節還不少像setClickable(true)的問題在原始碼裡面找了好一會才定位到問題,程式碼github,覺得對你有幫助的話,順手給個星吧!

碼字不易,期待各位的讚賞!!!

Android 點選波紋擴散動畫    Android 點選波紋擴散動畫


相關文章