波紋盪漾效果

前言

自從看大神的"風扇吹樹葉"的自定義控件,是根據Gif圖來作的。 我看到有意思的Gif圖,也會想着該如何實現。
so,從一個簡單的開始。
canvas

ripple_gif

沒什麼複雜的東西,圓心是個圓形。一共有三條波紋,從圓形中發出。效果圖以下。bash

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 + paddingide

@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進行取值。post

@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);
  }


複製代碼
相關文章
相關標籤/搜索