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