欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

自定义View——雷达涟漪效果图(优化版)

程序员文章站 2022-06-17 10:13:16
书接上文:如果没有看的小伙伴们可以去上篇看下https://blog.csdn.net/APPLYB/article/details/110523356上篇文章中说道采用缩放动画的话,RippleView放大过程中会失真,模糊的感觉 所以这篇着重说下如何来优化这个问题这是优化后的效果 不知道你能不能看出有什么不同 扩散的过程没有模糊也没有失真分析:使用ObjectAnimator 的ScaleX和ScaleY 会放大View。但既然放大 就一定会失真,模糊,如果你看不到 只能说明放大......

书接上文:如果没有看的小伙伴们可以去上篇看下 https://blog.csdn.net/APPLYB/article/details/110523356 

上篇文章中说道 采用缩放动画的话,RippleView放大过程中会失真,模糊的感觉 所以这篇着重说下如何来优化这个问题

这是优化后的效果 不知道你能不能看出有什么不同 扩散的过程没有模糊也没有失真

自定义View——雷达涟漪效果图(优化版)

分析:使用ObjectAnimator 的 ScaleX和ScaleY 会放大View。但既然放大 就一定会失真,模糊,如果你看不到 只能说明放大的不够。既然使用这个Scale* 动画

会使View模糊,那么问题来了。有没有一种方式可以不使用 ObjectAnimator 的Scale* 也能实现和放大一样的效果呢? 这个问题的答案是当然有:

我们可以设想一样 让渐变的过程中 均匀的改变原本RippleView的圆的半径,让圆一直重绘,这样我们就可以替换掉原来的放大动画所带来的弊端,

直接上完整代码 不懂的小伙伴可以揣摩一下  关键在于对原本RippleView的改造

package com.lyb.customview.RadarView;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.RelativeLayout;

import com.lyb.customview.R;

import java.util.ArrayList;

import androidx.annotation.FloatRange;
import androidx.annotation.IntRange;
import androidx.annotation.Nullable;

/**
 * ASCustomView
 *
 * @Description: 自定义雷达view
 * @Date : 2020-11-27 10:58
 * @Author: Lyb
 */
public class RadarViewPro extends RelativeLayout {
    private static final String TAG = "Lyb";
    /**
     * 涟漪从开始到结束的动画持续时间
     */
    private @IntRange(from = 0)
    int rippleDurationTime = 3000;
    /**
     * 涟漪的数量
     */
    private @IntRange(from = 0)
    int rippleAmount = 4;
    /**
     * 涟漪的线宽
     */

    private @FloatRange(from = 0)
    float rippleStrokeWidth = 1;
    /**
     * 涟漪的画笔
     */
    private Paint ripplePaint;
    /**
     * 1. 填充 2.边框
     */
    private @IntRange(from = 1, to = 2)
    int rippleType = 1;
    /**
     * 圆的半径
     */
    private @FloatRange(from = 0)
    float rippleRadius = 50;//半径
    private ArrayList<RippleView> rippleViewList = new ArrayList<>();
    /**
     * 动画的集合
     */
    private ArrayList<Animator> animatorList;
    /**
     * 动画集
     */
    private AnimatorSet animatorSet;
    /**
     * 动画的状态
     */

    private @IntRange(from = 0, to = 2)
    int rippleAnimatorState = 0;//0 未开始  1.进行中 2 暂停状态
    /**
     * 动画的状态
     */
    private int rippleColor;//0 未开始  1.进行中 2 暂停状态

    /**
     * 放大的倍数 默认放大3倍
     */
    private @FloatRange(from = 1)
    float ScaleMultiple = 3;

    private @FloatRange(from = 0)
    float alphaStart = 1.0f;
    private @FloatRange(from = 0)
    float alphaEnd = 0f;
    private RippleView rippleView;
    private float diameter;//直径


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

