Android仿每日優(yōu)鮮購(gòu)物車(chē)動(dòng)畫(huà)效果
目錄

前言
實(shí)現(xiàn)效果
小圖

圓形大圖(仿每日優(yōu)鮮)

使用方法
public class AnimManager {private WeakReference<Activity> mActivity;private AnimListener mListener;private long time;private final View startView;private final View endView;private final String imageUrl;private View animView;private double scale;private float animWidth;private float animHeight;private ViewGroup animMaskLayout;private AnimModule animModule = AnimModule.SMALL;private AnimManager() {this(new Builder());}AnimManager(Builder builder) {this.mActivity = builder.activity;this.startView = builder.startView;this.endView = builder.endView;this.time = builder.time;this.mListener = builder.listener;this.animView = builder.animView;this.imageUrl = builder.imageUrl;this.scale = builder.scale;this.animWidth = builder.animWidth;this.animHeight = builder.animHeight;this.animModule = builder.animModule;}/*** 開(kāi)始動(dòng)畫(huà)*/public void startAnim() {if (startView == null || endView == null) {throw new NullPointerException("startView or endView must not null");}int[] startLocation = new int[2];int[] endLocation = new int[2];startView.getLocationInWindow(startLocation);endView.getLocationInWindow(endLocation);if (animView != null) {setAnim(startLocation, endLocation);} else if (!TextUtils.isEmpty(imageUrl)) {createImageAndAnim(startLocation, endLocation);}}private void createImageAndAnim(final int[] startLocation, final int[] endLocation) {if(animModule == AnimModule.SMALL){final ImageView animImageView = new ImageView(getActivity());LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ConvertUtils.dp2px(animWidth),ConvertUtils.dp2px(animHeight));animImageView.setLayoutParams(layoutParams);Glide.with(getActivity()).load(imageUrl).asBitmap().listener(new RequestListener<String, Bitmap>() {@Overridepublic boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {return false;}@Overridepublic boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {setAnim(animImageView, startLocation, endLocation);return false;}}).into(animImageView);}else {if (startView != null) {final CircleImageView circleImageView = new CircleImageView(getActivity());// ViewGroup.LayoutParams starViewtLayoutParams = startView.getLayoutParams();int min = Math.min(startView.getMeasuredWidth(), startView.getMeasuredHeight());LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(min,min);circleImageView.setBorderColor(Color.WHITE);circleImageView.setBorderWidth(3);circleImageView.setLayoutParams(layoutParams);Glide.with(getActivity()).load(imageUrl).asBitmap().listener(new RequestListener<String, Bitmap>() {@Overridepublic boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {return false;}@Overridepublic boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {setAnim(circleImageView, startLocation, endLocation);return false;}}).into(circleImageView);}}}private void setAnim(int[] startLocation, int[] endLocation) {setAnim(animView, startLocation, endLocation);}private void setAnim(final View v, int[] startLocation, int[] endLocation) {animMaskLayout = createAnimLayout(getActivity());// 把動(dòng)畫(huà)小球添加到動(dòng)畫(huà)層animMaskLayout.addView(v);final View view = addViewToAnimLayout(v, startLocation);//終點(diǎn)位置int endX = endLocation[0] - startLocation[0] + endView.getMeasuredWidth()/2;// 動(dòng)畫(huà)位移的y坐標(biāo)int endY = endLocation[1] - startLocation[1] + 10;TranslateAnimation translateAnimationX = new TranslateAnimation(0, endX, 0, 0);translateAnimationX.setInterpolator(new AccelerateInterpolator());// 動(dòng)畫(huà)重復(fù)執(zhí)行的次數(shù)translateAnimationX.setRepeatCount(0);translateAnimationX.setFillAfter(true);TranslateAnimation translateAnimationY = new TranslateAnimation(0, 0, 0, endY);translateAnimationY.setInterpolator(new AccelerateInterpolator());translateAnimationY.setRepeatCount(0);translateAnimationX.setFillAfter(true);AnimationSet set = new AnimationSet(false);set.setFillAfter(false);if(animModule == AnimModule.BIG_CIRCLE){ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.1f, 1.0f, 0.1f);scaleAnimation.setInterpolator(new AccelerateInterpolator());scaleAnimation.setRepeatCount(0);scaleAnimation.setFillAfter(true);set.addAnimation(scaleAnimation);}set.addAnimation(translateAnimationY);set.addAnimation(translateAnimationX);if (scale == 1) {// 計(jì)算屏幕最遠(yuǎn)兩個(gè)點(diǎn)的直線距離double diagonalDef = Math.sqrt(Math.pow(ScreenUtils.getScreenWidth(), 2) + Math.pow(ScreenUtils.getScreenHeight(), 2));// 計(jì)算實(shí)際兩點(diǎn)的距離double diagonal = Math.abs(Math.sqrt(Math.pow(startLocation[0] - endLocation[0], 2) + Math.pow(startLocation[1] - endLocation[1], 2)));// 計(jì)算一個(gè)值,不同距離動(dòng)畫(huà)執(zhí)行的時(shí)間不同scale = diagonal / diagonalDef;}// 動(dòng)畫(huà)的執(zhí)行時(shí)間,計(jì)算出的時(shí)間小于300ms默認(rèn)為300msset.setDuration((time * scale) < 1000 ? 1000 : (long) (time * scale));view.startAnimation(set);// 動(dòng)畫(huà)監(jiān)聽(tīng)事件set.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {v.setVisibility(View.VISIBLE);if (mListener != null) {mListener.setAnimBegin(AnimManager.this);}}@Overridepublic void onAnimationRepeat(Animation animation) {}// 動(dòng)畫(huà)的結(jié)束調(diào)用的方法@Overridepublic void onAnimationEnd(Animation animation) {v.setVisibility(View.GONE);animMaskLayout.removeAllViews();if (mListener != null) {mListener.setAnimEnd(AnimManager.this);}}});}public void stopAnim() {if (animMaskLayout != null && animMaskLayout.getChildCount() > 0) {animMaskLayout.removeAllViews();}}private ViewGroup createAnimLayout(Activity mainActivity) {ViewGroup rootView = (ViewGroup) mainActivity.getWindow().getDecorView();LinearLayout animLayout = new LinearLayout(mainActivity);LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);animLayout.setLayoutParams(lp);animLayout.setId(R.id.anim_icon);animLayout.setBackgroundResource(android.R.color.transparent);rootView.addView(animLayout);return animLayout;}private View addViewToAnimLayout(final View view, int[] location) {int x = location[0];int y = location[1];LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);lp.leftMargin = x;lp.topMargin = y;view.setLayoutParams(lp);return view;}/*** 自定義時(shí)間** @param time* @return*/public long setTime(long time) {this.time = time;return time;}private Activity getActivity() {return mActivity.get();}public void setOnAnimListener(AnimListener listener) {mListener = listener;}//回調(diào)監(jiān)聽(tīng)public interface AnimListener {void setAnimBegin(AnimManager a);void setAnimEnd(AnimManager a);}public static final class Builder {WeakReference<Activity> activity;View startView;View endView;View animView;String imageUrl;long time;double scale;float animWidth;float animHeight;AnimListener listener;private AnimModule animModule = AnimModule.SMALL;public Builder() {this.time = 1000;this.scale = 1;this.animHeight = 25;this.animWidth = 25;}public Builder animModule(AnimModule animModule) {this.animModule = animModule;return this;}public Builder with(Activity activity) {this.activity = new WeakReference<>(activity);return this;}public Builder startView(View startView) {if (startView == null) {throw new NullPointerException("startView is null");}this.startView = startView;return this;}public Builder endView(View endView) {if (endView == null) {throw new NullPointerException("endView is null");}this.endView = endView;return this;}public Builder animView(View animView) {if (animView == null) {throw new NullPointerException("animView is null");}this.animView = animView;return this;}public Builder listener(AnimListener listener) {if (listener == null) {throw new NullPointerException("listener is null");}this.listener = listener;return this;}public Builder imageUrl(String imageUrl) {this.imageUrl = imageUrl;return this;}public Builder time(long time) {if (time <= 0) {throw new IllegalArgumentException("time must be greater than zero");}this.time = time;return this;}public Builder scale(double scale) {this.scale = scale;return this;}public Builder animWidth(float width) {if (width <= 0) {throw new IllegalArgumentException("width must be greater than zero");}this.animWidth = width;return this;}public Builder animHeight(float height) {if (height <= 0) {throw new IllegalArgumentException("height must be greater than zero");}this.animHeight = height;return this;}public AnimManager build() {return new AnimManager(this);}}public enum AnimModule{SMALL,//小的(默認(rèn))BIG_CIRCLE//大的圓形}}
animManager = new AnimManager.Builder().with(this).animModule(AnimManager.AnimModule.BIG_CIRCLE)//圖片的動(dòng)畫(huà)模式,小的或者大的(仿每日優(yōu)鮮).startView(startView)//開(kāi)始位置的控件.endView(imageViewShopCar)//結(jié)束位置的控件.listener(new AnimManager.AnimListener() {@Overridepublic void setAnimBegin(AnimManager a) {}@Overridepublic void setAnimEnd(AnimManager a) {//購(gòu)物車(chē)回彈動(dòng)畫(huà)(這里是加入購(gòu)物車(chē)動(dòng)畫(huà)執(zhí)行結(jié)束時(shí)的回調(diào)我在這里加入了購(gòu)物車(chē)回彈效果,不需要的話可以去掉)TranslateAnimation anim = new TranslateAnimation(0, 0, 20, 0);anim.setInterpolator(new BounceInterpolator());anim.setDuration(700);imageViewShopCar.startAnimation(anim);textViewNum.setText(num+"");}}).imageUrl(animImgUrl).build();animManager.startAnim();
源碼地址:
https://github.com/myml666/ShopCarAnim
評(píng)論
圖片
表情
