Android做加入购物车,Android实现购物车添加商品动画

本文实例为大家分享了Android实现购物车添加商品动画的具体代码,供大家参考,具体内容如下

实现需求:

在商品列表页面,从列表Item 添加商品的时候,需要一个动画,仿佛是是往购物车里添加商品。

实现思路:

获取起始点与终点的坐标,利用PathMeasure 绘制贝塞尔曲线;

为点击的Item 商品View 设置属性动画;

监听属性动画的update,改变View 的坐标;

实现效果:

0b46e7501c65b425a1d0299a76cf6913.gif

实现中会用到 PathMeasure 类:

我们主要使用它两个方法:

1、获取长度:

/** //获取弧线的总长度(周长)

* Return the total length of the current contour, or 0 if no path is

* associated with this measure object.

*/

public float getLength() {

return native_getLength(native_instance);//系统调用native 方法;

}

2、获取坐标:

/**

* Pins distance to 0 <= distance <= getLength(), and then computes the

* corresponding position and tangent. Returns false if there is no path,

* or a zero-length path was specified, in which case position and tangent

* are unchanged.

*

* @param distance The distance along the current contour to sample

* @param pos If not null, eturns the sampled position (x==[0], y==[1])

* @param tan If not null, returns the sampled tangent (x==[0], y==[1])

* @return false if there was no path associated with this measure object

*/

public boolean getPosTan(float distance, float pos[], float tan[]) {

if (pos != null && pos.length < 2 ||

tan != null && tan.length < 2) {

throw new ArrayIndexOutOfBoundsException();

}

return native_getPosTan(native_instance, distance, pos, tan);

}

方法 getPosTan(float distance, float pos[],float tan[]) - path 为 null ,返回 false

distance 为一个 0 - getLength() 之间的值,根据这个值 PathMeasure 会计算出当前点的坐标封装到 pos 中。上面这句话我们可以这么来理解,不管实际 Path 多么的复杂,PathMeasure 都相当于做了一个事情,就是把 Path “拉直”,然后给了我们一个接口(getLength)告诉我们path的总长度,然后我们想要知道具体某一点的坐标,只需要用相对的distance去取即可,这样就省去了自己用函数模拟path,然后计算获取点坐标的过程。

代码如下:

public class GoodsListActivity extends AppCompatActivity {

private RelativeLayout mRootRl;

private RecyclerView mGoodsRecyclerView;

private ImageView mCarImageView;

private TextView mCountTv;

private List mBitmapList = new ArrayList<>();

private PathMeasure mPathMeasure;

private float[] mCurrentPosition = new float[2];

private int mCount = 0;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_goods_list);

initView();

initData();

GoodsAdapter goodsAdapter = new GoodsAdapter(mBitmapList);

mGoodsRecyclerView.setLayoutManager(new LinearLayoutManager(this));

mGoodsRecyclerView.setAdapter(goodsAdapter);

}

private void initView(){

mGoodsRecyclerView = (RecyclerView)findViewById(R.id.recyclerView);

mCarImageView = (ImageView)findViewById(R.id.imageview_shop_car);

mCountTv = (TextView)findViewById(R.id.tv_count);

mRootRl = (RelativeLayout)findViewById(R.id.rl_root);

}

private void initData(){

mBitmapList.add(BitmapFactory.decodeResource(getResources(), R.drawable.car));

mBitmapList.add(BitmapFactory.decodeResource(getResources(), R.drawable.car));

mBitmapList.add(BitmapFactory.decodeResource(getResources(), R.drawable.car));

}

class GoodsAdapter extends RecyclerView.Adapter{

private List mData;

public GoodsAdapter(List data) {

mData = data;

}

@Override

public GoodsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View itemView = LayoutInflater.from(GoodsListActivity.this)

.inflate(R.layout.rv_goods_item, parent, false);

return new GoodsViewHolder(itemView);

}

@Override

public void onBindViewHolder(final GoodsViewHolder holder, int position) {

holder.ivGood.setImageBitmap(mData.get(position));

holder.tvBuy.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

addGoodToCar(holder.ivGood);

}

});

}

@Override

public int getItemCount() {

return mData != null ? mData.size() : 0;

}

}

private void addGoodToCar(ImageView imageView){

final ImageView view = new ImageView(GoodsListActivity.this);

view.setImageDrawable(imageView.getDrawable());

RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(100, 100);

mRootRl.addView(view, layoutParams);

//二、计算动画开始/结束点的坐标的准备工作

//得到父布局的起始点坐标(用于辅助计算动画开始/结束时的点的坐标)

int[] parentLoc = new int[2];

mRootRl.getLocationInWindow(parentLoc);

//得到商品图片的坐标(用于计算动画开始的坐标)

int startLoc[] = new int[2];

imageView.getLocationInWindow(startLoc);

//得到购物车图片的坐标(用于计算动画结束后的坐标)

int endLoc[] = new int[2];

mCarImageView.getLocationInWindow(endLoc);

float startX = startLoc[0] - parentLoc[0] + imageView.getWidth()/2;

float startY = startLoc[1] - parentLoc[1] + imageView.getHeight()/2;

//商品掉落后的终点坐标:购物车起始点-父布局起始点+购物车图片的1/5

float toX = endLoc[0] - parentLoc[0] + mCarImageView.getWidth() / 5;

float toY = endLoc[1] - parentLoc[1];

//开始绘制贝塞尔曲线

Path path = new Path();

path.moveTo(startX, startY);

//使用二次萨贝尔曲线:注意第一个起始坐标越大,贝塞尔曲线的横向距离就会越大,一般按照下面的式子取即可

path.quadTo((startX + toX) / 2, startY, toX, toY);

mPathMeasure = new PathMeasure(path, false);

//属性动画

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());

valueAnimator.setDuration(1000);

valueAnimator.setInterpolator(new LinearInterpolator());

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

float value = (float)animation.getAnimatedValue();

mPathMeasure.getPosTan(value, mCurrentPosition, null);

view.setTranslationX(mCurrentPosition[0]);

view.setTranslationY(mCurrentPosition[1]);

}

});

valueAnimator.addListener(new Animator.AnimatorListener() {

@Override

public void onAnimationStart(Animator animation) {

}

@Override

public void onAnimationEnd(Animator animation) {

// 购物车的数量加1

mCount++;

mCountTv.setText(String.valueOf(mCount));

// 把移动的图片imageview从父布局里移除

mRootRl.removeView(view);

//shopImg 开始一个放大动画

Animation scaleAnim = AnimationUtils.loadAnimation(GoodsListActivity.this, R.anim.shop_car_scale);

mCarImageView.startAnimation(scaleAnim);

}

@Override

public void onAnimationCancel(Animator animation) {

}

@Override

public void onAnimationRepeat(Animator animation) {

}

});

valueAnimator.start();

}

class GoodsViewHolder extends RecyclerView.ViewHolder{

private ImageView ivGood;

private TextView tvBuy;

public GoodsViewHolder(View itemView) {

super(itemView);

ivGood = (ImageView)itemView.findViewById(R.id.iv_goods);

tvBuy = (TextView) itemView.findViewById(R.id.tv_buy);

}

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值