Custom water ripple effect

First, look at the results:

To achieve this effect, in fact, we need to analyze a few animation. Obviously a small round is started, the outer diffusion slowly, so there are two animations, x-axis scale animation, y-axis scale animation. Also in the process of diffusion, the circle of transparency is constantly changing, so there is a transparency of the animation. To sum up, there are three animation, as follows:

  • Animation x-axis, the corresponding attribute is ScaleX
  • Y-axis property animation object is ScaleY
  • Transparency animation, the corresponding attribute is Alpha (1 -> 0)

Let's look at how to implement the code.

1, a custom container, inherited RelativeLayout. For several water ripples management need to be performed, where the use of four water ripples

2, custom water ripples, inherited from View.

 

Custom container class: Add 4 ripple


public class MyAnimationRelativeLayout extends RelativeLayout {
    private float radius;
    private float strokeWidth;
    private int strokeColor;
    private List<MyCircleView> mViewList;
    private AnimatorSet animatorSet;
    private boolean isRunning = false;

    public MyAnimationRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.waterView);
        radius = array.getDimension(R.styleable.waterView_radius,54);
        strokeWidth = array.getDimension(R.styleable.waterView_strokeWidth,4);
        strokeColor = array.getColor(R.styleable.waterView_waterColor,context.getResources().getColor(R.color.colorPrimary));
        array.recycle();

        initView();
    }

    public int getStrokeColor() {
        return strokeColor;
    }

    public void setStrokeColor(int strokeColor) {
        this.strokeColor = strokeColor;
    }

    public float getStrokeWidth() {
        return strokeWidth;
    }

    public void setStrokeWidth(float strokeWidth) {
        this.strokeWidth = strokeWidth;
    }

    private void initView(){
        mViewList = new ArrayList<>();
        animatorSet = new AnimatorSet();
        List<Animator> animationList = new ArrayList<>();
        LayoutParams lp = new LayoutParams((int)radius,(int)radius);
        lp.addRule(CENTER_IN_PARENT);

        int scaleFlag = 5;//缩放系数
        int animTime = 3500;
        int perTime = 3500/4;
        for(int i=0;i<4;i++){
            MyCircleView myCircleView = new MyCircleView(this);
            addView(myCircleView,lp);
            mViewList.add(myCircleView);

            //设置x缩放动画
            ObjectAnimator xScaleAnim = ObjectAnimator.ofFloat(myCircleView,"ScaleX",1,scaleFlag);
            xScaleAnim.setDuration(animTime);
            xScaleAnim.setRepeatCount(ValueAnimator.INFINITE);
            xScaleAnim.setRepeatMode(ValueAnimator.RESTART);
            xScaleAnim.setStartDelay(perTime*i);
            //设置y缩放动画
            ObjectAnimator yScaleAnim = ObjectAnimator.ofFloat(myCircleView,"ScaleY",1,scaleFlag);
            yScaleAnim.setDuration(animTime);
            yScaleAnim.setRepeatCount(ValueAnimator.INFINITE);
            yScaleAnim.setRepeatMode(ValueAnimator.RESTART);
            yScaleAnim.setStartDelay(perTime*i);
            //设置透明度变化
            ObjectAnimator aScaleAnim = ObjectAnimator.ofFloat(myCircleView,"Alpha",1,0);
            aScaleAnim.setDuration(animTime);
            aScaleAnim.setRepeatMode(ValueAnimator.RESTART);
            aScaleAnim.setRepeatCount(ValueAnimator.INFINITE);
            aScaleAnim.setStartDelay(perTime*i);

            animationList.add(xScaleAnim);
            animationList.add(yScaleAnim);
            animationList.add(aScaleAnim);

        }

        animatorSet.setDuration(animTime);
        animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
        animatorSet.playTogether(animationList);

    }

    public boolean isRunning() {
        return isRunning;
    }



    /**
     * 开始动画
     */

    public void startAnim(){

        if(!isRunning){
            isRunning = true;
            for (MyCircleView myCircleView : mViewList) {
                myCircleView.setVisibility(VISIBLE);
            }

            animatorSet.start();
        }
    }

    public void stopAnim(){
        if(isRunning){
            isRunning = false;
            //倒叙一下, 从外往里面停止
            Collections.reverse(mViewList);
            for (MyCircleView myCircleView : mViewList) {
                myCircleView.setVisibility(INVISIBLE);
            }
            animatorSet.end();
        }

    }




}

Custom properties file attrs: ripple color may be provided, the radius

<declare-styleable name="waterView">
        <attr name="radius" format="dimension"/>
        <attr name="strokeWidth" format="dimension"/>
        <attr name="waterColor" format="color"/>

    </declare-styleable>

Custom water ripples: Main draw a circle


public class MyCircleView extends View {

    private Paint mPaint;
    private MyAnimationRelativeLayout myAnimationRelativeLayout;

    public MyCircleView(MyAnimationRelativeLayout myAnimationRelativeLayout) {
        this(myAnimationRelativeLayout.getContext(),null);
        this.myAnimationRelativeLayout = myAnimationRelativeLayout;
        setVisibility(INVISIBLE);//默认不可见
        initPaint();
    }

    public MyCircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

    }


    private void initPaint(){
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(myAnimationRelativeLayout.getStrokeColor());
        mPaint.setStrokeWidth(myAnimationRelativeLayout.getStrokeWidth());
        mPaint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //设置半径
        int radius = Math.min(canvas.getHeight()/2,canvas.getWidth()/2);
        //中心点位置
        canvas.drawCircle(radius,radius,radius-myAnimationRelativeLayout.getStrokeWidth(),mPaint);
    }
}

Here the main code is complete, it should be noted that in the container, we have added four water ripples, and add three animations for each water ripples, finally put these animations animations performed centrally. Execution time of each interval of 3500/4 ripple herein, and each animation is repeated infinitely performed.

Guess you like

Origin blog.csdn.net/qinbin2015/article/details/90047149