先看下效果图:
1.首先列表布局采用Recycleview
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
<LinearLayout
android:background="#fff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_shop_cart"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="2dp"
android:src="@mipmap/icon_shop_shopcart"/>
<TextView
android:visibility="gone"
android:gravity="center"
android:text="11"
android:id="@+id/tv_num"
android:textColor="#fff"
android:layout_gravity="right"
android:background="@drawable/cart_num"
android:layout_width="20dp"
android:layout_height="20dp"/>
</FrameLayout>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"/>
<TextView
android:layout_width="80dp"
android:layout_height="30dp"
android:layout_marginRight="6dp"
android:background="#f17334"
android:gravity="center"
android:text="购买"
android:textColor="#ffffff"/>
</LinearLayout>
</RelativeLayout>
2.购物车item布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#fff"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@mipmap/icon_shop_goods"/>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/iv"
android:text="麻辣牛肉粉"
android:textColor="#000"/>
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/iv"
android:text="精选上等黄牛肉,加上特制秘方..."
android:textSize="12sp"/>
<TextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv2"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/iv"
android:background="@drawable/shape_discount"
android:paddingLeft="4dp"
android:paddingRight="2dp"
android:text="8折"
android:textColor="#fff"
android:textSize="12sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv2"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/tv3"
android:background="@drawable/shape_users"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:text="饿了么vip专享"
android:textColor="#fff"
android:textSize="12sp"/>
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="10dp"
android:layout_marginTop="40dp"
android:layout_toRightOf="@+id/iv"
android:text="¥19.99元"
android:textColor="#ff00"/>
<TextView
android:id="@+id/tv_old"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/tv_price"
android:layout_marginLeft="5dp"
android:text="¥28.50元"
android:textSize="13sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/iv_reduce"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignBottom="@+id/tv_price"
android:layout_toLeftOf="@+id/tvamount"
android:src="@mipmap/icon_shop_reduce"/>
<TextView
android:id="@+id/tvamount"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignBottom="@+id/tv_price"
android:layout_centerInParent="true"
android:layout_toLeftOf="@+id/iv_add"
android:gravity="center"
android:text="1"
android:textColor="#000"/>
<ImageView
android:id="@+id/iv_add"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignBottom="@+id/tv_price"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:src="@mipmap/icon_shop_add"/>
</RelativeLayout>
3.点击加号操作这里分二钟情况一是当数量为0时减号会执行旋转和平移渐变的动画,二是数量不为0时只会进行抛物线动画,其中抛物线动画实现思路就是得到加号和购物车的坐标,然后得到最外层容器添加一个view来执行这个动画,动画执行完成后移除这个动画:
//得到加号在屏幕的坐标
int[] addLocation = new int[2];
v.getLocationInWindow(addLocation);
//得到购物车图标的坐标
int[] cartLocation = mActivity.getCartLocation();
//添加一个imageview
final ImageView iv = new ImageView(v.getContext());
iv.setBackgroundResource(R.mipmap.icon_shop_add);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(v.getWidth(), v.getHeight());
lp.leftMargin = addLocation[0];
lp.topMargin = addLocation[1] - v.getHeight();
mActivity.getContainer().addView(iv, lp);
//横向移动
ObjectAnimator oaX = ObjectAnimator.ofFloat(iv, "translationX", cartLocation[0] - addLocation[0] + v.getWidth() / 2);
//纵向
ObjectAnimator oaY = ObjectAnimator.ofFloat(iv, "translationY", cartLocation[1] - addLocation[1]);
oaX.setInterpolator(new LinearInterpolator());
oaY.setInterpolator(new AccelerateInterpolator());
AnimatorSet set = new AnimatorSet();
set.play(oaX).with(oaY);
set.setDuration(500).start();
4.完整代码:
private RecyclerView mRecyclerView;
private ImageView mIvCart;
private RelativeLayout mContainer;
private TextView mtvNum;
public int mCount = 0;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shopping_cart);
mRecyclerView = findViewById(R.id.rv);
mIvCart = findViewById(R.id.iv_shop_cart);
mContainer = findViewById(R.id.container);
mtvNum = findViewById(R.id.tv_num);
final List<CartModel> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
CartModel cartModel = new CartModel();
cartModel.setName("红烧牛肉面" + i);
list.add(cartModel);
}
final ShoppingAdapter shoppingAdapter = new ShoppingAdapter(this, list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
mRecyclerView.setAdapter(shoppingAdapter);
//购物车点击事件的回调
}
/**
* 得到布局最外层
*
* @return
*/
public RelativeLayout getContainer() {
return this.mContainer;
}
/**
* 得到购物车在窗体上的坐标
*
* @return
*/
public int[] getCartLocation() {
int[] cartLocation = new int[2];
mIvCart.getLocationInWindow(cartLocation);
return cartLocation;
}
public void setMtvNum() {
if (mCount > 0) {
mtvNum.setText(String.valueOf(mCount));
mtvNum.setVisibility(View.VISIBLE);
}else {
mtvNum.setVisibility(View.GONE);
}
}
private List<CartModel> mDatas;
private int mAmountLeft;
private int mReduceLeft;
private int mAddLeft;
private ShoppingCartActivity mActivity;
public ShoppingAdapter(Activity activity, List<CartModel> list) {
mDatas = list;
this.mActivity = (ShoppingCartActivity) activity;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_shopping_cart, parent, false);
MyHolder holder = new MyHolder(view);
return holder;
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
final MyHolder myHolder = (MyHolder) holder;
myHolder.setItem(position);
//点击加号
myHolder.imageViewAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final CartModel cartModel = mDatas.get(position);
//如果该商品数量为0就进行这个动画
if (cartModel.getCount() == 0) {
myHolder.imageViewReduce.setVisibility(View.VISIBLE);
myHolder.tvAmount.setVisibility(View.VISIBLE);
AnimatorSet set = new AnimatorSet();
//减号
ObjectAnimator ta1 = ObjectAnimator.ofFloat(myHolder.imageViewReduce, "translationX", mAddLeft - mReduceLeft, 0);
ObjectAnimator ra1 = ObjectAnimator.ofFloat(myHolder.imageViewReduce, "rotation", 0, 360);
ObjectAnimator aa1 = ObjectAnimator.ofFloat(myHolder.imageViewReduce, "alpha", 0, 1);
//数字
ObjectAnimator ta2 = ObjectAnimator.ofFloat(myHolder.tvAmount, "translationX", mAddLeft - mAmountLeft, 0);
ObjectAnimator ra2 = ObjectAnimator.ofFloat(myHolder.tvAmount, "rotation", 0, 360);
ObjectAnimator aa2 = ObjectAnimator.ofFloat(myHolder.tvAmount, "alpha", 0, 1);
set.play(ta1).with(ra1).with(ta2).with(ra2).with(aa1).with(aa2);
set.setDuration(500).start();
}
//addGoods2CartAnim((ImageView) v,cartModel);
//得到加号在屏幕的坐标
int[] addLocation = new int[2];
v.getLocationInWindow(addLocation);
//得到购物车图标的坐标
int[] cartLocation = mActivity.getCartLocation();
//添加一个imageview
final ImageView iv = new ImageView(v.getContext());
iv.setBackgroundResource(R.mipmap.icon_shop_add);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(v.getWidth(), v.getHeight());
lp.leftMargin = addLocation[0];
lp.topMargin = addLocation[1] - v.getHeight();
mActivity.getContainer().addView(iv, lp);
//横向移动
ObjectAnimator oaX = ObjectAnimator.ofFloat(iv, "translationX", cartLocation[0] - addLocation[0] + v.getWidth() / 2);
//纵向
ObjectAnimator oaY = ObjectAnimator.ofFloat(iv, "translationY", cartLocation[1] - addLocation[1]);
oaX.setInterpolator(new LinearInterpolator());
oaY.setInterpolator(new AccelerateInterpolator());
AnimatorSet set = new AnimatorSet();
set.play(oaX).with(oaY);
set.setDuration(500).start();
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
//移除这个view
mActivity.getContainer().removeView(iv);
//跟新购物车
cartModel.setCount(cartModel.getCount() + 1);
((MyHolder) holder).tvAmount.setText(String.valueOf(cartModel.getCount()));
mActivity.mCount++;
mActivity.setMtvNum();
}
@Override
public void onAnimationCancel(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
});
}
});
//点击减号
myHolder.imageViewReduce.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final CartModel cartModel = mDatas.get(position);
//如果该商品数量为1就进行这个动画
if (cartModel.getCount() == 1) {
AnimatorSet set = new AnimatorSet();
//减号
ObjectAnimator ta1 = ObjectAnimator.ofFloat(myHolder.imageViewReduce, "translationX", 0, mAddLeft - mReduceLeft);
ObjectAnimator ra1 = ObjectAnimator.ofFloat(myHolder.imageViewReduce, "rotation", 0, 360);
ObjectAnimator aa1 = ObjectAnimator.ofFloat(myHolder.imageViewReduce, "alpha", 1, 0);
//数字
ObjectAnimator ta2 = ObjectAnimator.ofFloat(myHolder.tvAmount, "translationX", 0, mAddLeft - mAmountLeft);
ObjectAnimator ra2 = ObjectAnimator.ofFloat(myHolder.tvAmount, "rotation", 0, 360);
ObjectAnimator aa2 = ObjectAnimator.ofFloat(myHolder.tvAmount, "alpha", 1, 0);
set.play(ta1).with(ra1).with(ta2).with(ra2).with(aa1).with(aa2);
set.setDuration(500).start();
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
cartModel.setCount(cartModel.getCount() - 1);
myHolder.tvAmount.setText(String.valueOf(cartModel.getCount()));
if(cartModel.getCount()==0){
myHolder.tvAmount.setVisibility(View.INVISIBLE);
myHolder.imageViewReduce.setVisibility(View.INVISIBLE);
}
mActivity.mCount--;
mActivity.setMtvNum();
}
@Override
public void onAnimationCancel(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
});
} else {
cartModel.setCount(cartModel.getCount() - 1);
myHolder.tvAmount.setText(String.valueOf(cartModel.getCount()));
mActivity.mCount--;
mActivity.setMtvNum();
}
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
class MyHolder extends RecyclerView.ViewHolder {
TextView title;
ImageView imageViewAdd;
ImageView imageViewReduce;
TextView tvAmount;
TextView tvOld;
public MyHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.tv);
imageViewAdd = itemView.findViewById(R.id.iv_add);
imageViewReduce = itemView.findViewById(R.id.iv_reduce);
tvAmount = itemView.findViewById(R.id.tvamount);
tvOld = itemView.findViewById(R.id.tv_old);
tvOld.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
imageViewAdd.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//得到加号的左边位置
mAddLeft = imageViewAdd.getLeft();
imageViewAdd.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
imageViewReduce.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//得到减号的左边位置
mReduceLeft = imageViewReduce.getLeft();
imageViewReduce.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
tvAmount.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//得到价格的左边位置
mAmountLeft = tvAmount.getLeft();
tvAmount.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
public void setItem(int position) {
CartModel cartModel = mDatas.get(position);
title.setText(cartModel.getName());
tvAmount.setText(String.valueOf(cartModel.getCount()));
if (cartModel.getCount() > 0) {//数目大于0就显示
imageViewReduce.setVisibility(View.VISIBLE);
tvAmount.setVisibility(View.VISIBLE);
} else {//数目小于0就隐藏
imageViewReduce.setVisibility(View.INVISIBLE);
tvAmount.setVisibility(View.INVISIBLE);
}
}
}