效果图
attrs.xml
自定义属性
<declare-styleable name="RippleAnimationView"><attr name="ripple_anim_color" format="color" /><!-- 水波纹填充类型 --><attr name="ripple_anim_type" format="enum"><enum name="fillRipple" value="0" /><enum name="strokeRipple" value="1" /></attr><!-- 水波纹的半径 --><attr name="radius" format="integer" /><!-- 水波纹边框大小 --><attr name="stroeWidth" format="integer" /></declare-styleable>
RippleAnimationView.java
管理水波纹属性以及动画状态
public class RippleAnimationView extends RelativeLayout {private Paint paint;private int radius;private int strokeWidth;private int rippleColor;private AnimatorSet animatorSet;public RippleAnimationView(Context context) {this(context, null);}public RippleAnimationView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public RippleAnimationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint();paint.setAntiAlias(true);TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RippleAnimationView);// 水波纹填充类型int rippleType = array.getInt(R.styleable.RippleAnimationView_ripple_anim_type, 0);radius = array.getInteger(R.styleable.RippleAnimationView_radius, 54);strokeWidth = array.getInteger(R.styleable.RippleAnimationView_stroeWidth, 2);rippleColor = array.getColor(R.styleable.RippleAnimationView_ripple_anim_color, ContextCompat.getColor(context,R.color.colorAccent));array.recycle();// 设置画笔线宽paint.setStrokeWidth(UIUtils.getInstance().getWidth(strokeWidth));if (rippleType == 0) {paint.setStyle(Paint.Style.FILL);} else {paint.setStyle(Paint.Style.STROKE);}paint.setColor(rippleColor);LayoutParams params = new LayoutParams(UIUtils.getInstance().getWidth(radius + strokeWidth),UIUtils.getInstance().getWidth(radius + strokeWidth));params.addRule(CENTER_IN_PARENT, TRUE);// 缩放系数float maxScale = UIUtils.getInstance().displayMetricsWidth / (2 * UIUtils.getInstance().getWidth(radius + strokeWidth));// 延迟时间int rippleDuration = 3500;int singleDelay = rippleDuration / 4; // 时间间隔// 动画集合List<Animator> animatorList = new ArrayList<>();// 实例化水波纹viewfor (int i = 0;i<4;i++){RippleCircleView rippleCircleView = new RippleCircleView(this);addView(rippleCircleView,params);// 添加水波纹到集合viewList.add(rippleCircleView);// 初始化属性动画// xObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(rippleCircleView,"ScaleX",1.0f,maxScale);scaleXAnimator.setRepeatCount(ObjectAnimator.INFINITE);// 无限循环scaleXAnimator.setRepeatMode(ObjectAnimator.RESTART);scaleXAnimator.setStartDelay(i*singleDelay);scaleXAnimator.setDuration(rippleDuration);animatorList.add(scaleXAnimator);// yObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(rippleCircleView,"ScaleY",1.0f,maxScale);scaleYAnimator.setRepeatCount(ObjectAnimator.INFINITE);// 无限循环scaleYAnimator.setRepeatMode(ObjectAnimator.RESTART);scaleYAnimator.setStartDelay(i*singleDelay);scaleYAnimator.setDuration(rippleDuration);animatorList.add(scaleYAnimator);// alphaObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(rippleCircleView,"Alpha",1.0f,0f);alphaAnimator.setRepeatCount(ObjectAnimator.INFINITE);// 无限循环alphaAnimator.setRepeatMode(ObjectAnimator.RESTART);alphaAnimator.setStartDelay(i*singleDelay);alphaAnimator.setDuration(rippleDuration);animatorList.add(alphaAnimator);}animatorSet = new AnimatorSet();animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); // 差值器:先加速,后减速animatorSet.playTogether(animatorList);}private boolean animationRunning;private List<RippleCircleView> viewList = new ArrayList<>();/*** 开启动画*/public void startRippleAnimation(){if (!animationRunning){for (RippleCircleView rippleCircleView: viewList) {rippleCircleView.setVisibility(VISIBLE);}animatorSet.start();animationRunning = true;}}/*** 结束动画*/public void stopRippleAnimation(){if (animationRunning){// 逆序播放(从外向内播放动画)Collections.reverse(viewList);for (RippleCircleView rippleCircleView: viewList) {rippleCircleView.setVisibility(INVISIBLE);}animatorSet.end();animationRunning = false;}}public int getStrokeWidth() {return strokeWidth;}public Paint getPaint() {return paint;}public boolean isAnimationRunning() {return animationRunning;}
}
RippleCircleView.java
绘制水波纹
public class RippleCircleView extends View {private RippleAnimationView rippleAnimationView;public RippleCircleView(RippleAnimationView rippleAnimationView) {this(rippleAnimationView.getContext(),null);this.rippleAnimationView = rippleAnimationView;// 一开始隐藏this.setVisibility(INVISIBLE);}public RippleCircleView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);}public RippleCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onDraw(Canvas canvas) {int radius = Math.min(getWidth(),getHeight()) / 2;// 画圆canvas.drawCircle(radius,radius,radius - rippleAnimationView.getStrokeWidth(),rippleAnimationView.getPaint());}
}
使用水波纹动画
<com.wangyi.course.lession4.RippleAnimationView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/ripple_view"android:layout_width="match_parent"android:layout_height="match_parent"app:ripple_anim_color="#c0362e"app:stroeWidth="18"app:ripple_anim_type="strokeRipple"app:radius="150"><ImageViewandroid:id="@+id/iv_play"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_centerVertical="true"android:src="@drawable/ic_play"/>
</com.wangyi.course.lession4.RippleAnimationView>
RippleAnimationView rippleAnimationView = findViewById(R.id.ripple_view);findViewById(R.id.iv_play).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (rippleAnimationView.isAnimationRunning()) {rippleAnimationView.stopRippleAnimation();} else {rippleAnimationView.startRippleAnimation();}}});