关于自定义view--实现自定义水波纹效果

开发中的东西太多,怕自己忘记了,简单记录一下。

声明:此控件借鉴了大佬的想法,在此感谢大佬提供的支持,我只是把大佬的想法拿出来而已。

ok,废话到此结束,看效果:

分析一下,我们可以看到,图中有两个圆:stop状态下,黄色的默认图,start状态下,水波纹效果的黑色的圆,默认状态下下的圆没什么好说的,直接通过

canvas.drawCircle

绘制一个圆就好,关键是,点击start之后,黑色的圆的水波纹怎么搞。我们可以观察这个水波纹,他是由好多个透明度同的圆来组成的,我们就可以在绘制这个黑色的圆的时候,通过设定他的半径和透明度的方式来实现这样一个效果。

下面还是上代码吧,再下去,我自己都晕了

public class WaterRippleView extends android.support.v7.widget.AppCompatTextView {
    /**
     * 波纹生成时的半径
     */
    private float mWaveRadiusMin;
    /**
     * 波纹消失前的半径
     */
    private float mWaveRadiusMax;
    /**
     * 每条波纹持续时间
     */
    private long mWaveDuration;
    private Paint mPaint;
    /**
     * 中间圆圈的画笔
     */
    private Paint mCenterCirclePaint;
    /**
     * 画笔是否为stroke模式(即线条)
     */
    private boolean stroke = false;
    /**
     * 波纹颜色
     */
    private int mWaveColor;
    /**
     * 波纹停止的颜色
     */
    private int mWaveStopColor;
    /**
     * 波纹动画效果
     */
    private Interpolator mInterpolator = new DecelerateInterpolator();
    private boolean mIsRunning;
    private int mStopCircleColor;
    private int mCenterCircleRadius;
    /**
     * 动画集合
     */
    private ArrayList<ValueAnimator> mAnimators;

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

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

