Android特效专辑(八)——实现心型起泡飞舞的特效,让你的APP瞬间暖心


马上也要放年假了,家里估计会没网,更完这篇的话,可能要到年后了,不过在此期间会把更新内容都保存在本地,这样有网就可以发表了,也是极好的,今天说的这个特效,原本是Only上的一个小彩蛋的,我们来看看图片

只要我点击了Only这个字,下面就开始上升起起泡了,这个实现起来其实就是一个欲盖弥彰的动画而已,准备好三张颜色不一样的心型图片咯,这样的话,我们就开始动手来写一写吧!
首先新建一个工程——HeartFaom
准备工作就是准备图片咯

BezierEvaluator

单位转换以及计算轨迹
package com.lgl.heartfaom;import android.animation.TypeEvaluator;
import android.graphics.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;}@Overridepublic PointF evaluate(float time, PointF startValue, PointF endValue) {float timeLeft = 1.0f - time;PointF point = new PointF();// 结果point.x = timeLeft * timeLeft * timeLeft * (startValue.x) + 3* timeLeft * timeLeft * time * (pointF1.x) + 3 * timeLeft* time * time * (pointF2.x) + time * time * time * (endValue.x);point.y = timeLeft * timeLeft * timeLeft * (startValue.y) + 3* timeLeft * timeLeft * time * (pointF1.y) + 3 * timeLeft* time * time * (pointF2.y) + time * time * time * (endValue.y);return point;}
}

PeriscopeLayout

