WindowManager仿网易严选加入购物车动画效果

关于WindowManager的介绍网上一大堆,这里只介绍一下具体的使用。详情可参考:点击打开链接

此外还需要知道WindowManager.LayoutParams,参考介绍:点击打开链接

案例是网易严选的加入购物车时,商品会移动并缩小进入购物车的动画效果。


重要的三个方法是:

addView() 添加View到Window

 removeView() 移除View

updateViewLayout() 更新View坐标大小。


获取WindowManager:

    /**
     * 获取WindowManager
     * @return
     */
    private WindowManager initWindowManager(){
        return (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    }

初始化WindowManager.LayoutParams

    /**
     * 初始化WindowManger.LayoutParams
     * @return
     */
    private WindowManager.LayoutParams initParams(){
        //布局参数
        final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
        layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
        //格式
        layoutParams.format = PixelFormat.TRANSLUCENT;
        //这里的作用是以屏幕左上角为(0,0)点,默认为屏幕中心点
        layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
        //类型
        layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
        return layoutParams;
    }

注意点:

//这里的作用是以屏幕左上角为(0,0)点,默认为屏幕中心点
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;

默认坐标中心是屏幕的中心点,所以要自己设置gravity,来保证坐标原点在左上角,方便后面的位置计算。


添加View

    /**
     * 添加View
     * @param view 添加的View
     * @param width view的宽度
     * @param height view的高度
     * @param x x坐标
     * @param y y坐标
     */
    public void addView(final View view, int width, int height, float x, float y){
        if(!added) {
            //窗口管理器
            this.view = view;
            view.setVisibility(View.VISIBLE);
            layoutParams.width = width;
            layoutParams.height = height;
            layoutParams.x = (int) x;
            layoutParams.y = (int) y;
            //加载view
            wm.addView(view, layoutParams);
            added = true;
        }
    }


执行动画第一步(View上移,并返回):

    /**
     * 方案一
     * 执行动画
     * @param startY 起点Y坐标
     * @param middleY 中间Y坐标
     * @param ey 终点y坐标
     * @param startX 起点X坐标
     * @param ex 终点y坐标
     */
    public void updateViewAnim0(final float startY, float middleY, final float ey, final float startX, final float ex){

        //起始宽高
        final int swidth = layoutParams.width;
        final int sheight = layoutParams.height;

        //最终宽高
        final int fwidth = (int) (swidth * 0.2);
        final int fheight = (int) (sheight * 0.2);

        //最终sx
        final int endX = (int) (ex - fwidth * 0.5);
        final int endY = (int) (ey - fheight * 0.5);

        ValueAnimator anim = ValueAnimator.ofFloat(startY, middleY, startY);
        anim.setDuration(400);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //设置坐标
                float moveY = (float)animation.getAnimatedValue();
                layoutParams.y = (int) moveY;
                //更新
                wm.updateViewLayout(view, layoutParams);
            }
        });

        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {}

            @Override
            public void onAnimationEnd(Animator animator) {
                updateViewAnim1(startX, endX, startY, endY, swidth, sheight, fwidth, fheight);
            }

            @Override
            public void onAnimationCancel(Animator animator) {}

            @Override
            public void onAnimationRepeat(Animator animator) {}
        });
        anim.start();
    }

第二步:获取图片移动并且缩小

    public void updateViewAnim1(final float startX, final float endX, final float startY, final float endY, final float swidth, final float sheight, final float fwidth, final float fheight){
        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
        anim.setInterpolator(new MyInterpolator());
        anim.setDuration(500);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float frac = (float) animation.getAnimatedValue();
                Log.i("fracccccc", "frac:" + frac);

                float scale = 1 - frac;
                if(scale >= 0.8)scale = 0.8f;
                //设置宽高
                double wnow = swidth * (scale);

                double hnow = sheight * (scale);

                layoutParams.width = (int) (wnow);
                layoutParams.height = (int) (hnow);

//                view.setScaleY(scale);
//                view.setScaleX(scale);

                //设置坐标
//                float moveY = (float)animation.getAnimatedValue();
                float moveY = (endY - startY) * frac + startY;
                layoutParams.y = (int) moveY;

                double moveX = (endX - startX) * frac + startX;
                layoutParams.x = (int) moveX;

                //更新
                if(frac == 1){
                    view.setVisibility(View.GONE);
                }
                wm.updateViewLayout(view, layoutParams);
            }
        });

        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {}

            @Override
            public void onAnimationEnd(Animator animator) {
                wm.removeView(view);
                added = false;
                if(animFinished != null){
                    animFinished.finish();
                }
            }

            @Override
            public void onAnimationCancel(Animator animator) {}

            @Override
            public void onAnimationRepeat(Animator animator) {}
        });
        anim.start();
    }