    public WaterRippleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //执行初始化
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.WaterRippleView, 0, defStyleAttr);
        mWaveColor = typedArray.getColor(R.styleable.WaterRippleView_color, Color.BLUE);
        mStopCircleColor = getResources().getColor(R.color.income_top);//设置停止状态下的颜色--默认值
        mWaveStopColor = typedArray.getColor(R.styleable.WaterRippleView_stopColor, Color.BLUE);//设置停止状态下的额颜色--xml
        mWaveDuration = typedArray.getInteger(R.styleable.WaterRippleView_duration, 3000);
        stroke = typedArray.getBoolean(R.styleable.WaterRippleView_stroke, false);//是否开启水波纹效果
        typedArray.recycle();//释放掉TypedArray
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//设置抗锯齿
        mPaint.setDither(true);

        mPaint.setStrokeWidth(3);//设置线的粗细
        mAnimators = new ArrayList<>();
        mCenterCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCenterCirclePaint.setStyle(Paint.Style.FILL);
        mCenterCirclePaint.setColor(mStopCircleColor);
        if (stroke) {
            mPaint.setStyle(Paint.Style.STROKE);
        } else {
            mPaint.setStyle(Paint.Style.FILL);
        }
    }

    private ValueAnimator createAnimator() {
        ValueAnimator animator = new ValueAnimator();
        animator.setFloatValues(mWaveRadiusMin, mWaveRadiusMax);
        L.d("mWaveRadiusMin", mWaveRadiusMin + "");
        L.d("mWaveRadiusMax", mWaveRadiusMax + "");
        animator.setDuration(mWaveDuration);
        animator.setRepeatCount(-1);
        animator.setInterpolator(mInterpolator);
        return animator;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);
        mCenterCircleRadius = (int) (size / 2 * 0.8);
        mWaveRadiusMin = mCenterCircleRadius;
        mWaveRadiusMax = size / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int cX = getMeasuredWidth() / 2;
        int cY = getMeasuredHeight() / 2;
        if (mIsRunning) {
            if (mAnimators.size() > 0) {
                for (ValueAnimator mAnimator : mAnimators) {
                    if (mAnimator != null) {
                        float animatorValue = (float) mAnimator.getAnimatedValue();
                        L.d("animatorValue", "" + animatorValue);
                        //设置透明度
                        int alpha = getAlpha(animatorValue);
                        mPaint.setAlpha(alpha);
                        //画水波纹
                        canvas.drawCircle(cX, cY, animatorValue, mPaint);
                    }
                }
            }
        }
        canvas.drawCircle(cX, cY, mCenterCircleRadius, mCenterCirclePaint);
        postInvalidate();
        super.onDraw(canvas);
    }

    private void createAnimators() {
        for (int i = 0; i < 3; i++) {
            mAnimators.add(createAnimator());
        }
    }

    //开启动画
    public void start() {
        if (mIsRunning) {
            return;
        }
        mIsRunning = true;
        mPaint.setColor(mWaveColor);
        mCenterCirclePaint.setColor(mWaveColor);
        if (mAnimators.size() == 0) {
            createAnimators();
        }
        final int size = mAnimators.size();
        for (int i = 0; i < size; i++) {
            final int index = i;
            postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (mIsRunning && index < size) {
                        mAnimators.get(index).start();
                    }
                }
            }, (long) (mWaveDuration * index * 1f / size));
        }
        postInvalidate();
    }

    //是否开启水波纹
    public boolean isStart() {
        for (ValueAnimator mAnimator : mAnimators) {
            if (mAnimator == null && !mAnimator.isRunning()) {
                return false;
            }
        }
        return true;
    }

    //关闭动画
    public void stop() {
        mIsRunning = false;
        mPaint.setColor(mStopCircleColor);
        mCenterCirclePaint.setColor(mStopCircleColor);
        for (ValueAnimator mAnimator : mAnimators) {
            if (mAnimator != null) {
                mAnimator.cancel();

            }
        }
        mAnimators.clear();
    }

    //设置水波纹颜色
    public void setColor(int color) {
        mWaveColor = color;
        postInvalidate();
    }

    //设计水波纹持续时间
    public void setDuration(long duration) {
        mWaveDuration = duration;
        postInvalidate();
    }

    //是否画笔stroke
    public void setStroke(boolean stroke) {
        this.stroke = stroke;
        postInvalidate();
    }

    public boolean isStroke() {
        return stroke;
    }


    //获取水波纹透明度
    private int getAlpha(float mRadius) {
        int alpha = 1;
        if (mWaveRadiusMax > 0) {
            alpha = (int) ((1 - (mRadius - mWaveRadiusMin) / (mWaveRadiusMax - mWaveRadiusMin)) * 127);
        }
        return alpha;
    }

}

  XML中引用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Button
android:id="@+id/click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="start" />

<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="stop" />

<com.zhd.admin.androldlrden.view.WaterRippleView
android:id="@+id/wrv_water"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
app:color="@color/dig_wave"
app:duration="1500"
app:stopColor="#00000000"
app:stroke="false"
app:waveCreateSpeed="500" />
</LinearLayout>

  Activity中使用:

public class MainActivity extends AppCompatActivity {

    private WaterRippleView waterRippleView;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        waterRippleView = findViewById(R.id.wrv_water);
        textView = findViewById(R.id.click);
    }

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.click:
                waterRippleView.setStroke(true);
                waterRippleView.start();
                break;
            case R.id.stop:
                waterRippleView.stop();
                break;
        }
    }
}

  ok,这样就可以了。

  PS:第一次写这种东西,说的不是很清楚,欢迎大家补充,以后会不定期记录自己学到的东西。


-------------------------羞耻的分割线-------------------------------
更新一下项目地址

https://github.com/zhddream/WaterRippleView

  

 

转载于:https://www.cnblogs.com/zhdsky/p/8892272.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值