Android_自定义波纹view

常见的水波纹效果:如下

这里写图片描述

然后换各种不同的颜色

这里写图片描述

我们给属性动画加一句动画的模式即可实现这样效果

这里写图片描述

实现思路

会画圆就能画波纹,会画波纹就能动

  • 初始化一组数据包括每个波纹段的颜色,
  • 对应的颜色初始化对应的画笔,
  • 绘制静态的圆圈

工作完成了一大半,剩下的就是这个圆环动画的效果,就是让圆圈的半径从0到最大,ok 一个属性动画搞定,


  1. 初始化内容
//构造波纹属性
     private void initTools() {
        paints = new ArrayList<>();
        circleRadiusList = new ArrayList<>();
        waveColors = new ArrayList<>();
        waveColors.add(ContextCompat.getColor(getContext(), android.R.color.white));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_20));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_40));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_60));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_80));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_100));


        for (int paintColor : waveColors) {
            Paint tempPaint = new Paint();
            tempPaint.setColor(paintColor);
            tempPaint.setAntiAlias(true);
            tempPaint.setStrokeJoin(Paint.Join.ROUND);
            tempPaint.setStrokeCap(Paint.Cap.ROUND);
            tempPaint.setStyle(Paint.Style.FILL);
            paints.add(tempPaint);

            CircleRadiuEntity c = new CircleRadiuEntity();
            circleRadiusList.add(c);
        }

    }

接下来就是出事后对应的属性动画

//这里只有一点需要注意的就是,每个index对应的属性动画启动的间隔是当前的角标 * 时间间隔
   public void startWave() {
        for (int i = 0; i < waveColors.size(); i++) {
            ValueAnimator valueAnimatorC = ValueAnimator.ofFloat(0F, 1F);
            final int finalI = i;
            valueAnimatorC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                //计算当前动画时间内,每个圆圈半径的变化
                    Float aFloat = Float.valueOf(animation.getAnimatedValue().toString());
                    circleRadiusList.get(finalI).setRadius((int) (maxRadius * aFloat));
                    invalidate();
                }
            });
            valueAnimatorC.setRepeatCount(ValueAnimator.INFINITE);
            valueAnimatorC.setRepeatMode(ValueAnimator.REVERSE);
            valueAnimatorC.setDuration(UNIT_TIME * waveColors.size());
            valueAnimatorC.setStartDelay(i * UNIT_TIME);
            valueAnimatorC.start();
        }
    }

最后就是ondraw

//API非常简单就是根据我们计算的圆的半径绘制即可
  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < paints.size(); i++) {
            Paint currentCirclePaint = paints.get(i);
            int currentCircleRadius = circleRadiusList.get(i).getRadius();
            canvas.drawCircle(circelCenterPoint.x, circelCenterPoint.y, currentCircleRadius, currentCirclePaint);
        }
    }

代码非常简单就100行代码,完整的项目就不上传了,把完整的类放到最后,有兴趣的可以粘贴到项目中,

public class ClearCircleView extends View {
    private static final int DEF_VIEW_SIZE = 200;
    private static final int UNIT_TIME = 300;

    private Point circelCenterPoint;
    private int maxRadius;
    private ArrayList<Integer> waveColors;

    private List<Paint> paints;
    private List<CircleRadiuEntity> circleRadiusList;

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

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

    public ClearCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initTools();
    }

    private void initTools() {
        paints = new ArrayList<>();
        circleRadiusList = new ArrayList<>();
        waveColors = new ArrayList<>();
        waveColors.add(ContextCompat.getColor(getContext(), android.R.color.white));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_20));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_40));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_60));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_80));
        waveColors.add(ContextCompat.getColor(getContext(), R.color.color_gray_100));

//        waveColors.add(ContextCompat.getColor(getContext(), R.color.colorAccent));
//        waveColors.add(ContextCompat.getColor(getContext(), R.color.colorPrimary));
//        waveColors.add(ContextCompat.getColor(getContext(), android.R.color.holo_green_light));
//        waveColors.add(ContextCompat.getColor(getContext(), android.R.color.holo_orange_light));
//        waveColors.add(ContextCompat.getColor(getContext(), android.R.color.holo_red_light));
//        waveColors.add(ContextCompat.getColor(getContext(), android.R.color.holo_purple));
//        waveColors.add(ContextCompat.getColor(getContext(), android.R.color.white));

        for (int paintColor : waveColors) {
            Paint tempPaint = new Paint();
            tempPaint.setColor(paintColor);
            tempPaint.setAntiAlias(true);
            tempPaint.setStrokeJoin(Paint.Join.ROUND);
            tempPaint.setStrokeCap(Paint.Cap.ROUND);
            tempPaint.setStyle(Paint.Style.FILL);
            paints.add(tempPaint);

            CircleRadiuEntity c = new CircleRadiuEntity();
            circleRadiusList.add(c);
        }

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        circelCenterPoint = new Point(w / 2, h / 2);
        maxRadius = Math.min(w, h) / 2;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMeasureMode = MeasureSpec.getMode(heightMeasureSpec);

        int widthMeaure;
        int heightMeaure;

        if (widthMeasureMode == MeasureSpec.AT_MOST || widthMeasureMode == MeasureSpec.UNSPECIFIED) {
            widthMeaure = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEF_VIEW_SIZE, getResources().getDisplayMetrics());
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthMeaure, MeasureSpec.EXACTLY);
        }

        if (heightMeasureMode == MeasureSpec.AT_MOST || heightMeasureMode == MeasureSpec.UNSPECIFIED) {
            heightMeaure = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEF_VIEW_SIZE, getResources().getDisplayMetrics());
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightMeaure, MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < paints.size(); i++) {
            Paint currentCirclePaint = paints.get(i);
            int currentCircleRadius = circleRadiusList.get(i).getRadius();
            canvas.drawCircle(circelCenterPoint.x, circelCenterPoint.y, currentCircleRadius, currentCirclePaint);
        }
    }

    public void startWave() {
        for (int i = 0; i < waveColors.size(); i++) {
            ValueAnimator valueAnimatorC = ValueAnimator.ofFloat(0F, 1F);
            final int finalI = i;
            valueAnimatorC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    Float aFloat = Float.valueOf(animation.getAnimatedValue().toString());
                    circleRadiusList.get(finalI).setRadius((int) (maxRadius * aFloat));
                    invalidate();
                }
            });
            valueAnimatorC.setRepeatCount(ValueAnimator.INFINITE);
            valueAnimatorC.setRepeatMode(ValueAnimator.REVERSE);
            valueAnimatorC.setDuration(UNIT_TIME * waveColors.size());
            valueAnimatorC.setStartDelay(i * UNIT_TIME);
            valueAnimatorC.start();
        }
    }

    class CircleRadiuEntity {
        int radius;

        int getRadius() {
            return radius;
        }

        void setRadius(int radius) {
            this.radius = radius;
        }
    }
}

END

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值