贝塞尔曲线的计算以及气泡的实现
package com.lgl.heartfaom;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.annotation.TargetApi;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;public class PeriscopeLayout extends RelativeLayout {private Interpolator line = new LinearInterpolator();// 线性private Interpolator acc = new AccelerateInterpolator();// 加速private Interpolator dce = new DecelerateInterpolator();// 减速private Interpolator accdec = new AccelerateDecelerateInterpolator();// 先加速后减速private Interpolator[] interpolators;private int mHeight;private int mWidth;private LayoutParams lp;private Drawable[] drawables;private Random random = new Random();private int dHeight;private int dWidth;public PeriscopeLayout(Context context) {super(context);init();}public PeriscopeLayout(Context context, AttributeSet attrs) {super(context, attrs);init();}public PeriscopeLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}@TargetApi(Build.VERSION_CODES.LOLLIPOP)public PeriscopeLayout(Context context, AttributeSet attrs,int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);init();}private void init() {// 初始化显示的图片drawables = new Drawable[3];Drawable red = getResources().getDrawable(R.drawable.pl_red);Drawable yellow = getResources().getDrawable(R.drawable.pl_yellow);Drawable blue = getResources().getDrawable(R.drawable.pl_blue);drawables[0] = red;drawables[1] = yellow;drawables[2] = blue;// 获取图的宽高 用于后面的计算// 注意 我这里3张图片的大小都是一样的,所以我只取了一个dHeight = red.getIntrinsicHeight();dWidth = red.getIntrinsicWidth();// 底部 并且 水平居中lp = new LayoutParams(dWidth, dHeight);lp.addRule(CENTER_HORIZONTAL, TRUE);// 这里的TRUE 要注意 不是truelp.addRule(ALIGN_PARENT_BOTTOM, TRUE);// 初始化插补器interpolators = new Interpolator[4];interpolators[0] = line;interpolators[1] = acc;interpolators[2] = dce;interpolators[3] = accdec;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = getMeasuredWidth();mHeight = getMeasuredHeight();}public void addHeart() {ImageView imageView = new ImageView(getContext());// 随机选一个imageView.setImageDrawable(drawables[random.nextInt(3)]);imageView.setLayoutParams(lp);addView(imageView);Animator set = getAnimator(imageView);set.addListener(new AnimEndListener(imageView));set.start();}private Animator getAnimator(View target) {AnimatorSet set = getEnterAnimtor(target);ValueAnimator bezierValueAnimator = getBezierValueAnimator(target);AnimatorSet finalSet = new AnimatorSet();finalSet.playSequentially(set);finalSet.playSequentially(set, bezierValueAnimator);finalSet.setInterpolator(interpolators[random.nextInt(4)]);finalSet.setTarget(target);return finalSet;}private AnimatorSet getEnterAnimtor(final View target) {ObjectAnimator alpha = ObjectAnimator.ofFloat(target, View.ALPHA, 0.2f,1f);ObjectAnimator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X,0.2f, 1f);ObjectAnimator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y,0.2f, 1f);AnimatorSet enter = new AnimatorSet();enter.setDuration(500);enter.setInterpolator(new LinearInterpolator());enter.playTogether(alpha, scaleX, scaleY);enter.setTarget(target);return enter;}private ValueAnimator getBezierValueAnimator(View target) {// 初始化一个贝塞尔计算器- - 传入BezierEvaluator evaluator = new BezierEvaluator(getPointF(2),getPointF(1));// 这里最好画个图 理解一下 传入了起点 和 终点ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) / 2, mHeight - dHeight),new PointF(random.nextInt(getWidth()), 0));animator.addUpdateListener(new BezierListenr(target));animator.setTarget(target);animator.setDuration(3000);return animator;}/*** 获取中间的两个 点** @param scale*/private PointF getPointF(int scale) {PointF pointF = new PointF();pointF.x = random.nextInt((mWidth - 100));// 减去100 是为了控制 x轴活动范围,看效果 随意~~// 再Y轴上 为了确保第二个点 在第一个点之上,我把Y分成了上下两半 这样动画效果好一些 也可以用其他方法pointF.y = random.nextInt((mHeight - 100)) / scale;return pointF;}private class BezierListenr implements ValueAnimator.AnimatorUpdateListener {private View target;public BezierListenr(View target) {this.target = target;}@Overridepublic void onAnimationUpdate(ValueAnimator animation) {// 这里获取到贝塞尔曲线计算出来的的x y值 赋值给view 这样就能让爱心随着曲线走啦PointF pointF = (PointF) animation.getAnimatedValue();target.setX(pointF.x);target.setY(pointF.y);// 这里顺便做一个alpha动画target.setAlpha(1 - animation.getAnimatedFraction());}}private class AnimEndListener extends AnimatorListenerAdapter {private View target;public AnimEndListener(View target) {this.target = target;}@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);// 因为不停的add 导致子view数量只增不减,所以在view动画结束后remove掉removeView((target));}}
}

activity_main.xml

布局的实现
<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:background="#000" ><Buttonandroid:id="@+id/btn_start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="飞舞吧!" /><com.lgl.heartfaom.PeriscopeLayoutandroid:id="@+id/periscope"android:layout_width="match_parent"android:layout_height="match_parent" ></com.lgl.heartfaom.PeriscopeLayout></RelativeLayout>

MainActivity

接着就是怎么去使用它了
package com.lgl.heartfaom;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;public class MainActivity extends Activity {private Button btn_start;// 心型气泡private PeriscopeLayout periscopeLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 初始化periscopeLayout = (PeriscopeLayout) findViewById(R.id.periscope);btn_start = (Button) findViewById(R.id.btn_start);btn_start.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// 调用添加泡泡的方法periscopeLayout.addHeart();}});}
}

好,我们接下来就可以运行一下试试实际上的效果了

觉得不错的点个赞哦!

Demo下载地址:http://download.csdn.net/detail/qq_26787115/9422603

