preface
International practice puts the picture first
GIF animation will see, to what bike, real machine effect is ok.
General train of thought
Rewrite the draw() method by inheriting Drawable, and use ValueAnimator to constantly change the radius of the circle to achieve the ripple effect. One thing to note is that the ripple should spread from the center of the cell phone to the edge of the lift. Take a look at the code:
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) {// Change the circle radius. animation.getAnimatedValue(); invalidateSelf(); }}); mValueAnimator.setDuration(500); } /** * Ripple spread animation starts */ public voidstart() {
if(mValueAnimator ! = null) { mValueAnimator.start(); }}}Copy the code
In onBoundsChange(), we calculate the maximum radius and initialize the mValueAnimator to make the radius change constantly. With invalidateSelf(), we call Draw () to draw a circle with an increasing radius to create a ripple effect.
So the question is, how do you get the current finger click position? It’s very simple to override dispatchTouchEvent() in the corresponding View, and when event.getAction() == motionEvent.action_up, get the coordinates of the current event and look at the code:
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) {
ifACTION_UP (event.getAction() == motionEvent.action_up) {// This is added for testing purposesif (mIsSwitch) {
mWaveDrawable.setColors(mEndColor, mStartColor);
} else{ mWaveDrawable.setColors(mStartColor, mEndColor); } mWaveDrawable.setClickXY(event.getX(), event.getY()); mWaveDrawable.start(); mIsSwitch = ! mIsSwitch; }returnsuper.dispatchTouchEvent(event); }}Copy the code
Note that setClickable(true) is best set, otherwise a View like TextView without setOnClickListener() will not receive motionEvent.action_UP events by default.
Afterword.
This effect is very simple to implement, but there are many details like setClickable(true) problem in the source code to find a long time to locate the problem, code github, feel helpful to you, handy to give a star bar!
Code word is not easy, look forward to your appreciation!!