前言
國際慣例先放圖
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,覺得對你有幫助的話,順手給個星吧!
碼字不易,期待各位的讚賞!!!