插值器:

    /**
     * 插值器 匀速
     */
    public class MyInterpolator implements Interpolator{

        @Override
        public float getInterpolation(float v) {
            return v;
        }
    }



使用:

                            if(ivDraw == null) {
                                ivDraw = (LoookDraweeView) LayoutInflater.from(context).inflate(R.layout.item_pw_loookdraweeview, null);
                                ivDraw.setImageURI(Uri.parse(popup_url));
                            }

                            int[] location = new int[2];
                            drawee_goods.getLocationOnScreen(location);
                            //起点
                            final float sx = location[0];
                            float sy = location[1];
                            //中间点
                            float my = sy * 4 / 5;

                            ll_cart.getLocationOnScreen(location);
                            ll_cart.getWidth();
                            //终点
                            float ex = (float) (location[0] + ll_cart.getWidth() * 0.5);
                            float ey = (float) (location[1] + ll_cart.getHeight() * 0.5);

                            if(wm == null) {
                                wm = new WindowManagerUtil(context);
                            }
                            wm.setAnimFinished(new WindowManagerUtil.AnimFinished() {
                                @Override
                                public void finish() {
                                    finished = true;
                                    if(buy_type.equals("shop_car")) {
                                        Local.addShopCartNum(buySku.buy_num);
                                        updateShopCartNum();
                                        doActionGetCartCount();
                                    }
                                    hideGoodsSelecter();
                                }
                            });
                            wm.addView(ivDraw, Local.dip2px(88), Local.dip2px(88), sx, sy);
                            wm.updateViewAnim0(sy, my, ey, sx, ex);



全部代码:

package com.xxxx.Dialog;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Interpolator;

/**
 * Created by lk on 16/8/9.
 */
public class WindowManagerUtil {

    private final Context context;
    private WindowManager wm;
    private WindowManager.LayoutParams layoutParams;
    private View view;
    private AnimFinished animFinished;
    private boolean added;

    public WindowManagerUtil(Context context){
        this.context = context;
        wm = initWindowManager();
        layoutParams = initParams();
    }