Android特效专辑(八)——实现心型起泡飞舞的特效,让你的APP瞬间暖心相关推荐

  1. 助老打车暖心车站落地杭州 帮助老年人扫码一键叫车

    11月12日消息,杭州首批助老打车暖心车站在上城区闸弄口街道落成启用,社区老年人可以在暖心车站扫码一键叫车. 杭州助老打车暖心车站落成现场,中国人口福利基金会和高德地图共同发布了<老年人出行现状 ...

  2. Android特效专辑(十二)——仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View...

    Android特效专辑(十二)--仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术 ...

  3. Android特效专辑(十二)——仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View

    Android特效专辑(十二)--仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术 ...

  4. Android特效专辑(六)——仿QQ聊天撒花特效,无形装逼,最为致命

    Android特效专辑(六)--仿QQ聊天撒花特效,无形装逼,最为致命 我的关于特效的专辑已经在CSDN上申请了一个专栏--http://blog.csdn.net/column/details/li ...

  5. Android特效专辑(一)——水波纹过渡特效(首页)

    Android特效专辑(一)--水波纹过渡特效(首页) Android特效专辑(一)--水波纹过渡特效(首页) 也是今天看到的一个特效,感觉挺美丽的,近期也一直在筹划一个APP.就想把他当做APP的首 ...

  6. 使用jQuery实现点击页面时,出现心型特效,几秒后消失的效果案例

    首先呢,实现这个特效使用的技术是前端技术jQuery,实现代码只需几十行即可. 第一步创建一个demo.html文件,给body设置一个高度,这里如果body如果没有设置高度的话,不会看到效果. ht ...

  7. 推荐八款来自极客标签的超棒前端特效[第八期]

    为什么80%的码农都做不了架构师?>>>    日期:2013-6-24  来源:GBin1.com 本周,我们带来了极客社区推荐的10款前端特效,非常有趣的小游戏和页面生成.希望可 ...

  8. Android RecyclerView(八)设置自定义 下拉刷新 与 上拉加载数据

    Android RecyclerView(八)设置下拉刷新 与 上拉加载数据 GitHub 项目源码 CSDN 博客说明 智慧安卓App 文章分析 下拉刷新效果 上拉加载数据效果 1 xml布局文件中 ...

  9. Python+matplotlib绘制散点图模拟心型图案

    推荐教材: <Python数据分析.挖掘与可视化>(慕课版)(ISBN:978-7-115-52361-7),董付国,人民邮电出版社,定价49.8元,2020年1月出版,2021年3月第6 ...

最新文章

  1. JRE、JVM和JDK
  2. hibernate(七) hibernate中查询方式详解
  3. Nginx前端设置反向代理,后端Apache如何获取访客的真实IP,结合PHP。
  4. 这样的阅读工具,人手一个不过分吧?
  5. Android开发者必须深入学习的10个应用开源项目
  6. 三层架构:软件设计架构
  7. java 方法继承方法_Java继承和方法重写
  8. FFMPEG结构体分析之AVStream
  9. jquery刷新页面
  10. .NET 6新特性试用 | DateOnly和TimeOnly类型
  11. excel字符串反转
  12. java使用初始化输入参数_使用初始化参数配置java web应用程序
  13. 【Excel-2010】导入网站数据
  14. CCF NOI1066 素数对
  15. Asp.net 基础(二)
  16. 营业执照号码生成规则
  17. 微信小程序开发之——WebView
  18. 笔记本计算机无法上无线网络,告诉你解决笔记本电脑连不上无线网络
  19. 新手做搭建独立站需要准备什么
  20. 浏览器页面前端自适应方案

热门文章

  1. 百度地图、高德地图、腾讯地图比较
  2. 营销革命4.0 从传统到数字
  3. Open3D 曲面重建
  4. 自动复制吱口令html,js随机复制多吱口令代码
  5. 记一个npm安装问题 Refusing to delete xxx\.bin\xxx.cmd: is outside xxx\webpack and not a link
  6. 个人计算机有ip地址吗,如何查看ip? 查看个人电脑IP地址五大方法
  7. 电脑照片太大怎么压缩?如何调整照片kb?
  8. 风变python培训班学费一般多少
  9. 高数——定积分计算大法之换元法
  10. Oasys Analysis and Design of Concrete (ADC) v8.1 1CD