贝塞尔曲线之购物车动画效果.docx
- 文档编号:11926819
- 上传时间:2023-04-16
- 格式:DOCX
- 页数:18
- 大小:91.87KB
贝塞尔曲线之购物车动画效果.docx
《贝塞尔曲线之购物车动画效果.docx》由会员分享,可在线阅读,更多相关《贝塞尔曲线之购物车动画效果.docx(18页珍藏版)》请在冰豆网上搜索。
贝塞尔曲线之购物车动画效果
贝塞尔曲线之购物车动画效果
Question
贝塞尔曲线是什么?
贝塞尔曲线可以做什么?
怎么做?
Whatisit?
贝塞尔曲线在XX定义是贝塞尔曲线(Béziercurve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。
Usage
贝塞尔曲线根据不同点实现不同动态效果:
一阶贝塞尔曲线(两点),绘制成一条直线
看了上面贝塞尔曲线不同点不同效果后,相信大家都清楚贝塞尔曲线能干什么?
没错,贝塞尔曲线能造高逼格动画
就笔者目前了解的采用贝塞尔曲线实现的知名开源项目有:
QQ拖拽清除效果
纸飞机刷新动画
滴油刷新动画
波浪动画
到此大家是不是很兴奋,想更多了解如何造一个高逼格贝塞尔曲线动画。
接下来我就给大家讲述如何造一个基于贝塞尔曲线实现的购物车动画,大家擦亮眼睛啦~~
Howtodoit?
思路
确定动画起终点
在起终点之间使用二次贝塞尔曲线填充起终点之间点的轨迹
设置属性动画,ValueAnimator插值器,获取中间点的坐标
将执行动画控件的x、y坐标设为上面得到的中间点坐标
开启属性动画
当动画结束时的操作
知识点
Android中提供了绘制一阶、二阶、三阶的接口:
一阶接口:
publicvoidlineTo(floatx,floaty)
二阶接口:
publicvoidquadTo(floatx1,floaty1,floatx2,floaty2)
三阶接口:
publicvoidcubicTo(floatx1,floaty1,floatx2,floaty2,floatx3,floaty3)
PathMeasure使用
getLength()
理解booleangetPosTan(floatdistance,float[]pos,float[]tan)
如何获取控件在屏幕中的绝对坐标
int[]location=newint[2];view.getLocationInWindow(location);得到view在屏幕中的绝对坐标。
理解属性动画插值器ValueAnimator
Code
首先写购物车布局xml,代码如下:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
xmlversion="1.0"encoding="utf-8"?
>
android:
id="@+id/rly_bezier_curve_shopping_cart"
android:
layout_width="match_parent"
android:
layout_height="match_parent"
android:
paddingBottom="@dimen/activity_vertical_margin"
android:
paddingLeft="@dimen/activity_horizontal_margin"
android:
paddingRight="@dimen/activity_horizontal_margin"
android:
paddingTop="@dimen/activity_vertical_margin">
android: id="@+id/fly_bezier_curve_shopping_cart" android: layout_width="match_parent" android: layout_height="wrap_content" android: layout_alignParentBottom="true" android: layout_alignParentLeft="true" android: paddingRight="30dp" android: layout_alignParentStart="true"> android: id="@+id/iv_bezier_curve_shopping_cart" android: layout_width="40dp" android: layout_height="40dp" android: layout_gravity="right" android: src="@drawable/menu_shop_car_selected"/> android: id="@+id/tv_bezier_curve_shopping_cart_count" android: layout_width="wrap_content" android: layout_height="wrap_content" android: textColor="@color/white" android: background="@drawable/corner_view" android: text="0" android: layout_gravity="right"/>
android: id="@+id/lv_bezier_curve_shopping_cart" android: layout_width="match_parent" android: layout_height="match_parent" android: layout_above="@+id/fly_bezier_curve_shopping_cart"/> 然后写购物车适配器、实体类,代码如下: [java]viewplaincopy在CODE上查看代码片派生到我的代码片 /** *@className: GoodsAdapter *@classDescription: 购物车商品适配器 *@author: leibing *@createTime: 2016/09/28 */ publicclassGoodsAdapterextendsBaseAdapter{ //数据源(购物车商品图片) privateArrayList //布局 privateLayoutInflatermLayoutInflater; //回调监听 privateCallBackListenermCallBackListener; /** *构造函数 *@authorleibing *@createTime2016/09/28 *@lastModify2016/09/28 *@paramcontext上下文 *@parammData数据源(购物车商品图片) *@return */ publicGoodsAdapter(Contextcontext,ArrayList mLayoutInflater=LayoutInflater.from(context); this.mData=mData; } @Override publicintgetCount(){ returnmData! =null? mData.size(): 0; } @Override publicObjectgetItem(inti){ returnmData! =null? mData.get(i): null; } @Override publiclonggetItemId(inti){ returni; } @Override publicViewgetView(inti,Viewview,ViewGroupviewGroup){ ViewHolderviewHolder; if(view==null){ view=mLayoutInflater.inflate(R.layout.adapter_shopping_cart_item,null); viewHolder=ewViewHolder(view); view.setTag(viewHolder); }else{ //复用ViewHolder viewHolder=(ViewHolder)view.getTag(); } //更新UI if(i viewHolder.updateUI(mData.get(i)); returnview; } /** *@className: ViewHolder *@classDescription: 商品ViewHolder *@author: leibing *@createTime: 2016/09/28 */ classViewHolder{ //显示商品图片 privateImageViewmShoppingCartItemIv; /** *构造函数 *@authorleibing *@createTime2016/09/28 *@lastModify2016/09/28 *@paramview视图 *@return */ publicViewHolder(Viewview){ //findView mShoppingCartItemIv=ImageView)view.findViewById(R.id.iv_shopping_cart_item); //onClick view.findViewById(R.id.tv_shopping_cart_item).setOnClickListener( newView.OnClickListener(){ @Override publicvoidonClick(Viewview){ if(mShoppingCartItemIv! =null&&mCallBackListener! =null) mCallBackListener.callBackImg(mShoppingCartItemIv); } }); } /** *更新UI *@authorleibing *@createTime2016/09/28 *@lastModify2016/09/28 *@paramgoods商品实体对象 *@return */ publicvoidupdateUI(GoodsModelgoods){ if(goods! =null &&goods.getmGoodsBitmap()! =null &&mShoppingCartItemIv! =null) mShoppingCartItemIv.setImageBitmap(goods.getmGoodsBitmap()); } } /** *设置回调监听 *@authorleibing *@createTime2016/09/28 *@lastModify2016/09/28 *@parammCallBackListener回调监听 *@return */ publicvoidsetCallBackListener(CallBackListenermCallBackListener){ this.mCallBackListener=mCallBackListener; } /** *@interfaceName: CallBackListener *@interfaceDescription: 回调监听 *@author: leibing *@createTime: 2016/09/28 */ publicinterfaceCallBackListener{ voidcallBackImg(ImageViewgoodsImg); } } 然后写添加数据源以及设置适配器,代码如下: [java]viewplaincopy在CODE上查看代码片派生到我的代码片 //购物车父布局 privateRelativeLayoutmShoppingCartRly; //购物车列表显示 privateListViewmShoppingCartLv; //购物数目显示 privateTextViewmShoppingCartCountTv; //购物车图片显示 privateImageViewmShoppingCartIv; //购物车适配器 privateGoodsAdaptermGoodsAdapter; //数据源(购物车商品图片) privateArrayList //贝塞尔曲线中间过程点坐标 privatefloat[]mCurrentPosition=newfloat[2]; //路径测量 privatePathMeasuremPathMeasure; //购物车商品数目 privateintgoodsCount=0; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //findView mShoppingCartLv=(ListView)findViewById(R.id.lv_bezier_curve_shopping_cart); mShoppingCartCountTv=(TextView)findViewById(R.id.tv_bezier_curve_shopping_cart_count); mShoppingCartRly=(RelativeLayout)findViewById(R.id.rly_bezier_curve_shopping_cart); mShoppingCartIv=(ImageView)findViewById(R.id.iv_bezier_curve_shopping_cart); //是否显示购物车商品数目 isShowCartGoodsCount(); //添加数据源 addData(); //设置适配器 setAdapter(); } /** *设置适配器 *@authorleibing *@createTime2016/09/28 *@lastModify2016/09/28 *@param *@return */ privatevoidsetAdapter(){ //初始化适配器 mGoodsAdapter=newGoodsAdapter(this,mData); //设置适配器监听 mGoodsAdapter.setCallBackListener(newGoodsAdapter.CallBackListener(){ @Override publicvoidcallBackImg(ImageViewgoodsImg){ //添加商品到购物车 addGoodsToCart(goodsImg); } }); //设置适配器 mShoppingCartLv.setAdapter(mGoodsAdapter); } 接下来写最重要的一块,添加商品到购物车,代码如下: [java]viewplaincopy在CODE上查看代码片派生到我的代码片 /** *添加商品到购物车 *@authorleibing *@createTime2016/09/28 *@lastModify2016/09/28 *@paramgoodsImg商品图标 *@return */ privatevoidaddGoodsToCart(ImageViewgoodsImg){ //创造出执行动画的主题goodsImg(这个图片就是执行动画的图片,从开始位置出发,经过一个抛物线(贝塞尔曲线),移动到购物车里) finalImageViewgoods=newImageView(this); goods.setImageDrawable(goodsImg.getDrawable()); RelativeLayout.LayoutParamsparams=newRelativeLayout.LayoutParams(100,100); mShoppingCartRly.addView(goods,params); //得到父布局的起始点坐标(用于辅助计算动画开始/结束时的点的坐标) int[]parentLocation=ewint[2]; mShoppingCartRly.getLocationInWindow(parentLocation); //得到商品图片的坐标(用于计算动画开始的坐标) intstartLoc[]=newint[2]; goodsImg.getLocationInWindow(startLoc); //得到购物车图片的坐标(用于计算动画结束后的坐标) intendLoc[]=newint[2]; mShoppingCartIv.getLocationInWindow(endLoc); //开始掉落的商品的起始点: 商品起始点-父布局起始点+该商品图片的一半 floatstartX=startLoc[0]-parentLocation[0]+goodsImg.getWidth()/2; floatstartY=startLoc[1]-parentLocation[1]+goodsImg.getHeight()/2; //商品掉落后的终点坐标: 购物车起始点-父布局起始点+购物车图片的1/5 floattoX=endLoc[0]-parentLocation[0]+mShoppingCartIv.getWidth()/5; floattoY=endLoc[1]-parentLocation[1]; //开始绘制贝塞尔曲线 Pathpath=newPath(); //移动到起始点(贝塞尔曲线的起点) path.moveTo(startX,startY); //使用二阶贝塞尔曲线: 注意第一个起始坐标越大,贝塞尔曲线的横向距离就会越大,一般按照下面的式子取即可 path.quadTo((startX+toX)/2,startY,toX,toY); //mPathMeasure用来计算贝塞尔曲线的曲线长度和贝塞尔曲线中间插值的坐标,如果是true,path会形成一个闭环 mPathMeasure=newPathMeasure(path,false); //属性动画实现(从0到贝塞尔曲线的长度之间进行插值计算,获取中间过程的距离值) ValueAnimatorvalueAnimator=ValueAnimator.ofFloat(0,mPathMeasure.getLength()); valueAnimator.setDuration(500); //匀速线性插值器 valueAnimator.setInterpolator(newLinearInterpolator()); valueAnimator.addUpdateListener(newValueAnimator.AnimatorUpdateListener(){ @Override publicvoidonAnimationUpdate(ValueAnimatoranimation){ //当插值计算进行时,获取中间的每个值, //这里这个值是中间过程中的曲线长度(下面根据这个值来得出中间点的坐标值) floatvalue=(Float)animation.getAnimatedValue(); //获取当前点坐标封装到mCurrentPosition //booleangetPosTan(floatdistance,float[]pos,float[]tan): //传入一个距离distance(0<=distance<=getLength()),然后会计算当前距离的坐标点和切线,pos会自动填充上坐标,这个方法很重要。 //mCurrentPosition此时就是中间距离点的坐标值 mPathMeasure.getPosTan(value,mCurrentPosition,null); //移动的商品图片(动画图片)的坐标设置为该中间点的坐标 goods.setTranslationX(mCurrentPosition[0]); goods.setTranslationY(mCurrentPosition[1]); } }); //开始执行动画 valueAnimator.start(); //动画结束后的处理 valueAnimator.addListener(newAnimator.AnimatorListener(){ @Oride publicvoidonAnimationStart(Animatoranimation){
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 贝塞尔 曲线 购物 动画 效果
![提示](https://static.bdocx.com/images/bang_tan.gif)