    /**
     * 获取WindowManager
     * @return
     */
    private WindowManager initWindowManager(){
        return (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    }

    /**
     * 初始化WindowManger.LayoutParams
     * @return
     */
    private WindowManager.LayoutParams initParams(){
        //布局参数
        final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
        layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
        //格式
        layoutParams.format = PixelFormat.TRANSLUCENT;
        //这里的作用是以屏幕左上角为(0,0)点,默认为屏幕中心点
        layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
        //类型
        layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
        return layoutParams;
    }

    /**
     * 添加View
     * @param view 添加的View
     * @param width view的宽度
     * @param height view的高度
     * @param x x坐标
     * @param y y坐标
     */
    public void addView(final View view, int width, int height, float x, float y){
        if(!added) {
            //窗口管理器
            this.view = view;
            view.setVisibility(View.VISIBLE);
            layoutParams.width = width;
            layoutParams.height = height;
            layoutParams.x = (int) x;
            layoutParams.y = (int) y;
            //加载view
            wm.addView(view, layoutParams);
            added = true;
        }
    }

    /**
     * 方案一
     * 执行动画
     * @param startY 起点Y坐标
     * @param middleY 中间Y坐标
     * @param ey 终点y坐标
     * @param startX 起点X坐标
     * @param ex 终点y坐标
     */
    public void updateViewAnim0(final float startY, float middleY, final float ey, final float startX, final float ex){

        //起始宽高
        final int swidth = layoutParams.width;
        final int sheight = layoutParams.height;

        //最终宽高
        final int fwidth = (int) (swidth * 0.2);
        final int fheight = (int) (sheight * 0.2);

        //最终sx
        final int endX = (int) (ex - fwidth * 0.5);
        final int endY = (int) (ey - fheight * 0.5);

        ValueAnimator anim = ValueAnimator.ofFloat(startY, middleY, startY);
        anim.setDuration(400);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //设置坐标
                float moveY = (float)animation.getAnimatedValue();
                layoutParams.y = (int) moveY;
                //更新
                wm.updateViewLayout(view, layoutParams);
            }
        });

        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {}

            @Override
            public void onAnimationEnd(Animator animator) {
                updateViewAnim1(startX, endX, startY, endY, swidth, sheight, fwidth, fheight);
            }

            @Override
            public void onAnimationCancel(Animator animator) {}

            @Override
            public void onAnimationRepeat(Animator animator) {}
        });
        anim.start();
    }

    public void updateViewAnim1(final float startX, final float endX, final float startY, final float endY, final float swidth, final float sheight, final float fwidth, final float fheight){
        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
        anim.setInterpolator(new MyInterpolator());
        anim.setDuration(500);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float frac = (float) animation.getAnimatedValue();
                Log.i("fracccccc", "frac:" + frac);

                float scale = 1 - frac;
                if(scale >= 0.8)scale = 0.8f;
                //设置宽高
                double wnow = swidth * (scale);

                double hnow = sheight * (scale);

                layoutParams.width = (int) (wnow);
                layoutParams.height = (int) (hnow);

//                view.setScaleY(scale);
//                view.setScaleX(scale);

                //设置坐标
//                float moveY = (float)animation.getAnimatedValue();
                float moveY = (endY - startY) * frac + startY;
                layoutParams.y = (int) moveY;

                double moveX = (endX - startX) * frac + startX;
                layoutParams.x = (int) moveX;

                //更新
                if(frac == 1){
                    view.setVisibility(View.GONE);
                }
                wm.updateViewLayout(view, layoutParams);
            }
        });

        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {}

            @Override
            public void onAnimationEnd(Animator animator) {
                wm.removeView(view);
                added = false;
                if(animFinished != null){
                    animFinished.finish();
                }
            }

            @Override
            public void onAnimationCancel(Animator animator) {}

            @Override
            public void onAnimationRepeat(Animator animator) {}
        });
        anim.start();
    }

    /**
     * 插值器 匀速
     */
    public class MyInterpolator implements Interpolator{

        @Override
        public float getInterpolation(float v) {
            return v;
        }
    }

    /**
     * 方案二
     * @param startY
     * @param middleY
     * @param ey
     * @param startX
     * @param ex
     */
    public void updateViewAnim(float startY, float middleY, float ey, final float startX, final float ex){
        //起始宽高
        final int swidth = layoutParams.width;
        final int sheight = layoutParams.height;

        //最终宽高
        final int fwidth = (int) (swidth * 0.25);
        final int fheight = (int) (sheight * 0.25);

        //最终sx
        final int endX = (int) (ex - fwidth * 0.5);
        final int endY = (int) (ey - fheight * 0.5);

        ValueAnimator anim = ValueAnimator.ofFloat(startY, middleY, endY);
        anim.setDuration(1000);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float frac = animation.getAnimatedFraction();
                //设置宽高
                if(frac >= 0.25) {
                    double wnow = swidth * (1.25 - frac);
                    wnow = wnow > fwidth ? wnow : fwidth;

                    double hnow = sheight * (1.25 - frac);
                    hnow = hnow > fheight ? hnow : fheight;

                    layoutParams.width = (int) (wnow);
                    layoutParams.height = (int) (hnow);

                }

                //设置坐标
                float moveY = (float)animation.getAnimatedValue();
                layoutParams.y = (int) moveY;

                double moveX = (endX - startX) * frac + startX;
                layoutParams.x = (int) moveX;

                //更新
                wm.updateViewLayout(view, layoutParams);
            }
        });

        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                wm.removeView(view);
            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });
        anim.start();
    }

    //设置监听回调
    public void setAnimFinished(AnimFinished animFinished){
        this.animFinished = animFinished;
    }

    public interface AnimFinished{
        void finish();
    }

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值