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