波纹荡漾效果

·  阅读 1710

前言

自从看大神的"风扇吹树叶"的自定义控件,是根据Gif图来做的。 我看到有意思的Gif图,也会想着该如何实现。
so,从一个简单的开始。

ripple_gif

没什么复杂的东西,圆心是个圆形。一共有三条波纹,从圆形中发出。效果图如下。

ripple_gif

初始化

public class RippleView extends BaseView {
    // 绘图
    private int mRadius = DisplayUtils.dp2px(this.getContext(), 30);
    private int mFirstRip = DisplayUtils.dp2px(this.getContext(), 20);
    private int mSecondRip = DisplayUtils.dp2px(this.getContext(), 40);
    private int mThirdRip = DisplayUtils.dp2px(this.getContext(), 60);
    // 动画
    private ValueAnimator mValueAnimator;
    private float mAnimationValue;

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

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

    public RippleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint.setStrokeWidth(DisplayUtils.dp2px(this.getContext(), 1));
        mValueAnimator = ValueAnimator.ofFloat(0, 1).setDuration(1000);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAnimationValue = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        mValueAnimator.setRepeatCount(-1);

        mValueAnimator.start();

    }

复制代码

测量View大小

也比较容易理解,View的大小 = 内心圆直径 + 最大波浪的最终位置 + margin + padding


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int measuredWidth = width, measuredHeight = height;
        if (widthMode != MeasureSpec.EXACTLY) {
            measuredWidth = mRadius * 2 + mThirdRip * 2 + mMargin * 2 + mPadding * 2;
        }
        if (heightMode != MeasureSpec.EXACTLY) {
            measuredHeight = mRadius * 2 + mThirdRip * 2 + mMargin * 2 + mPadding * 2;
        }
        setMeasuredDimension(measuredWidth, measuredHeight);
    }
复制代码

绘制

绘制内心圆,三个波浪。波浪根据mAnimationValue进行取值。


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(mViewWidth / 2, mViewHeight / 2);
        canvas.save();
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.drawCircle(0, 0, mRadius, mPaint);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(0, 0, mRadius + mFirstRip * mAnimationValue, mPaint);
        canvas.drawCircle(0, 0, mRadius + mSecondRip * mAnimationValue, mPaint);
        canvas.drawCircle(0, 0, mRadius + mThirdRip * mAnimationValue, mPaint);
        postInvalidate();
        canvas.restore();
    }
复制代码

调控速度

速度最小值为1,最大值为100. 由SeekBar控制。到此结束。

    public void setSpeed(int speed) {
        long l = (long) (1000  * (1-(speed * 1.0f) / 100f));
        mValueAnimator.setDuration(l);
    }
}



@Override
  public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
      mRippleView.setSpeed(progress);
  }


复制代码
分类:
Android
标签: