自定义控件之水波纹特效

首先看一下效果:

实现这个效果,其实需要分析一下有几个动画 。很明显一开始是一个小圆,慢慢的在外扩散,所以这里有两个动画,x轴缩放动画,y轴缩放动画。另外在扩散的过程中,圆的透明度也是在不断变化的,所以有一个透明度的动画。总结起来,有3个动画,如下:

  • x轴动画,对应的属性是ScaleX
  • y轴动画,对象的属性是ScaleY
  • 透明度动画,对应的属性是Alpha(1-->0)

下面看代码如何实现。

1、自定义一个容器,继承于RelativeLayout。用于管理需要执行的几个水波纹,这里使用了4个水波纹

2、自定义水波纹,继承于View。

自定义容器类:添加4个水波纹


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

    }




}

自定义属性文件attrs:可以设置水波纹颜色,半径

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

    </declare-styleable>

自定义水波纹:主要画一个圆


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

这里就完成了主要的代码,需要注意的是在容器中我们添加了4个水波纹,并且为每个水波纹添加了3个动画,最后将这些动画放到动画集中执行。每个水波纹的执行时间间隔为这里的3500/4,并且每个动画是重复无限执行的。

猜你喜欢

转载自blog.csdn.net/qinbin2015/article/details/90047149
今日推荐