android仿美团底部导航栏的点击效果——揭露动画

来源:互联网 发布:office mac 2016 密码 编辑:程序博客网 时间:2024/06/05 05:38

又是划水的一天好开心,无聊逛了逛美团,喜欢上美团底部导航栏的点击效果。感觉在哪里见过,又想不起来,后来一波百度,发现就是安卓5.0的揭露动画createCircularReveal。

这里写图片描述

什么事揭露动画,参考http://www.itdadao.com/articles/c15a1442955p0.html。
看到没,大概就是这种动画效果,用的好的话,这种效果其实会很可爱。

于是,我快速的加入新建demo中,

// 显示if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {    /**      * createCircularReveal 方法参数      * view 执行动画的view      * centerX 圆心横坐标      * centerY 圆心纵坐标      * startRadius 动画开始时圆的半径      * endRadius 动画结束时圆的半径      */    final Animator animator = ViewAnimationUtils.createCircularReveal(animateView,                        animateView.getWidth() / 2,                        animateView.getHeight() / 2,                        0,                        (float) Math.hypot(animateView.getWidth(), animateView.getHeight()));                         // Math.hypot确定圆的半径(算长宽的斜边长,这样半径不会太短也不会很长效果比较舒服)    animatorHide.addListener(new Animator.AnimatorListener() {                    @Override                    public void onAnimationStart(Animator animation) {                        animateView.setVisibility(View.VISIBLE);                    }                    @Override                    public void onAnimationEnd(Animator animation) {                    }                    @Override                    public void onAnimationCancel(Animator animation) {                    }                    @Override                    public void onAnimationRepeat(Animator animation) {                    }                });    animatorHide.setDuration(5000);    animatorHide.start();} else {    animateView.setVisibility(View.VISIBLE);}animateView.setEnabled(true);

使用时直接调用:

CircleAnimateUtils.handleAnimate(iv);

这样仿美团底部导航栏的点击动画就实现了,超简单吧。

接着无聊。。。发现揭露动画效果只能实现在5.0以上的手机,5.0以下的没有这个效果。如果是我做的话,5.0以下就不管了,但是美团没有这么懒,成功实现5.0以下的揭露动画。

究竟是如何实现的,本大王不服,噼里啪啦百度一波,发现了一个可爱的第三方:
https://github.com/zhangke3016/TranslationCompat

里面的CircularRevealLayout直接拖过来用了:

public class CircularRevealLayout extends FrameLayout {    private Path path;    private float centerX;    private float centerY;    private float revealRadius;    private boolean isRunning;    private View childView;    private float startRadius;    private float endRadius;    public CircularRevealLayout(Context context) {        this(context, null);    }    public CircularRevealLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public CircularRevealLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        path = new Path();    }    public void setChildView(View childView) {        this.childView = childView;    }    public void setCenterX(float centerX) {        this.centerX = centerX;    }    public void setCenterY(float centerY) {        this.centerY = centerY;    }    public void setStartRadius(float startRadius) {        this.startRadius = startRadius;    }    public void setEndRadius(float endRadius) {        this.endRadius = endRadius;    }    public void setRevealRadius(float revealRadius) {        this.revealRadius = revealRadius;        invalidate();    }    public Animator getAnimator() {        ObjectAnimator reveal = ObjectAnimator.ofFloat(this, "revealRadius", startRadius, endRadius);        reveal.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animator) {                animationStart(animator);            }            @Override            public void onAnimationEnd(Animator animator) {                animationEnd(animator);            }            @Override            public void onAnimationCancel(Animator animator) {                animationCancel(animator);            }            @Override            public void onAnimationRepeat(Animator animator) {            }        });        return reveal;    }    private void animationStart(Animator animator) {        isRunning = true;    }    private void animationEnd(Animator animator) {        isRunning = false;    }    private void animationCancel(Animator animator) {        isRunning = false;    }    @Override    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {        if (isRunning && childView == child) {            final int state = canvas.save();            path.reset();            path.addCircle(centerX, centerY, revealRadius, Path.Direction.CW);            canvas.clipPath(path);            boolean isInvalided = super.drawChild(canvas, child, drawingTime);            canvas.restoreToCount(state);            return isInvalided;        }        return super.drawChild(canvas, child, drawingTime);    }    public static class Builder {        private View view;        private float centerX;        private float centerY;        private float startRadius;        private float endRadius;        public Builder(View view) {            this.view = view;        }        public static Builder on(View view) {            return new Builder(view);        }        public Builder centerX(float centerX) {            this.centerX = centerX;            return this;        }        public Builder centerY(float centerY) {            this.centerY = centerY;            return this;        }        public Builder startRadius(float startRadius) {            this.startRadius = startRadius;            return this;        }        public Builder endRadius(float endRadius) {            this.endRadius = endRadius;            return this;        }        private void setParameter(CircularRevealLayout layout) {            layout.setCenterX(centerX);            layout.setCenterY(centerY);            layout.setStartRadius(startRadius);            layout.setEndRadius(endRadius);            layout.setChildView(view);        }        public Animator create() {            if (view.getParent() != null && view.getParent() instanceof CircularRevealLayout) {                CircularRevealLayout layout = ((CircularRevealLayout) view.getParent());                setParameter(layout);                return layout.getAnimator();            }            CircularRevealLayout layout = new CircularRevealLayout(view.getContext());            if (Build.VERSION.SDK_INT >= 11) {                layout.setLayerType(View.LAYER_TYPE_SOFTWARE, null);            }            setParameter(layout);            ViewGroup.LayoutParams params = view.getLayoutParams();            ViewGroup parent = (ViewGroup) view.getParent();            int index = 0;            if (parent != null) {                index = parent.indexOfChild(view);                parent.removeView(view);            }            layout.addView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));            if (parent != null) {                parent.addView(layout, index, params);            }            return layout.getAnimator();        }    }}

牛逼吧,反正我暂时还不会写,只会copy.

public class CircleAnimateUtils {    public static void handleAnimate(final View animateView) {        Animator animator = CircularRevealLayout.Builder.on(animateView)                .centerX(animateView.getWidth() / 2)                .centerY(animateView.getHeight() / 2)                .startRadius(0)                .endRadius((float) Math.hypot(animateView.getWidth(), animateView.getHeight()))                .create();        mAnimator.setDuration(5000);        mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());              mAnimator.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                super.onAnimationEnd(animation);            }            @Override            public void onAnimationStart(Animator animation) {                animateView.setVisibility(View.VISIBLE);                super.onAnimationStart(animation);            }        });        mAnimator.start();     } }

使用的时候直接调用 CircleAnimateUtils.handleAnimate(iv);

源码:https://github.com/jjjSilence/jjjPlus/tree/%E5%B0%81%E8%A3%85
仿美团底部导航栏点击——揭露动画

阅读全文
0 0
原创粉丝点击