Решение ScaleAnimation
, предоставленное Ves , будет работать, но я подумал, что мог бы также погрузиться в него и сделать правильный (и, я думаю, более эффективный) кастом View
.Особенно, когда речь идет о нескольких «рябях».
Это весь класс View, в init()
можно внести изменения в рябь, чтобы изменитьцвета, количество ряби и т. д.
RippleView.java
public class RippleView extends View implements ValueAnimator.AnimatorUpdateListener {
public static final String TAG = "RippleView";
private class Ripple {
AnimatorSet mAnimatorSet;
ValueAnimator mRadiusAnimator;
ValueAnimator mAlphaAnimator;
Paint mPaint;
Ripple(float startRadiusFraction, float stopRadiusFraction, float startAlpha, float stopAlpha, int color, long delay, long duration, float strokeWidth, ValueAnimator.AnimatorUpdateListener updateListener){
mRadiusAnimator = ValueAnimator.ofFloat(startRadiusFraction, stopRadiusFraction);
mRadiusAnimator.setDuration(duration);
mRadiusAnimator.setRepeatCount(ValueAnimator.INFINITE);
mRadiusAnimator.addUpdateListener(updateListener);
mRadiusAnimator.setInterpolator(new DecelerateInterpolator());
mAlphaAnimator = ValueAnimator.ofFloat(startAlpha, stopAlpha);
mAlphaAnimator.setDuration(duration);
mAlphaAnimator.setRepeatCount(ValueAnimator.INFINITE);
mAlphaAnimator.addUpdateListener(updateListener);
mAlphaAnimator.setInterpolator(new DecelerateInterpolator());
mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(mRadiusAnimator, mAlphaAnimator);
mAnimatorSet.setStartDelay(delay);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(color);
mPaint.setAlpha((int)(255*startAlpha));
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(strokeWidth);
}
void draw(Canvas canvas, int centerX, int centerY, float radiusMultiplicator){
mPaint.setAlpha( (int)(255*(float)mAlphaAnimator.getAnimatedValue()) );
canvas.drawCircle(centerX, centerY, (float)mRadiusAnimator.getAnimatedValue()*radiusMultiplicator, mPaint);
}
void startAnimation(){
mAnimatorSet.start();
}
void stopAnimation(){
mAnimatorSet.cancel();
}
}
private List<Ripple> mRipples = new ArrayList<>();
public RippleView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public RippleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public RippleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if( isInEditMode() )
return;
/*
Tweak your ripples here!
*/
mRipples = new ArrayList<>();
mRipples.add(new Ripple(0.0f, 1.0f, 1.0f, 0.0f, Color.RED, 0, 2000, 4, this));
mRipples.add(new Ripple(0.0f, 1.0f, 1.0f, 0.0f, Color.WHITE, 500, 2000, 4, this));
}
public void startAnimation() {
setVisibility(View.VISIBLE);
for (Ripple ripple : mRipples) {
ripple.startAnimation();
}
}
public void stopAnimation() {
for (Ripple ripple : mRipples) {
ripple.stopAnimation();
}
setVisibility(View.GONE);
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
int centerX = getWidth()/2;
int centerY = getHeight()/2;
int radiusMultiplicator = getWidth()/2;
for (Ripple ripple : mRipples) {
ripple.draw(canvas, centerX, centerY, radiusMultiplicator);
}
}
}
Просто позвоните .startAnimation()
на RippleView
, чтобы запустить анимацию.
RippleView r = findViewById(R.id.rippleView);
r.startAnimation();