<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 13164字,需瀏覽 27分鐘

           ·

          2021-08-18 18:12

          目錄



          前言

          最近項(xiàng)目需要一個(gè)加入購(gòu)物車(chē)的動(dòng)畫(huà)效果,費(fèi)了一點(diǎn)時(shí)間做出來(lái)了,在這記錄下方便以后使用。


          實(shí)現(xiàn)效果

          • 小圖



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



          使用方法

          整個(gè)效果的核心類(lèi)已經(jīng)被我封裝成了一個(gè)類(lèi)了,直接使用即可。
          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>() { @Override public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) { return false; }
          @Override public 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>() { @Override public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) { return false; }
          @Override public 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)為300ms set.setDuration((time * scale) < 1000 ? 1000 : (long) (time * scale)); view.startAnimation(set); // 動(dòng)畫(huà)監(jiān)聽(tīng)事件 set.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { v.setVisibility(View.VISIBLE); if (mListener != null) { mListener.setAnimBegin(AnimManager.this); } }
          @Override public void onAnimationRepeat(Animation animation) { }
          // 動(dòng)畫(huà)的結(jié)束調(diào)用的方法 @Override public 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() {                        @Override                        public void setAnimBegin(AnimManager a) {
          }
          @Override public 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


          到這里就結(jié)束啦。
          瀏覽 77
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色色一区二区 | 亚洲的做爱 | 豆花视频在线看成人网站 | 青娱乐欧美视频 | 69人妻人人澡人人爽人人精品 |