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的動畫效果不顯示!!!!知道的同學請留言或者私信一下,感激(抱拳)了各位。。。