Android -- 贝塞尔二阶实现饿了么加入购物车效果
1,上周我們實(shí)現(xiàn)了簡(jiǎn)單的三階貝塞爾曲線效果實(shí)例,今天是使用二階貝塞爾曲線加動(dòng)畫實(shí)現(xiàn)的加入購(gòu)物車效果,在碼代碼過(guò)程中出現(xiàn)了些問(wèn)題,過(guò)一下和大家來(lái)探討探討,先看一下效果圖
2,從上面的效果來(lái)看我們基本上可以把功能拆分為兩個(gè)動(dòng)畫效果:+號(hào)圖片按照曲線掉下(曲線的軌跡就是一個(gè)簡(jiǎn)單的貝塞爾曲線)、購(gòu)物車圖標(biāo)從縮小到放大。知道了實(shí)現(xiàn)的原理我們開(kāi)始我們功能的實(shí)現(xiàn)
- 實(shí)現(xiàn)基本基本布局、RecyclerView展示數(shù)據(jù)
從上面的效果我們可以得到,我們的布局是一個(gè)簡(jiǎn)單的RecyclerView和下面的RelativeLayout,布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayoutxmlns: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.RecyclerViewandroid:id="@+id/recycler"android:layout_width="match_parent"android:layout_height="match_parent"></android.support.v7.widget.RecyclerView><LinearLayoutandroid: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><FrameLayoutandroid: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"><ImageViewandroid: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實(shí)體類、添加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;}@Overridepublic MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_shop_menu, parent, false));}@Overridepublic 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() {@Overridepublic void onClick(View v) {if (mShopOnClickListtener != null) {mShopOnClickListtener.add(v, position);}}});holder.ic_reduce.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (mShopOnClickListtener != null) {mShopOnClickListtener.remove(v, position);}}});}@Overridepublic 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中簡(jiǎn)單的添加數(shù)據(jù)
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;@Overrideprotected 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);}@Overridepublic void add(final View view, int position) {Toast.makeText(mContext, "加", Toast.LENGTH_SHORT).show();}@Overridepublic void remove(View view, int position) {Toast.makeText(mContext, "減", Toast.LENGTH_SHORT).show();} }看一下我們的效果:
OK,大致的展示效果基本上是實(shí)現(xiàn)了
- 使用加入購(gòu)物車效果
下面我們來(lái)實(shí)現(xiàn)貝塞爾曲線效果,首先獲取兩個(gè)數(shù)據(jù)點(diǎn):一個(gè)是每次點(diǎn)擊“+”號(hào)的坐標(biāo)位置、一個(gè)是下面紅色的購(gòu)物車圖標(biāo)。控制點(diǎn)我打算取開(kāi)始點(diǎn)的Y坐標(biāo)和結(jié)束點(diǎn)的X坐標(biāo),那么怎么獲取當(dāng)前控件相對(duì)于整個(gè)屏幕的坐標(biāo)呢,這里View里面有一個(gè)getLocationInWindow()方法(這里要留心一下這個(gè)方法),然后不了解的同學(xué)可以搜索一下view.getLocationInWindow(int[] location)和view.getLocationOnScreen(int[] location),方法的區(qū)別,這里我從網(wǎng)上偷了了一個(gè)圖,如下:
getLocationInWindow是以B為原點(diǎn)的C的坐標(biāo)getLocationOnScreen以A為原點(diǎn)ok,這樣我們看一下我們的貝塞爾三個(gè)坐標(biāo)的初始化
@Overridepublic void add(final View view, int position) {//貝塞爾起始數(shù)據(jù)點(diǎn)int[] startPosition = new int[2];//貝塞爾結(jié)束數(shù)據(jù)點(diǎn)int[] endPosition = new int[2];//控制點(diǎn)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; }繼續(xù),自定義差值器,我們按照貝塞爾的三階公式來(lái)套,上一篇詳細(xì)的介紹過(guò)了就不在廢話了,這里不懂的話建議你去看一下我的上一篇博客,里面有詳細(xì)的介紹
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;}@Overridepublic 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;} }
開(kāi)啟動(dòng)畫自動(dòng)調(diào)用
@Overridepublic void add(final View view, int position) {//貝塞爾起始數(shù)據(jù)點(diǎn)int[] startPosition = new int[2];//貝塞爾結(jié)束數(shù)據(jù)點(diǎn)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() {@Overridepublic 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();}按照我們的思路,這個(gè)功能基本上是實(shí)現(xiàn)了,感覺(jué)很簡(jiǎn)單,又可以多了些時(shí)間去打兩把王者農(nóng)藥了,看一下我們的效果圖:
呃!!!我的動(dòng)畫呢??? ,看一下我們打印動(dòng)畫軌跡的效果
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.0view的坐標(biāo)一直在改變啊!思路上沒(méi)什么問(wèn)題啊,想了好久,會(huì)不會(huì)是因?yàn)檫@是RecyclerView的item的ImageView,是不是它不能超過(guò)它父控件的距離呢?(到最后我也沒(méi)搞懂為什么不顯示view,如果知道的同學(xué)請(qǐng)告知一下),姑且算是這個(gè)問(wèn)題,那我們就每次都new一個(gè)ImageView,添加到主布局中,代碼如下:
@Overridepublic void add(final View view, int position) {//貝塞爾起始數(shù)據(jù)點(diǎn)int[] startPosition = new int[2];//貝塞爾結(jié)束數(shù)據(jù)點(diǎn)int[] endPosition = new int[2];//控制點(diǎn)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() {@Overridepublic 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();}效果如下:
??這又是什么鬼,兩個(gè)控制點(diǎn)出問(wèn)題了??既然控制點(diǎn)出問(wèn)題了我們來(lái)看看我們控制點(diǎn)怎么得到的:view.getLocationInWindow(int[] location)和view.getLocationOnScreen(int[] location),,感覺(jué)也沒(méi)什么問(wèn)題啊 ? 我們打印一下我們的貝塞爾兩個(gè)數(shù)據(jù)點(diǎn)和一個(gè)控制點(diǎn)
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.0ok,這里我們看不到我們的效果,我們將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???為什么兩次獲取的坐標(biāo)都是一樣的,還有我們的上面動(dòng)畫為什么會(huì)偏差這個(gè)多,感覺(jué)這個(gè)高度貌似是我們的狀態(tài)欄和標(biāo)題欄的高度啊 ?,為了驗(yàn)證我們的猜想,我們隱藏掉狀態(tài)欄和標(biāo)題欄試試
1 //獲取當(dāng)前窗體 2 final Window window = getWindow(); 3 //隱藏狀態(tài)欄 4 window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 5 //隱藏標(biāo)題欄 6 requestWindowFeature(Window.FEATURE_NO_TITLE);效果如下:
效果實(shí)現(xiàn)了,沒(méi)問(wèn)題,說(shuō)明真的是這個(gè)問(wèn)題,那view.getLocationInWindow(int[] location)按照別人博客里面說(shuō)的就是取的相對(duì)坐標(biāo)啊,我們獲取一下我們主界面的mRecyclerView的坐標(biāo)看看
04-10 02:45:33.183 32056-32056/com.qianmo.beziershopcart I/wangjtiao: ControllF:0,210可以看到我們的標(biāo)題欄+狀態(tài)欄高度是210,但是我們起始點(diǎn)的坐標(biāo)是(1014,242)這個(gè)有問(wèn)題啊,應(yīng)該是(1014,32)這樣我們的動(dòng)畫才會(huì)在正確的起始位置和結(jié)束位置啊。帶著我們的疑問(wèn),查了半天資料,終于在一個(gè)論壇發(fā)現(xiàn)了
因?yàn)槟愕拇a顯示的界面 contentView < window = screen 為什么會(huì)相等呢,因?yàn)榇藭r(shí)的Window就是包含狀態(tài)欄+contentView的大小 不是你認(rèn)為的 contentView = window < screen 除非你的view是從dialog 或者 popupWindow 上顯示, 這時(shí)候getLocationInWindow獲得的值就是相對(duì)的坐標(biāo)。所以getLocationInWindow方法獲取的是狀態(tài)欄+contentView的大小,而不是我們以為的contentView的大小,知道了這里我們基本上就知道怎么解決這個(gè)問(wèn)題了,只需要減去這個(gè)高度就可以了,我們可以直接減去mRecyclerView的Y坐標(biāo)即可,代碼如下:
@Overridepublic void add(final View view, int position) {//貝塞爾起始數(shù)據(jù)點(diǎn)int[] startPosition = new int[2];//貝塞爾結(jié)束數(shù)據(jù)點(diǎn)int[] endPosition = new int[2];//控制點(diǎn)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() {@Overridepublic 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();}看一下效果:
沒(méi)問(wèn)題了,這里的位置也沒(méi)什么問(wèn)題,再添加動(dòng)畫完成監(jiān)聽(tīng),移除剛剛new的ImageView
valueAnimator.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {imageView.setVisibility(View.GONE);main_layout.removeView(imageView);}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});- 購(gòu)物車圖標(biāo)從縮小到放大的實(shí)現(xiàn)
這個(gè)就很簡(jiǎn)單了,就是一個(gè)簡(jiǎn)單的屬性動(dòng)畫,然后將上面這幾個(gè)動(dòng)畫放在集合中,代碼如下:
@Overridepublic void add(final View view, int position) {//貝塞爾起始數(shù)據(jù)點(diǎn)int[] startPosition = new int[2];//貝塞爾結(jié)束數(shù)據(jù)點(diǎn)int[] endPosition = new int[2];//控制點(diǎn)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() {@Overridepublic 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,這樣就實(shí)現(xiàn)了我們的效果了,有沒(méi)有很簡(jiǎn)單,二階且三個(gè)點(diǎn)都是固定的貝塞爾還是很簡(jiǎn)單的嘛,github代碼下載
但是這里還有個(gè)遺留的問(wèn)題還是沒(méi)搞懂,為什么RecyclerView的item的ImageView的動(dòng)畫效果不顯示!!!!知道的同學(xué)請(qǐng)留言或者私信一下,感激(抱拳)了各位。。。
?
總結(jié)
以上是生活随笔為你收集整理的Android -- 贝塞尔二阶实现饿了么加入购物车效果的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 读书笔记《React引领未来的用户界面开
- 下一篇: Webbench网站压力测试