先来个效果图

这个动画效果主要几个关注点是:

一、自定义的RelativeLayout中动态加载ImageView

二、刚开始的三个还没移动的动画效果anpha和scaleX,scaleY ,用ObjectAnimator加载

三、红心移动效果,运用了ValueAnimator的TypeEvalutors(估值器) 和addUpdateListener监听,在TypeEvalutors获取了贝塞尔曲线运动时所随机移动的每一个PointF,

然后在监听中获取这个PointF,赋值给imageView的对象,这样就实现了imageView的对象不的x,y坐标不停的改变,实现移动效果

四、最后,在动画结束后remove(imageView)移除对象

详细代码:

先来个layout的xml

[java] view plaincopyprint?
  1. <RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  2. xmlns:tools=”http://schemas.android.com/tools”
  3. android:layout_width=”match_parent”
  4. android:layout_height=”match_parent”
  5. android:paddingBottom=”@dimen/activity_vertical_margin”
  6. android:paddingLeft=”@dimen/activity_horizontal_margin”
  7. android:paddingRight=”@dimen/activity_horizontal_margin”
  8. android:paddingTop=”@dimen/activity_vertical_margin”
  9. tools:context=”.MainActivity” >
  10. <Button
  11. android:id=”@+id/button1”
  12. android:layout_width=”wrap_content”
  13. android:layout_height=”wrap_content”
  14. android:layout_alignParentLeft=”true”
  15. android:layout_alignParentTop=”true”
  16. android:text=”开始”
  17. android:onClick=”startClick”/>
  18. <com.example.test_periscopedemo.MyLayout
  19. android:id=”@+id/myLayout”
  20. android:layout_width=”300dp”
  21. android:layout_height=”300dp”
  22. android:layout_below=”@id/button1”
  23. android:background=”@android:color/holo_green_light”
  24. />
  25. </RelativeLayout>

<RelativeLayout 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: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" ><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:text="开始" android:onClick="startClick"/><com.example.test_periscopedemo.MyLayout android:id="@+id/myLayout"android:layout_width="300dp"android:layout_height="300dp"android:layout_below="@id/button1"android:background="@android:color/holo_green_light"/></RelativeLayout>

主Activity:

[java] view plaincopyprint?
  1. package com.example.test_periscopedemo;
  2. import android.os.Bundle;
  3. import android.app.Activity;
  4. import android.view.Menu;
  5. import android.view.View;
  6. public class MainActivity extends Activity {
  7. MyLayout myLayout;
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_main);
  12. myLayout = (MyLayout) findViewById(R.id.myLayout);
  13. }
  14. public void startClick(View view){
  15. myLayout.addLayout();
  16. }
  17. }

package com.example.test_periscopedemo;import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;public class MainActivity extends Activity {MyLayout myLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myLayout = (MyLayout) findViewById(R.id.myLayout);}public void startClick(View view){myLayout.addLayout();}}

自定义的 RelativeLayout,这个主要的实现类

[java] view plaincopyprint?
  1. package com.example.test_periscopedemo;
  2. import java.util.Random;
  3. import android.animation.Animator;
  4. import android.animation.AnimatorListenerAdapter;
  5. import android.animation.AnimatorSet;
  6. import android.animation.ObjectAnimator;
  7. import android.animation.ValueAnimator;
  8. import android.animation.ValueAnimator.AnimatorUpdateListener;
  9. import android.content.Context;
  10. import android.graphics.BitmapFactory;
  11. import android.graphics.PointF;
  12. import android.graphics.drawable.Drawable;
  13. import android.util.AttributeSet;
  14. import android.view.View;
  15. import android.view.animation.AnimationSet;
  16. import android.widget.ImageView;
  17. import android.widget.RelativeLayout;
  18. public class MyLayout extends RelativeLayout{
  19. Random random;
  20. Drawable blue,red,yellow;
  21. LayoutParams lp;
  22. int dWidth,dHeight;
  23. int mWidth,mHeight;
  24. Drawable[] drawables = new Drawable[3];
  25. public MyLayout(Context context, AttributeSet attrs) {
  26. super(context, attrs);
  27. init();
  28. }
  29. @Override
  30. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  31. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  32. mWidth = getMeasuredWidth();
  33. mHeight = getMeasuredHeight();
  34. }
  35. private void init() {
  36. dWidth = BitmapFactory.decodeResource(getResources(), R.drawable.pl_blue).getWidth();
  37. dHeight = BitmapFactory.decodeResource(getResources(), R.drawable.pl_blue).getHeight();
  38. random = new Random();
  39. blue = getResources().getDrawable(R.drawable.pl_blue);
  40. red = getResources().getDrawable(R.drawable.pl_red);
  41. yellow = getResources().getDrawable(R.drawable.pl_yellow);
  42. drawables[0] = blue;
  43. drawables[1] = red;
  44. drawables[2] = yellow;
  45. lp = new LayoutParams(dWidth, dHeight);
  46. lp.addRule(CENTER_HORIZONTAL, TRUE); // 这里的TRUE 要注意 不是true
  47. lp.addRule(ALIGN_PARENT_BOTTOM, TRUE);
  48. }
  49. public void addLayout(){
  50. ImageView iv =new ImageView(getContext());
  51. iv.setLayoutParams(lp);
  52. addView(iv);
  53. iv.setImageDrawable(drawables[random.nextInt(3)]);
  54. getAnimator(iv);
  55. }
  56. private void getAnimator(final View iv){
  57. ValueAnimator va = ValueAnimator.ofObject(new BezierEvaluator(new PointF(mWidth/2-dWidth/2,mHeight-dHeight), getPointF()), new PointF(
  58. (mWidth - dWidth) / 2, mHeight - dHeight),
  59. new PointF(random.nextInt(getWidth()), 0));// 随机
  60. va.addUpdateListener(new AnimatorUpdateListener() {
  61. @Override
  62. public void onAnimationUpdate(ValueAnimator animation) {
  63. PointF pointF = (PointF) animation.getAnimatedValue();
  64. iv.setX(pointF.x);
  65. iv.setY(pointF.y);
  66. // 这里偷个懒,顺便做一个alpha动画,这样alpha渐变也完成啦
  67. iv.setAlpha(1 - animation.getAnimatedFraction());
  68. }
  69. });
  70. ObjectAnimator alpha = ObjectAnimator.ofFloat(iv, ”alpha”, 0.2f,1.0f);
  71. ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, ”scaleX”, 0.2f,1.0f);
  72. ObjectAnimator scaleY = ObjectAnimator.ofFloat(iv, ”scaleY”, 0.2f,1.0f);
  73. AnimatorSet set = new AnimatorSet();
  74. set.setDuration(3000);
  75. set.playTogether(alpha,scaleX,scaleY);
  76. set.play(va).after(alpha);
  77. set.setTarget(iv);
  78. set.addListener(new AnimatorListenerAdapter(){
  79. @Override
  80. public void onAnimationEnd(Animator animation) {
  81. super.onAnimationEnd(animation);
  82. System.out.println(”结束”);
  83. removeView(iv);
  84. }
  85. });
  86. set.start();
  87. }
  88. private PointF getPointF(){
  89. PointF p = new PointF();
  90. p.x = random.nextInt(mWidth);
  91. p.y = 50;
  92. return p;
  93. }
  94. }

package com.example.test_periscopedemo;import java.util.Random;import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AnimationSet;
import android.widget.ImageView;
import android.widget.RelativeLayout;public class MyLayout extends RelativeLayout{Random random;Drawable blue,red,yellow;LayoutParams lp;int dWidth,dHeight;int mWidth,mHeight;Drawable[] drawables = new Drawable[3];public MyLayout(Context context, AttributeSet attrs) {super(context, attrs);init();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = getMeasuredWidth();mHeight = getMeasuredHeight();}private void init() {dWidth = BitmapFactory.decodeResource(getResources(), R.drawable.pl_blue).getWidth();dHeight = BitmapFactory.decodeResource(getResources(), R.drawable.pl_blue).getHeight();random = new Random();blue = getResources().getDrawable(R.drawable.pl_blue);red = getResources().getDrawable(R.drawable.pl_red);yellow = getResources().getDrawable(R.drawable.pl_yellow);drawables[0] = blue;drawables[1] = red;drawables[2] = yellow;lp = new LayoutParams(dWidth, dHeight);lp.addRule(CENTER_HORIZONTAL, TRUE); // 这里的TRUE 要注意 不是truelp.addRule(ALIGN_PARENT_BOTTOM, TRUE);}public void addLayout(){ImageView iv =new ImageView(getContext());iv.setLayoutParams(lp);     addView(iv);        iv.setImageDrawable(drawables[random.nextInt(3)]);getAnimator(iv);}private void getAnimator(final View iv){    ValueAnimator va = ValueAnimator.ofObject(new BezierEvaluator(new PointF(mWidth/2-dWidth/2,mHeight-dHeight), getPointF()), new PointF((mWidth - dWidth) / 2, mHeight - dHeight),new PointF(random.nextInt(getWidth()), 0));// 随机        va.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {PointF pointF = (PointF) animation.getAnimatedValue();iv.setX(pointF.x);iv.setY(pointF.y);// 这里偷个懒,顺便做一个alpha动画,这样alpha渐变也完成啦iv.setAlpha(1 - animation.getAnimatedFraction());}});     ObjectAnimator alpha = ObjectAnimator.ofFloat(iv, "alpha", 0.2f,1.0f);      ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "scaleX", 0.2f,1.0f);ObjectAnimator scaleY = ObjectAnimator.ofFloat(iv, "scaleY", 0.2f,1.0f);AnimatorSet set = new AnimatorSet();set.setDuration(3000);set.playTogether(alpha,scaleX,scaleY);set.play(va).after(alpha);set.setTarget(iv);set.addListener(new AnimatorListenerAdapter(){@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);System.out.println("结束");removeView(iv);}});set.start();}private PointF getPointF(){PointF p = new PointF();p.x = random.nextInt(mWidth);p.y = 50;return p;}}

自定义的TypeEvaluator类,根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值,即在动画执行的不同的时间,返回不同的值,就在这利用贝塞尔曲线工式,获取一个随机移动的点的坐标做为返回值

[java] view plaincopyprint?
  1. package com.example.test_periscopedemo;
  2. import android.animation.TypeEvaluator;
  3. import android.graphics.PointF;
  4. //我们自定义一个BezierEvaluator 实现 TypeEvaluator
  5. //由于我们view的移动需要控制x y 所以就传入PointF 作为参数,是不是感觉完全契合??
  6. public class BezierEvaluator implements TypeEvaluator<PointF> {
  7. private PointF pointF1;//途径的两个点
  8. private PointF pointF2;
  9. public BezierEvaluator(PointF pointF1,PointF pointF2){
  10. this.pointF1 = pointF1;
  11. this.pointF2 = pointF2;
  12. System.out.println(”p1=”+pointF1);
  13. System.out.println(”p2=”+pointF2);
  14. }
  15. @Override
  16. public PointF evaluate(float time, PointF startValue,
  17. PointF endValue) {
  18. float timeLeft = 1.0f - time;
  19. PointF point = new PointF();//结果
  20. PointF point0 = (PointF)startValue;//起点
  21. PointF point3 = (PointF)endValue;//终点
  22. System.out.println(”time”+time);
  23. System.out.println(”p0=”+point0);
  24. System.out.println(”p3=”+point3);
  25. //代入公式
  26. point.x = timeLeft * timeLeft * timeLeft * (point0.x)
  27. + 3 * timeLeft * timeLeft * time * (pointF1.x)
  28. + 3 * timeLeft * time * time * (pointF2.x)
  29. + time * time * time * (point3.x);
  30. point.y = timeLeft * timeLeft * timeLeft * (point0.y)
  31. + 3 * timeLeft * timeLeft * time * (pointF1.y)
  32. + 3 * timeLeft * time * time * (pointF2.y)
  33. + time * time * time * (point3.y);
  34. return point;
  35. }
  36. }

package com.example.test_periscopedemo;import android.animation.TypeEvaluator;
import android.graphics.PointF;//我们自定义一个BezierEvaluator 实现 TypeEvaluator
//由于我们view的移动需要控制x y 所以就传入PointF 作为参数,是不是感觉完全契合??
public class BezierEvaluator implements TypeEvaluator<PointF> {private PointF pointF1;//途径的两个点 private PointF pointF2;public BezierEvaluator(PointF pointF1,PointF pointF2){this.pointF1 = pointF1;this.pointF2 = pointF2;System.out.println("p1="+pointF1);System.out.println("p2="+pointF2);}@Overridepublic PointF evaluate(float time, PointF startValue,PointF endValue) {float timeLeft = 1.0f - time;PointF point = new PointF();//结果PointF point0 = (PointF)startValue;//起点PointF point3 = (PointF)endValue;//终点System.out.println("time"+time);System.out.println("p0="+point0);System.out.println("p3="+point3);//代入公式 point.x = timeLeft * timeLeft * timeLeft * (point0.x)+ 3 * timeLeft * timeLeft * time * (pointF1.x)+ 3 * timeLeft * time * time * (pointF2.x)+ time * time * time * (point3.x);point.y = timeLeft * timeLeft * timeLeft * (point0.y)+ 3 * timeLeft * timeLeft * time * (pointF1.y)+ 3 * timeLeft * time * time * (pointF2.y)+ time * time * time * (point3.y);return point;}
}

全部完成

贝萨尔曲线实现Periscope心形点赞动画效果相关推荐

  1. html怎么显示一个点赞的心形,jquery心形点赞关注效果的简单实现

    html代码 css代码 .heart { width: 100px; height: 100px; background: url("") no-repeat; backgrou ...

  2. iOS 直播心形点赞动画

    iOS 直播心形点赞动画 https://github.com/KKKiller/KKHeartFlyAnimation

  3. [deviceone开发]-心形点赞动画示例

    一.简介 这个示例展示do_Animator组件的简单使用,通过点击"点赞"按钮,不断弹出心形图片,向上动画漂移到顶部消失.间隔时间和上下左右移动的步长都是一定范围的随机值. 二. ...

  4. 微信小程序心形点赞效果

    微信小程序心形点赞效果 前言 准备 实现 原理 布局 样式 逻辑实现 尾巴 前言 之前写过一篇文章微信小程序Canvas绘图API,简单介绍了下微信小程序(下面统称小程序)Canvas绘图相关API的 ...

  5. html+js画一颗心形,用SVG和Vanilla JS框架创建一个“星形变心形”的动画效果

    在我写的这篇文章中, 讲述了如何用Vanilla JavaScript使动画顺滑的从一种状态过渡到另一种.最好先看下那篇文章,因为在这篇文章中我们要用到一些那篇文章中讲过的内容.例如例子的演示.各种时 ...

  6. python绘制立体心形折纸图解_PS制作超漂亮的立体的心形折纸效果

    今天为大家分享PS制作超漂亮的立体的心形折纸效果方法,教程难度不是很大,制作出来的折纸效果非常漂亮,好了,一起来学习吧! 背景选择灰色的渐变底 如下 新建一个图层,可以使用其他的图案 或者 图形 但是 ...

  7. android炫酷动画代码,Android高级UI特效仿直播点赞动画效果

    Android高级UI特效仿直播点赞动画效果 发布时间:2020-10-02 16:06:18 来源:脚本之家 阅读:117 作者:mrr 本文给大家分享高级UI特效仿直播点赞效果-一个优美炫酷的点赞 ...

  8. 用SVG和Vanilla JS框架创建一个“星形变心形”的动画效果

    在我写的这篇文章中, 讲述了如何用Vanilla JavaScript使动画顺滑的从一种状态过渡到另一种.最好先看下那篇文章,因为在这篇文章中我们要用到一些那篇文章中讲过的内容.例如例子的演示.各种时 ...

  9. html5点赞按钮特效,jquery仿直播app按钮点赞动画效果

    特效描述:直播app按钮 按钮点赞动画 点赞动画效果.仿照直播软件制作的飘赞效果,jquery点赞动画效果. 代码结构 1. 引入JS 2. HTML代码 $(function () { $(&quo ...

最新文章

  1. C++ cin.ignore()用法
  2. UIScrollView用法
  3. 微服务架构下,静态数据通用缓存机制!
  4. iOS 深拷贝和浅拷贝
  5. 编写高质量的代码,改善c#程序的157个建议_之1~10
  6. php 实时更新内容_亿级视频内容如何实时更新?优酷视频背后的技术揭秘
  7. 三菱plcfx5u指令手册_从西门子200的PLC程序来看三菱FX5U的PLC程序
  8. mysql导入报编码错误问题解决
  9. docker container
  10. tomcat7 java_java开发环境配置(windows下JDK7+tomcat7)
  11. Opencv学习笔记(2)模块,图像读取、显示、叠加、融合、颜色分离、亮度、对比度
  12. 2022华为软挑成功退赛奖
  13. c语言数码管显示小数点,8位数码管显示正整数和小数及解决鬼影问题
  14. 我靠跨境电商5个月全款买房:那个你看不起的行业,未来十年最赚钱!
  15. EasyExcel代码层面设置写出的Excel样式、以及拦截器策略的使用、自动列宽设置、EasyExcel默认设置详解
  16. 店盈通带你看拼多多开店怎样让排名靠前?
  17. UC如被百度控股,手机qq浏览器改如何进攻和防守
  18. vim中Ctrl+t和Ctrl+o快捷键的区别
  19. UE4官网教程 风格化效果
  20. Python 的scikit-learn和tensorflow在虚拟环境下安装配置笔记

热门文章

  1. 课堂实验一 SQL基础练习
  2. 一款功能超级强大的AI驱动自动一键抠图软件,可一键扣人物商品衣服动物婚纱图章签名logo
  3. 编写程序,根据输入的n,输出如下例所示的图形。
  4. linux 软链接创建及拷贝
  5. 做了个后末日朋克风的梦
  6. 计算机锁屏打不开,电脑快捷锁屏不能用怎么办
  7. mybatis和mybatis-plus集成springboot的配置区别
  8. Authentication failed for 解决办法
  9. idea导入子工程module
  10. 虚幻四蓝图实战(下车减速人物加速蓝图接口通信)