购物车特效-贝塞尔曲线动画(点击添加按钮的进候,产生抛物线动画效果)
Posted 六月June June
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了购物车特效-贝塞尔曲线动画(点击添加按钮的进候,产生抛物线动画效果)相关的知识,希望对你有一定的参考价值。
demo效果:
l 购物车特效原理:
1.从添加按钮获取开始坐标
2.从购物车图标获取结束坐标
3.打气一个视图,添加属性动画ObjectAnimator(缩小),ValueAnimator(路线)
4.动画开始时添加该视图,动画结束删除该视图
5.运动路径使用TypeEvaluator与贝塞尔函数计算
activity布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--贝塞尔曲线动画自定义控件-->
<custom.BezierAnim
android:id="@+id/bezier_anim"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!--添加按钮-->
<Button
android:id="@+id/bt_good"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_margin="10dp"
android:text="+" />
<!--购物车-->
<ImageView
android:id="@+id/iv_cart"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:src="@drawable/cart91" />
</RelativeLayout>
移动控件布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="50dp"
android:layout_height="50dp"
android:orientation="vertical">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/coin91" />
</RelativeLayout>
贝塞尔曲线动画的自定义控件编写:
public class BezierAnim extends FrameLayout {
public BezierAnim(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BezierAnim(Context context) {
this(context, null, 0);
}
public BezierAnim(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
//PointF等价于float[]数组,里面存放的x和y的值 (point相当于int[])
private PointF mLocation = new PointF();//这样创建出来,里面还没有值
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//获取当前父布局在界面的屏幕坐标(也就是父布局左上角坐标)
int[] layoutLoc = new int[2];
getLocationInWindow(layoutLoc);
mLocation.set(layoutLoc[0], layoutLoc[1]);//将父布局左上角的值赋值给mLocation
}
/**
* 开始贝塞尔动画
*
* @param startView 动画从哪个view开始(+号)
* @param endView 动画在哪个view结束(购物车)
* @param layoutIdMove 动画作用的移动控件(钱袋子的布局)
*/
public void startCartAnim(View startView, View endView, int layoutIdMove) {
//1,开始位置
int[] startLoc = new int[2];
startView.getLocationInWindow(startLoc);//获取当前view在屏幕上的坐标
PointF startF = new PointF(startLoc[0] - mLocation.x, startLoc[1] - mLocation.y);//得到当前view相对于父布局左上角位置的坐标
// 2,结束位置
int[] endLoc = new int[2];
endView.getLocationInWindow(endLoc);
final PointF endF = new PointF(endLoc[0] - mLocation.x, endLoc[1] - mLocation.y);
//3.移动控件。inflate()参数:作用布局,参考布局,false
final View moveView = LayoutInflater.from(getContext()).inflate(layoutIdMove, this, false);
//开始动画 使用属性动画合集
AnimatorSet set = new AnimatorSet();
//缩小动画
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(moveView, "scaleX", 1.0f, 0.1f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(moveView, "scaleY", 1.0f, 0.1f);
//路径动画(baisaier曲线路径,开始坐标,结束坐标)
ValueAnimator pathAnim = ObjectAnimator.ofObject(beisaier, startF, endF);
pathAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//更新坐标
PointF newPointF = (PointF) animation.getAnimatedValue();
moveView.setX(newPointF.x);
moveView.setY(newPointF.y);
}
});
//将这些动画放入集合中
set.playTogether(scaleXAnim, scaleYAnim, pathAnim);
Animator.AnimatorListener listener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
BezierAnim.this.addView(moveView);//加入动画作用的控件
}
@Override
public void onAnimationEnd(Animator animation) {
BezierAnim.this.removeView(moveView);//移除动画作用的控件
}
@Override
public void onAnimationCancel(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
};
set.addListener(listener);//动画播放监听器
set.setDuration(1000); //运动时间
set.start();
}
//路径计算器
private TypeEvaluator<PointF> beisaier = new TypeEvaluator<PointF>() {
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
//返回变化的轨迹坐标
PointF newF = new PointF((startValue.x + endValue.x) / 2, 0);//控制点
return BezierCurve.bezier(fraction, startValue, newF, endValue);
}
};
}
路径计算器:
public class BezierCurve {
/**
* 二次贝塞尔曲线插值
* t:值范围from = 0, to = 1
*/
public static PointF bezier(float t, PointF point0, PointF point1, PointF point2) {
float oneMinusT = 1.0f - t;
PointF point = new PointF();
point.x = oneMinusT * oneMinusT * point0.x
+ 2 * t * oneMinusT * point1.x
+ t * t * point2.x;
point.y = oneMinusT * oneMinusT * point0.y
+ 2 * t * oneMinusT * point1.y
+ t * t * point2.y;
return point;
}
/**
* 三次贝塞尔曲线插值
* t:值范围from = 0, to = 1
*/
public static PointF bezier(float t, PointF point0, PointF point1, PointF point2, PointF point3) {
float oneMinusT = 1.0f - t;
PointF point = new PointF();
point.x = oneMinusT * oneMinusT * oneMinusT * (point0.x)
+ 3 * oneMinusT * oneMinusT * t * (point1.x)
+ 3 * oneMinusT * t * t * (point2.x)
+ t * t * t * (point3.x);
point.y = oneMinusT * oneMinusT * oneMinusT * (point0.y)
+ 3 * oneMinusT * oneMinusT * t * (point1.y)
+ 3 * oneMinusT * t * t * (point2.y)
+ t * t * t * (point3.y);
return point;
}
}
activity开始动画:
public class CartBazierActivity extends Activity {
@InjectView(R.id.bt_good)
Button btGood;
@InjectView(R.id.iv_cart)
ImageView ivCart;
@InjectView(R.id.bezier_anim)
BezierAnim bezierAnim;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cart_bezier);
ButterKnife.inject(this);
}
@OnClick(R.id.bt_good)
public void bezierMove() {
Toast.makeText(this, "添加了一件商品", Toast.LENGTH_SHORT).show();
bezierAnim.startCartAnim(btGood, ivCart, R.layout.moveview);
}
}
若是startView和endView不在一个界面,可以用EventBus传值
更多:http://www.jb51.net/article/95991.htm
以上是关于购物车特效-贝塞尔曲线动画(点击添加按钮的进候,产生抛物线动画效果)的主要内容,如果未能解决你的问题,请参考以下文章