    public RadarViewPro(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RadarViewPro(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RadarViewPro_style);
        rippleDurationTime = typedArray.getInteger(R.styleable.RadarViewPro_style_rippleDurationTimePro, 3000);
        rippleAmount = typedArray.getInteger(R.styleable.RadarViewPro_style_rippleAmountPro, 4);
        rippleType = typedArray.getInteger(R.styleable.RadarViewPro_style_rippleTypePro, 1);
        rippleRadius = typedArray.getFloat(R.styleable.RadarViewPro_style_rippleRadiusPro, 50);
        rippleColor = typedArray.getColor(R.styleable.RadarViewPro_style_rippleColorPro, Color.RED);

        alphaStart = typedArray.getFloat(R.styleable.RadarViewPro_style_rippleAlphaStartPro, 1.0f);
        alphaEnd = typedArray.getFloat(R.styleable.RadarViewPro_style_rippleAlphaEndPro, 0f);
        ScaleMultiple = typedArray.getFloat(R.styleable.RadarViewPro_style_ScaleMultiple, 3f);


        //半径+线宽
        diameter = 2 * (rippleRadius + rippleStrokeWidth);
        LayoutParams rippleParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        rippleParams.addRule(CENTER_IN_PARENT, TRUE);
        animatorList = new ArrayList<>();
        animatorSet = new AnimatorSet();
        ripplePaint = new Paint();
        ripplePaint.setColor(rippleColor);
        if (rippleType == 1) {
            ripplePaint.setStyle(Paint.Style.FILL);
        } else {
            ripplePaint.setStyle(Paint.Style.STROKE);
            ripplePaint.setStrokeWidth(rippleStrokeWidth);
        }
        ripplePaint.setDither(true);
        ripplePaint.setAntiAlias(true);
        int delay = rippleDurationTime / rippleAmount;
        ripplePaint.setStrokeCap(Paint.Cap.ROUND);
        for (int i = 0; i < rippleAmount; i++) {
            rippleView = new RippleView(getContext());
            rippleView.setLayoutParams(rippleParams);
            addView(rippleView);
            rippleViewList.add(rippleView);
            ObjectAnimator objectAnimator = rippleView.getObjectAnimator();
            objectAnimator.setStartDelay(i * delay);
            animatorList.add(objectAnimator);
        }
        animatorSet.setDuration(rippleDurationTime);
        Log.i(TAG, "rippleDurationTime: " + rippleDurationTime);
        animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
        animatorSet.playTogether(animatorList);
    }


    private class RippleView extends View {
        float mRippleRadius;
        private ObjectAnimator objectAnimator;
        private Paint paint;
        private int dx;//圆心 X 坐标
        private int dy;//圆心 Y 坐标

        public RippleView(Context context) {
            super(context);
            mRippleRadius = diameter / 2;
            this.setVisibility(INVISIBLE);
            paint = new Paint();
            paint.setColor(Color.RED);
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(true);
            paint.setStrokeWidth(2);
            paint.setStrokeCap(Paint.Cap.ROUND);
            objectAnimator = ObjectAnimator.ofFloat(this, "Alpha", alphaStart, alphaEnd);
            objectAnimator.setRepeatMode(ObjectAnimator.RESTART);
            objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);
            objectAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    super.onAnimationStart(animation);
                    RippleView.this.setVisibility(VISIBLE);
                }
            });
            objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float rate = (float) animation.getAnimatedValue();
                    float total = diameter * ScaleMultiple;//总量
                    //  1->0 对应 1-ScaleMultiple
                    mRippleRadius = (1 - rate) * total;
                    invalidate();
                }
            });
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            dx = getMeasuredWidth() / 2;
            dy = getMeasuredHeight() / 2;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawCircle(dx, dy, mRippleRadius - rippleStrokeWidth, ripplePaint);
            //            canvas.drawLine(0,dy,getMeasuredWidth(),dy,paint);
            //            canvas.drawLine(dx,0,dx,getMeasuredHeight(),paint);
            //            canvas.drawPoint(dx,dy,paint);
        }

        public ObjectAnimator getObjectAnimator() {
            return objectAnimator;
        }
    }

    /**
     * 开始动画
     */
    public void startRippleAnimation() {
        if (rippleAnimatorState != 1) {
            //            for (RippleView rippleView : rippleViewList) {
            //                rippleView.setVisibility(VISIBLE);
            //            }
            animatorSet.start();
            rippleAnimatorState = 1;
        }
    }

    /**
     * 停止动画
     */
    public void stopRippleAnimation() {
        if (rippleAnimatorState != 0) {
            animatorSet.end();
            rippleAnimatorState = 0;
        }
    }

    /**
     * 暂停动画
     */
    public void pauseRippleAnimation() {
        if (rippleAnimatorState != 2) {
            animatorSet.pause();
            rippleAnimatorState = 2;
        }
    }

    /**
     * 恢复动画
     */
    public void resumeRippleAnimation() {
        if (rippleAnimatorState == 2) {
            animatorSet.resume();
            rippleAnimatorState = 1;
        }
    }

}

源码已经上传  下载后直接拷贝就行https://download.csdn.net/download/APPLYB/13261198

 

 

 

 

 

本文地址:https://blog.csdn.net/APPLYB/article/details/110537998