Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画

0.首先。先给出一张效果gif图。

1.贝塞尔曲线原理及相关公式參考:http://www.jianshu.com/p/c0d7ad796cee 作者:许方镇

2.原理:计算被点击 view、购物车view 以及他们所在父容器相对于屏幕的坐标。

3.在呗点击View坐标位置 父容器通过addView 添加须要完毕动画的imgview。

4.自己定义估值器 通过二次贝塞尔曲线公式(2个数据点,一个控制点)完毕抛物线路径上的点xy坐标计算。

5.利用属性动画 +自己定义估值器 完毕imgview在父容器内部的抛物线动画。

6.先给布局。当中包括一个ListView、 一个ImageView 、须要用到的父容器。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ffe1"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"> <RelativeLayout
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"> <ListView
android:id="@+id/main_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#0011ff"
android:dividerHeight="2dp"/>
<!-- shop img-->
<ImageView
android:id="@+id/main_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:layout_marginLeft="20dp"
android:src="@mipmap/shop"/>
</RelativeLayout> </LinearLayout>

7. 给出ListView 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="wrap_content"
android:background="#FFF"
android:padding="30dp"> <TextView
android:id="@+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#F00"
android:textSize="20sp"/> <ImageView
android:id="@+id/item_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@mipmap/add"/> </RelativeLayout>

8.给出ListView Adapter代码 不过点击时添加了回调接口:

public class ItemAdapter extends BaseAdapter implements View.OnClickListener {
List<String> data = new ArrayList<>();
Context mContext; public ItemAdapter(Context context) {
mContext = context;
for (int i = 0; i < 30; i++) {
data.add("item+" + i);
}
} @Override
public int getCount() {
return data.size();
} @Override
public Object getItem(int position) {
return data.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false);
convertView.setTag(new ViewH(convertView));
}
ViewH holder = (ViewH) convertView.getTag();
holder.tv.setText(data.get(position));
holder.img.setOnClickListener(this);
return convertView;
} @Override
public void onClick(View v) {
if (mListener != null) {
mListener.add(v);
}
} private AddClickListener mListener; public void setListener(AddClickListener listener) {
mListener = listener;
} public interface AddClickListener {
void add(View v);
} public static class ViewH {
private ImageView img;
private TextView tv; public ViewH(View view) {
img = ((ImageView) view.findViewById(R.id.item_img));
tv = ((TextView) view.findViewById(R.id.item_text));
}
}
}

9.当中自己定义MoveImageView不过添加了一个set方法方便属性动画 update时调用。

public class MoveImageView extends ImageView {

    public MoveImageView(Context context) {
super(context);
} public void setMPointF(PointF pointF) {
setX(pointF.x);
setY(pointF.y);
}
}

10.重要的实如今Activity部分:

public class MainActivity extends AppCompatActivity implements ItemAdapter.AddClickListener, Animator.AnimatorListener {

