• Android -- 贝塞尔二阶实现饿了么加入购物车效果


    1,上周我们实现了简单的三阶贝塞尔曲线效果实例,今天是使用二阶贝塞尔曲线加动画实现的加入购物车效果,在码代码过程中出现了些问题,过一下和大家来探讨探讨,先看一下效果图

      

    2,从上面的效果来看我们基本上可以把功能拆分为两个动画效果:+号图片按照曲线掉下(曲线的轨迹就是一个简单的贝塞尔曲线)、购物车图标从缩小到放大。知道了实现的原理我们开始我们功能的实现

    • 实现基本基本布局、RecyclerView展示数据

      从上面的效果我们可以得到,我们的布局是一个简单的RecyclerView和下面的RelativeLayout,布局文件如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/main_layout"
        tools:context="com.qianmo.beziershopcart.MainActivity">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
        </android.support.v7.widget.RecyclerView>
    
    
        <LinearLayout
            android:id="@+id/shopping_cart_bottom"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:background="#fd383838"
            android:orientation="horizontal">
    
        </LinearLayout>
    
        <FrameLayout
            android:id="@+id/shopping_cart_layout"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="35dp"
            android:background="@drawable/circle"
            android:clickable="true">
    
            <ImageView
                android:id="@+id/shopping_cart"
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:layout_gravity="center"
                android:src="@mipmap/ic_shopping_cart_white_24dp"/>
        </FrameLayout>
    </RelativeLayout>
    

      添加Shop实体类、添加RecyclerView的Adapter

    package com.qianmo.beziershopcart;
    
    /**
     * Created by wangjitao on 2017/4/10 0010.
     * E-Mail:543441727@qq.com
     */
    
    public class ShopBean {
    
        private String title;
        private String price;
        private int count;
    
        public ShopBean(String title, String price, int count) {
            this.title = title;
            this.price = price;
            this.count = count;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getPrice() {
            return price;
        }
    
        public void setPrice(String price) {
            this.price = price;
        }
    
        public int getCount() {
            return count;
        }
    
        public void setCount(int count) {
            this.count = count;
        }
    }
    

      适配器

    package com.qianmo.beziershopcart;
    
    import android.content.Context;
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import java.util.List;
    
    /**
     * Created by Administrator on 2017/4/10 0010.
     * E-Mail:543441727@qq.com
     */
    
    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
        private List<ShopBean> datas;
        private Context mContext;
        private ShopOnClickListtener mShopOnClickListtener;
    
        public MyAdapter(List<ShopBean> datas, Context mContext) {
            this.datas = datas;
            this.mContext = mContext;
        }
    
        @Override
        public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_shop_menu, parent, false));
        }
    
        @Override
        public void onBindViewHolder(MyAdapter.ViewHolder holder, final int position) {
            holder.shop_name.setText(datas.get(position).getTitle());
            holder.shop_price.setText(datas.get(position).getPrice());
            holder.count.setText(datas.get(position).getCount() + "");
    
            holder.ic_add.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mShopOnClickListtener != null) {
                        mShopOnClickListtener.add(v, position);
                    }
                }
            });
            holder.ic_reduce.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mShopOnClickListtener != null) {
                        mShopOnClickListtener.remove(v, position);
                    }
    
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return datas == null ? 0 : datas.size();
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder {
            TextView shop_name;
            TextView shop_price;
            TextView count;
            ImageView ic_add;
            ImageView ic_reduce;
    
            public ViewHolder(View itemView) {
                super(itemView);
                shop_name = (TextView) itemView.findViewById(R.id.tv_title);
                shop_price = (TextView) itemView.findViewById(R.id.tv_price);
                count = (TextView) itemView.findViewById(R.id.tv_count);
                ic_add = (ImageView) itemView.findViewById(R.id.iv_add);
                ic_reduce = (ImageView) itemView.findViewById(R.id.iv_remove);
            }
        }
    
        public ShopOnClickListtener getShopOnClickListtener() {
            return mShopOnClickListtener;
        }
    
        public void setShopOnClickListtener(ShopOnClickListtener mShopOnClickListtener) {
            this.mShopOnClickListtener = mShopOnClickListtener;
        }
    
    
        public interface ShopOnClickListtener {
    
            void add(View view, int position);
    
            void remove(View view, int position);
        }
    }
    

      在Activity中简单的添加数据

    package com.qianmo.beziershopcart;
    
    import android.animation.Animator;
    import android.animation.AnimatorSet;
    import android.animation.ObjectAnimator;
    import android.animation.ValueAnimator;
    import android.content.Context;
    import android.graphics.Point;
    import android.graphics.PointF;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.View;
    import android.view.Window;
    import android.view.WindowManager;
    import android.view.animation.AccelerateInterpolator;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity implements MyAdapter.ShopOnClickListtener {
        private Context mContext = MainActivity.this;
    
        private RelativeLayout main_layout;
        private RecyclerView mRecyclerView;
        private ImageView mImageViewShopCat;
        private List<ShopBean> datas;
        private MyAdapter myAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
    
    
        }
    
        private void initView() {
            mRecyclerView = (RecyclerView) findViewById(R.id.recycler);
            mImageViewShopCat = (ImageView) findViewById(R.id.shopping_cart);
            main_layout = (RelativeLayout) findViewById(R.id.main_layout);
            initData();
        }
    
        private void initData() {
            datas = new ArrayList<>();
            datas.add(new ShopBean("面包", "1.00", 10));
            datas.add(new ShopBean("蛋挞", "1.00", 10));
            datas.add(new ShopBean("牛奶", "1.00", 10));
            datas.add(new ShopBean("肠粉", "1.00", 10));
            datas.add(new ShopBean("绿茶饼", "1.00", 10));
            datas.add(new ShopBean("花卷", "1.00", 10));
            datas.add(new ShopBean("包子", "1.00", 10));
    
            datas.add(new ShopBean("粥", "1.00", 10));
            datas.add(new ShopBean("炒饭", "1.00", 10));
            datas.add(new ShopBean("炒米粉", "1.00", 10));
            datas.add(new ShopBean("炒粿条", "1.00", 10));
            datas.add(new ShopBean("炒牛河", "1.00", 10));
            datas.add(new ShopBean("炒菜", "1.00", 10));
    
            datas.add(new ShopBean("淋菜", "1.00", 10));
            datas.add(new ShopBean("川菜", "1.00", 10));
            datas.add(new ShopBean("湘菜", "1.00", 10));
            datas.add(new ShopBean("粤菜", "1.00", 10));
            datas.add(new ShopBean("赣菜", "1.00", 10));
            datas.add(new ShopBean("东北菜", "1.00", 10));
    
            datas.add(new ShopBean("淋菜", "1.00", 10));
            datas.add(new ShopBean("川菜", "1.00", 10));
            datas.add(new ShopBean("湘菜", "1.00", 10));
            datas.add(new ShopBean("粤菜", "1.00", 10));
            datas.add(new ShopBean("赣菜", "1.00", 10));
            datas.add(new ShopBean("东北菜", "1.00", 10));
    
            mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
            mRecyclerView.addItemDecoration(new RecyclerViewDivider(mContext, LinearLayoutManager.VERTICAL, 50, ContextCompat.getColor(mContext, R.color.colorAccent)));
            myAdapter = new MyAdapter(datas, mContext);
            mRecyclerView.setAdapter(myAdapter);
            myAdapter.setShopOnClickListtener(this);
        }
    
    
        @Override
        public void add(final View view, int position) {
           Toast.makeText(mContext, "加", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void remove(View view, int position) {
         Toast.makeText(mContext, "减", Toast.LENGTH_SHORT).show();
        }
    }
    

      看一下我们的效果:

      

      OK,大致的展示效果基本上是实现了

    • 使用加入购物车效果

      下面我们来实现贝塞尔曲线效果,首先获取两个数据点:一个是每次点击“+”号的坐标位置、一个是下面红色的购物车图标。控制点我打算取开始点的Y坐标和结束点的X坐标,那么怎么获取当前控件相对于整个屏幕的坐标呢,这里View里面有一个getLocationInWindow()方法(这里要留心一下这个方法),然后不了解的同学可以搜索一下view.getLocationInWindow(int[] location)和view.getLocationOnScreen(int[] location),方法的区别,这里我从网上偷了了一个图,如下:

      getLocationInWindow是以B为原点的C的坐标
      getLocationOnScreen以A为原点
    

      ok,这样我们看一下我们的贝塞尔三个坐标的初始化

     @Override
        public void add(final View view, int position) {
            //贝塞尔起始数据点
            int[] startPosition = new int[2];
            //贝塞尔结束数据点
            int[] endPosition = new int[2];
            //控制点
            int[] recyclerPosition = new int[2];
    
            view.getLocationInWindow(startPosition);
            mImageViewShopCat.getLocationInWindow(endPosition);
    
            PointF startF = new PointF();
            PointF endF = new PointF();
            PointF controllF = new PointF();
    
           
           startF.x = startPosition[0];
           startF.y = startPosition[1] ;
           endF.x = endPosition[0];
           endF.y = endPosition[1];
           controllF.y = startF.y;
    }
    

      继续,自定义差值器,我们按照贝塞尔的三阶公式来套,上一篇详细的介绍过了就不在废话了,这里不懂的话建议你去看一下我的上一篇博客,里面有详细的介绍

      

    package com.qianmo.beziershopcart;
    
    import android.animation.TypeEvaluator;
    import android.graphics.PointF;
    
    /**
     * Created by Administrator on 2017/4/10 0010.
     * E-Mail:543441727@qq.com
     */
    
    public class BezierTypeEvaluator implements TypeEvaluator<PointF> {
        private PointF mControllPoint;
    
        public BezierTypeEvaluator(PointF mControllPoint) {
            this.mControllPoint = mControllPoint;
        }
    
        @Override
        public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
            PointF pointCur = new PointF();
            pointCur.x = (1 - fraction) * (1 - fraction) * startValue.x + 2 * fraction * (1 - fraction) * mControllPoint.x + fraction * fraction * endValue.x;
            pointCur.y = (1 - fraction) * (1 - fraction) * startValue.y + 2 * fraction * (1 - fraction) * mControllPoint.y + fraction * fraction * endValue.y;
            return pointCur;
        }
    }
    

      开启动画自动调用

    @Override
        public void add(final View view, int position) {
            //贝塞尔起始数据点
            int[] startPosition = new int[2];
            //贝塞尔结束数据点
            int[] endPosition = new int[2];
            
            view.getLocationInWindow(startPosition);
            mImageViewShopCat.getLocationInWindow(endPosition);
    
            PointF startF = new PointF();
            PointF endF = new PointF();
            PointF controllF = new PointF();
    
            
            startF.x = startPosition[0];
            startF.y = startPosition[1] ;
            endF.x = endPosition[0];
            endF.y = endPosition[1];
            controllF.x = endF.x;
            controllF.y = startF.y;
    
            ValueAnimator valueAnimator = ValueAnimator.ofObject(new BezierTypeEvaluator(controllF), startF, endF);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    PointF pointF = (PointF) animation.getAnimatedValue();
                    view.setX(pointF.x);
                    view.setY(pointF.y);
    //                Log.i("wangjtiao", "viewF:" + view.getX() + "," + view.getY());
                }
            });
            valueAnimator .setDuration(800);
            valueAnimator .start();
        }
    

      按照我们的思路,这个功能基本上是实现了,感觉很简单,又可以多了些时间去打两把王者农药了,看一下我们的效果图:

      

      呃!!!我的动画呢??? ,看一下我们打印动画轨迹的效果

    04-10 03:55:37.271 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:899.42816,608.6747
    04-10 03:55:37.306 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:841.05066,615.05853
    04-10 03:55:37.369 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:700.9506,644.04346
    04-10 03:55:37.399 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:626.5742,669.1555
    04-10 03:55:37.427 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:552.1316,703.05035
    04-10 03:55:37.474 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:477.8907,747.9864
    04-10 03:55:37.502 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:410.36102,801.63885
    04-10 03:55:37.528 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:348.99896,864.93835
    04-10 03:55:37.549 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:320.21585,901.0647
    04-10 03:55:37.601 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:247.92773,1019.08307
    04-10 03:55:37.629 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:210.69424,1104.1696
    04-10 03:55:37.650 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:194.71275,1149.3108
    04-10 03:55:37.672 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:180.81482,1194.8556
    04-10 03:55:37.716 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:150.94038,1327.2924
    04-10 03:55:37.744 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:138.87828,1409.5398
    04-10 03:55:37.771 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:134.5641,1449.0864
    04-10 03:55:37.799 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:129.06772,1518.4921
    04-10 03:55:37.813 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:127.390335,1549.7286
    04-10 03:55:37.852 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:125.646034,1600.0463
    04-10 03:55:37.873 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:125.263214,1620.108
    04-10 03:55:37.902 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:125.0176,1646.6577
    04-10 03:55:37.932 29510-29510/com.qianmo.beziershopcart I/wangjtiao: viewF:125.0,1656.0
    

      view的坐标一直在改变啊!思路上没什么问题啊,想了好久,会不会是因为这是RecyclerView的item的ImageView,是不是它不能超过它父控件的距离呢?(到最后我也没搞懂为什么不显示view,如果知道的同学请告知一下),姑且算是这个问题,那我们就每次都new一个ImageView,添加到主布局中,代码如下:

    @Override
        public void add(final View view, int position) {
            //贝塞尔起始数据点
            int[] startPosition = new int[2];
            //贝塞尔结束数据点
            int[] endPosition = new int[2];
            //控制点
            int[] recyclerPosition = new int[2];
    
            view.getLocationInWindow(startPosition);
            mImageViewShopCat.getLocationInWindow(endPosition);
            mRecyclerView.getLocationInWindow(recyclerPosition);
    
            PointF startF = new PointF();
            PointF endF = new PointF();
            PointF controllF = new PointF();
    
    
            startF.x = startPosition[0];
            startF.y = startPosition[1];
            endF.x = endPosition[0];
            endF.y = endPosition[1];
            controllF.x = endF.x;
            controllF.y = startF.y;
    
            Log.i("wangjtiao", "startF:" + startF.x + "," + startF.y);
            Log.i("wangjtiao", "endF:" + endF.x + "," + endF.y);
            Log.i("wangjtiao", "ControllF:" + endF.x + "," + controllF.y);
            Log.i("wangjtiao", "ControllF:" + recyclerPosition[0] + "," + recyclerPosition[1]);
    
            final ImageView imageView = new ImageView(this);
            main_layout.addView(imageView);
            imageView.setImageResource(R.mipmap.ic_add_circle_blue_700_36dp);
            imageView.getLayoutParams().width = getResources().getDimensionPixelSize(R.dimen.item_dish_circle_size);
            imageView.getLayoutParams().height = getResources().getDimensionPixelSize(R.dimen.item_dish_circle_size);
            imageView.setVisibility(View.VISIBLE);
            imageView.setX(startF.x);
            imageView.setY(startF.y);
    
            ValueAnimator valueAnimator = ValueAnimator.ofObject(new BezierTypeEvaluator(controllF), startF, endF);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    PointF pointF = (PointF) animation.getAnimatedValue();
                    imageView.setX(pointF.x);
                    imageView.setY(pointF.y);
                    Log.i("wangjtiao", "viewF:" + view.getX() + "," + view.getY());
                }
            });
    
    
            valueAnimator.setDuration(800);
            valueAnimator.start();
        }
    

      效果如下:

      

      ??这又是什么鬼,两个控制点出问题了??既然控制点出问题了我们来看看我们控制点怎么得到的:view.getLocationInWindow(int[] location)和view.getLocationOnScreen(int[] location),,感觉也没什么问题啊   我们打印一下我们的贝塞尔两个数据点和一个控制点

    04-10 02:45:33.179 32056-32056/com.qianmo.beziershopcart I/wangjtiao: startF:1014.0,242.0
    04-10 02:45:33.183 32056-32056/com.qianmo.beziershopcart I/wangjtiao: endF:125.0,1656.0
    04-10 02:45:33.183 32056-32056/com.qianmo.beziershopcart I/wangjtiao: ControllF:125.0,242.0
    

      ok,这里我们看不到我们的效果,我们将view.getLocationInWindow(int[] location)替换成view.getLocationOnScreen(int[] location)

    04-10 02:40:44.161 27735-27735/com.qianmo.beziershopcart I/wangjtiao: startF:1014.0,242.0
    04-10 02:40:44.161 27735-27735/com.qianmo.beziershopcart I/wangjtiao: endF:125.0,1656.0
    04-10 02:45:33.183 32056-32056/com.qianmo.beziershopcart I/wangjtiao: ControllF:125.0,242.0
    

      ???为什么两次获取的坐标都是一样的,还有我们的上面动画为什么会偏差这个多,感觉这个高度貌似是我们的状态栏和标题栏的高度啊  ,为了验证我们的猜想,我们隐藏掉状态栏和标题栏试试

    1 //获取当前窗体
    2 final Window window = getWindow();
    3 //隐藏状态栏
    4  window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    5 //隐藏标题栏
    6 requestWindowFeature(Window.FEATURE_NO_TITLE);
    

      效果如下:

      效果实现了,没问题,说明真的是这个问题,那view.getLocationInWindow(int[] location)按照别人博客里面说的就是取的相对坐标啊,我们获取一下我们主界面的mRecyclerView的坐标看看

    04-10 02:45:33.183 32056-32056/com.qianmo.beziershopcart I/wangjtiao: ControllF:0,210
    

      可以看到我们的标题栏+状态栏高度是210,但是我们起始点的坐标是(1014,242)这个有问题啊,应该是(1014,32)这样我们的动画才会在正确的起始位置和结束位置啊。带着我们的疑问,查了半天资料,终于在一个论坛发现了

    因为你的代码显示的界面  contentView < window = screen
    为什么会相等呢,因为此时的Window就是包含状态栏+contentView的大小
    不是你认为的  contentView = window < screen
    除非你的view是从dialog 或者 popupWindow 上显示,
    这时候getLocationInWindow获得的值就是相对的坐标。
    

      所以getLocationInWindow方法获取的是状态栏+contentView的大小,而不是我们以为的contentView的大小,知道了这里我们基本上就知道怎么解决这个问题了,只需要减去这个高度就可以了,我们可以直接减去mRecyclerView的Y坐标即可,代码如下:

     @Override
        public void add(final View view, int position) {
            //贝塞尔起始数据点
            int[] startPosition = new int[2];
            //贝塞尔结束数据点
            int[] endPosition = new int[2];
            //控制点
            int[] recyclerPosition = new int[2];
    
            view.getLocationInWindow(startPosition);
            mImageViewShopCat.getLocationInWindow(endPosition);
            mRecyclerView.getLocationInWindow(recyclerPosition);
    
            PointF startF = new PointF();
            PointF endF = new PointF();
            PointF controllF = new PointF();
    
            startF.x = startPosition[0];
            startF.y = startPosition[1] - recyclerPosition[1];
            endF.x = endPosition[0];
            endF.y = endPosition[1] - recyclerPosition[1];
            controllF.x = endF.x;
            controllF.y = startF.y;
    
            final ImageView imageView = new ImageView(this);
            main_layout.addView(imageView);
            imageView.setImageResource(R.mipmap.ic_add_circle_blue_700_36dp);
            imageView.getLayoutParams().width = getResources().getDimensionPixelSize(R.dimen.item_dish_circle_size);
            imageView.getLayoutParams().height = getResources().getDimensionPixelSize(R.dimen.item_dish_circle_size);
            imageView.setVisibility(View.VISIBLE);
            imageView.setX(startF.x);
            imageView.setY(startF.y);
    
            ValueAnimator valueAnimator = ValueAnimator.ofObject(new BezierTypeEvaluator(controllF), startF, endF);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    PointF pointF = (PointF) animation.getAnimatedValue();
                    imageView.setX(pointF.x);
                    imageView.setY(pointF.y);
                    Log.i("wangjtiao", "viewF:" + view.getX() + "," + view.getY());
                }
            });
    
    
            valueAnimator.setDuration(800);
            valueAnimator.start();
        }
    

      看一下效果:

      

      没问题了,这里的位置也没什么问题,再添加动画完成监听,移除刚刚new的ImageView

    valueAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
    
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
                    imageView.setVisibility(View.GONE);
                    main_layout.removeView(imageView);
                }
    
                @Override
                public void onAnimationCancel(Animator animation) {
    
                }
    
                @Override
                public void onAnimationRepeat(Animator animation) {
    
                }
            });
    
    • 购物车图标从缩小到放大的实现

      这个就很简单了,就是一个简单的属性动画,然后将上面这几个动画放在集合中,代码如下:

    @Override
        public void add(final View view, int position) {
            //贝塞尔起始数据点
            int[] startPosition = new int[2];
            //贝塞尔结束数据点
            int[] endPosition = new int[2];
            //控制点
            int[] recyclerPosition = new int[2];
    
            view.getLocationInWindow(startPosition);
            mImageViewShopCat.getLocationInWindow(endPosition);
            mRecyclerView.getLocationInWindow(recyclerPosition);
    
            PointF startF = new PointF();
            PointF endF = new PointF();
            PointF controllF = new PointF();
    
            startF.x = startPosition[0];
            startF.y = startPosition[1] - recyclerPosition[1];
            endF.x = endPosition[0];
            endF.y = endPosition[1] - recyclerPosition[1];
            controllF.x = endF.x;
            controllF.y = startF.y;
    
            final ImageView imageView = new ImageView(this);
            main_layout.addView(imageView);
            imageView.setImageResource(R.mipmap.ic_add_circle_blue_700_36dp);
            imageView.getLayoutParams().width = getResources().getDimensionPixelSize(R.dimen.item_dish_circle_size);
            imageView.getLayoutParams().height = getResources().getDimensionPixelSize(R.dimen.item_dish_circle_size);
            imageView.setVisibility(View.VISIBLE);
            imageView.setX(startF.x);
            imageView.setY(startF.y);
    
            ValueAnimator valueAnimator = ValueAnimator.ofObject(new BezierTypeEvaluator(controllF), startF, endF);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    PointF pointF = (PointF) animation.getAnimatedValue();
                    imageView.setX(pointF.x);
                    imageView.setY(pointF.y);
                    Log.i("wangjtiao", "viewF:" + view.getX() + "," + view.getY());
                }
            });
    
    
            ObjectAnimator objectAnimatorX = new ObjectAnimator().ofFloat(mImageViewShopCat, "scaleX", 0.6f, 1.0f);
            ObjectAnimator objectAnimatorY = new ObjectAnimator().ofFloat(mImageViewShopCat, "scaleY", 0.6f, 1.0f);
            objectAnimatorX.setInterpolator(new AccelerateInterpolator());
            objectAnimatorY.setInterpolator(new AccelerateInterpolator());
            AnimatorSet set = new AnimatorSet();
            set.play(objectAnimatorX).with(objectAnimatorY).after(valueAnimator);
            set.setDuration(800);
            set.start();
        }
    

      最后的效果:

      

      ok,这样就实现了我们的效果了,有没有很简单,二阶且三个点都是固定的贝塞尔还是很简单的嘛,github代码下载

      但是这里还有个遗留的问题还是没搞懂,为什么RecyclerView的item的ImageView的动画效果不显示!!!!知道的同学请留言或者私信一下,感激(抱拳)了各位。。。

  • 相关阅读:
    Oracle 与.NET Framework 数据类型映射
    mvc使用JsonResult返回Json数据(转)
    like参数替换
    jquery 等比缩放
    【linq to sql】已有打开的与此命令相关联的 DataReader,必须首先将它关闭
    脚本
    2012年计划——开始我的敏捷个人之行
    在Win7 64位机器上安装Oracle 10客户端以及PlSql
    词干提取算法Porter Stemming Algorithm解读
    开源搜索框架Lucene学习之分词器(2)——TokenFilter类及其子类
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6689684.html
Copyright © 2020-2023  润新知