    private ImageView shopImg;//购物车 IMG
private RelativeLayout container;//ListView 购物车View的父布局
private ListView itemLv; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViews();
initViews();
} private void initViews() {
ItemAdapter adapter = new ItemAdapter(this);
//当前Activity实现 adapter内部 点击的回调
adapter.setListener(this);
itemLv.setAdapter(adapter);
} /**
* ListView + 点击回调方法
*/
@Override
public void add(View addV) {
int[] childCoordinate = new int[2];
int[] parentCoordinate = new int[2];
int[] shopCoordinate = new int[2];
//1.分别获取被点击View、父布局、购物车在屏幕上的坐标xy。
addV.getLocationInWindow(childCoordinate);
container.getLocationInWindow(parentCoordinate);
shopImg.getLocationInWindow(shopCoordinate); //2.自己定义ImageView 继承ImageView
MoveImageView img = new MoveImageView(this);
img.setImageResource(R.mipmap.heart1);
//3.设置img在父布局中的坐标位置
img.setX(childCoordinate[0] - parentCoordinate[0]);
img.setY(childCoordinate[1] - parentCoordinate[1]);
//4.父布局加入该Img
container.addView(img); //5.利用 二次贝塞尔曲线 需首先计算出 MoveImageView的2个数据点和一个控制点
PointF startP = new PointF();
PointF endP = new PointF();
PointF controlP = new PointF();
//開始的数据点坐标就是 addV的坐标
startP.x = childCoordinate[0] - parentCoordinate[0];
startP.y = childCoordinate[1] - parentCoordinate[1];
//结束的数据点坐标就是 shopImg的坐标
endP.x = shopCoordinate[0] - parentCoordinate[0];
endP.y = shopCoordinate[1] - parentCoordinate[1];
//控制点坐标 x等于 购物车x;y等于 addV的y
controlP.x = endP.x;
controlP.y = startP.y; //启动属性动画
ObjectAnimator animator = ObjectAnimator.ofObject(img, "mPointF",
new PointFTypeEvaluator(controlP), startP, endP);
animator.setDuration(1000);
animator.addListener(this);
animator.start();
} @Override
public void onAnimationStart(Animator animation) {
} @Override
public void onAnimationEnd(Animator animation) {
//动画结束后 父布局移除 img
Object target = ((ObjectAnimator) animation).getTarget();
container.removeView((View) target);
//shopImg 開始一个放大动画
Animation scaleAnim = AnimationUtils.loadAnimation(this, R.anim.shop_scale);
shopImg.startAnimation(scaleAnim);
} @Override
public void onAnimationCancel(Animator animation) {
} @Override
public void onAnimationRepeat(Animator animation) {
} /**
* 自己定义估值器
*/
public class PointFTypeEvaluator implements TypeEvaluator<PointF> {
/**
* 每一个估值器相应一个属性动画。每一个属性动画仅相应唯一一个控制点
*/
PointF control;
/**
* 估值器返回值
*/
PointF mPointF = new PointF(); public PointFTypeEvaluator(PointF control) {
this.control = control;
} @Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
return getBezierPoint(startValue, endValue, control, fraction);
} /**
* 二次贝塞尔曲线公式
*
* @param start 開始的数据点
* @param end 结束的数据点
* @param control 控制点
* @param t float 0-1
* @return 不同t相应的PointF
*/
private PointF getBezierPoint(PointF start, PointF end, PointF control, float t) {
mPointF.x = (1 - t) * (1 - t) * start.x + 2 * t * (1 - t) * control.x + t * t * end.x;
mPointF.y = (1 - t) * (1 - t) * start.y + 2 * t * (1 - t) * control.y + t * t * end.y;
return mPointF;
}
} private void findViews() {
shopImg = (ImageView) findViewById(R.id.main_img);
container = (RelativeLayout) findViewById(R.id.main_container);
itemLv = (ListView) findViewById(R.id.main_lv);
}
}

11.购物车有一个Scale的补间动画:

<?xml version="1.0" encoding="utf-8"?

>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:repeatCount="1"
android:repeatMode="reverse">
<scale
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.2"
android:toYScale="1.2"/>
</set>

12.供參考~完~~

Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画的更多相关文章

  1. css贝塞尔曲线模仿饿了么购物车小球动画

    在线观看贝塞尔曲线值:传送门 在线观看动画效果:传送门 代码: <!DOCTYPE html> <html> <head> <meta charset=&qu ...

  2. canvas绘制二次贝塞尔曲线----演示二次贝塞尔四个参数的作用

    canvas中绘制二次贝塞尔曲线的方法为ctx.quadraticCurveTo(x1,y1,x2,y2); 四个参数分别为两个控制点的坐标.开始点即当前canvas中目前的点,如果想从指定的点开始, ...

  3. 基于canvas二次贝塞尔曲线绘制鲜花

    canvas中二次贝塞尔曲线参数说明: cp1x:控制点1横坐标 cp1y:控制点1纵坐标 x: 结束点1横坐标 y:结束点1纵坐标 cp2x:控制点2横坐标 cp2y:控制点2纵坐标 z:结束点2横 ...

  4. Bezier贝塞尔曲线的原理、二次贝塞尔曲线的实现

    Bezier曲线的原理 Bezier曲线是应用于二维图形的曲线.曲线由顶点和控制点组成,通过改变控制点坐标可以改变曲线的形状. 一次Bezier曲线公式: 一次Bezier曲线是由P0至P1的连续点, ...

  5. IOS贝塞尔曲线圆形进度条和加载动画

    做项目让做一个加载动画,一个圈圈在转中间加一个图片,网上有好多demo,这里我也自己写了一个,中间的图片可加可不加.其中主要用到贝塞尔曲线.UIBezierPath是对CGContextRef的进一步 ...

  6. canvas 绘制二次贝塞尔曲线

    代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...

  7. Android 自定义View高级特效,神奇的贝塞尔曲线

    效果图 效果图中我们实现了一个简单的随手指滑动的二阶贝塞尔曲线,还有一个复杂点的,穿越所有已知点的贝塞尔曲线.学会使用贝塞尔曲线后可以实现例如QQ红点滑动删除啦,360动态球啦,bulabulabul ...

  8. Android 贝塞尔曲线解析

    相信很多同学都知道"贝塞尔曲线"这个词,我们在很多地方都能经常看到.利用"贝塞尔曲线"可以做出很多好看的UI效果,本篇博客就让我们一起学习"贝塞尔曲线 ...

  9. 二次、三次贝塞尔曲线demo(演示+获取坐标点)

    二次贝塞尔曲线demo: See the Pen quadraticCurveDemo by hanyanjun (@hanyanjun) on CodePen. 我的demo地址(二次) 推荐点击以 ...

随机推荐

  1. JQuery中的事件(三)

    一:页面载入 ready(fn)当DOM载入就绪可以查询及操纵时绑定一个要执行的函数.这是事件模块中最重要的一个函数,因为它可以极大地提高web应用程序的响应速度.简单地说,这个方法纯粹是对向wind ...

  2. CSS - !important声明强制优先

    !important声明强制优先 CSS优先级中还有一个最无敌的声明,就是!important. 在CSS样式表中,带有!important声明的样式优先使用,它的优先级会超越任何地方.任何方式的样式 ...

  3. HDU 3980 (SG 环变成链 之前的先手变成后手)

    题意 两个人在一个由 n 个玻璃珠组成的一个圆环上玩涂色游戏,游戏的规则是: 1.每人一轮,每轮选择一个长度为 m 的连续的.没有涂过色的玻璃珠串涂色 2.不能涂色的那个人输掉游戏 Aekdycoin ...

  4. POJ 1328 Radar Installation【贪心】

    POJ 1328 题意: 将一条海岸线看成X轴,X轴上面是大海,海上有若干岛屿,给出雷达的覆盖半径和岛屿的位置,要求在海岸线上建雷达,在雷达能够覆盖全部岛屿情况下,求雷达的最少使用量. 分析: 贪心法 ...

  5. 基于thinkphp的RBAC权限控制

    RBAC  Role-Based Access Control 权限控制在后台管理中是十分常见的,它的模型大体上是下面这张图的形式 我用的字段和上面不一样,图只是个示例 一个简易的权限控制模型只需要3 ...

  6. 「BZOJ2882」工艺

    题解: 就是个最小表示法 大概做法就是扩大2倍原串 然后双指针比较,如果不相同了直接跳 原理随便画画就知道了

  7. Shell命令 中|| &&使用

    转自:https://www.cnblogs.com/aaronLinux/p/8340281.html

  8. POJ1006 Biorhythms【中国剩余定理】

    <题目链接> 题目大意: 人体的体力每23天会达到峰值,情感每28天会达到峰值,智力每33天会达到峰值,一个人在a天体力达到峰值,b天情感达到峰值,c天智力达到峰值,求这个人下一次体力情感 ...

  9. 001.网络TCP/IP工程知识点

    一 互联网概述 计算机网络定义:由自主计算机互连起来的集合体. 计算机网络两大部分:硬件:计算机.通信设备.接口设备和传输介质. 软件:通信协议和应用软件. 广域网拓扑结构通常有:网状拓扑结构和环形拓 ...

  10. 基于Vue.js的uni-app前端框架结合.net core开发跨平台project

    一.由来 最近由于业务需要要开发一套公益的APP项目,因此结合所给出的需求最终采用uni-app这种跨平台前端框架以及.netcore快速搭建我们的项目,并且能做到一套代码跨多个平台. 当然在前期技术 ...