效果

知识点

位移动画 随机数 估值器(TypeEvaluator )使用

思路

1.在底部中心位置初始化图片
1.1用上透明度变化和scale变化的动画
2.计算二阶贝塞尔曲线
3.添加透明度变化动画,飘到顶部时颜色最淡
4.优化
4.1加一些随机的插值器
4.2动画结束时将添加的View删除

大部分代码

1 自定义Layout

class LikesLayout extends RelativeLayout {private static final String TAG = "LikesLayout";//星星的图片宽高private int mDrawableWidth = 0;private int mDrawableHeight = 0;// 用于产生随机数private final Random mRandom;// 存储图片资源idprivate final int[] mImageResId;//整个layout宽高private int mWidth;private int mHeight;private final Interpolator[] mInterpolator;public LikesLayout(Context context) {this(context, null);}public LikesLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public LikesLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mRandom = new Random();// 初始化资源idmImageResId = new int[]{R.drawable.star_blue, R.drawable.star_green, R.drawable.star_red, R.drawable.star_blue_bright, R.drawable.star_orange_light};Drawable drawable = ContextCompat.getDrawable(context, R.drawable.star_blue);//假设所有星星的大小相等(如果不等要分别计算)if (drawable != null) {mDrawableWidth = drawable.getIntrinsicWidth();mDrawableHeight = drawable.getIntrinsicHeight();}mInterpolator = new Interpolator[]{new AccelerateDecelerateInterpolator(), new AccelerateInterpolator(),new DecelerateInterpolator(), new LinearInterpolator()};}// 获取控件的宽高@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = MeasureSpec.getSize(widthMeasureSpec);mHeight = MeasureSpec.getSize(heightMeasureSpec);}public void addLikes() {for (int i = 0; i < 30; i++) {addLike();}}// 1.在底部中心位置初始化图片 用上透明度变化和scale变化的动画private void addLike() {// 添加一个ImageView在底部final ImageView likeIv = new ImageView(getContext());// 给一个图片资源(随机) 这里视频有点问题 比如 mRandom.nextInt(5);取值可能是是[0,5)的整数,视频里面写道 mRandom.nextInt(mImageRes.length - 1) 其实-1是不必要的int imageIndex = mRandom.nextInt(mImageResId.length);likeIv.setImageResource(mImageResId[imageIndex]);// 怎么添加到底部中心?利用RelativeLayout的LayoutParamsRelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);params.addRule(ALIGN_PARENT_BOTTOM);params.addRule(CENTER_HORIZONTAL);likeIv.setLayoutParams(params);addView(likeIv);AnimatorSet animator = getAnimator(likeIv);animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {// 4.2动画结束时将添加的View删除removeView(likeIv);}});animator.start();}private AnimatorSet getAnimator(ImageView likeIv) {// 入场动画 添加的效果:有放大和透明度变化 (属性动画)// 1.1用上透明度变化和scale变化的动画AnimatorSet innerAnimator = new AnimatorSet();ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(likeIv, "alpha", 0.3f, 1.0f);ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(likeIv, "scaleX", 0.3f, 1.0f);ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(likeIv, "scaleY", 0.3f, 1.0f);innerAnimator.playTogether(alphaAnimator, scaleXAnimator, scaleYAnimator);innerAnimator.setDuration(350);// 运行的路径动画  playSequentially 按循序执行AnimatorSet allAnimatorSet = new AnimatorSet();allAnimatorSet.playSequentially(innerAnimator, getBezierAnimator(likeIv));// 2.计算二阶贝塞尔曲线 本节难点return allAnimatorSet;}private Animator getBezierAnimator(ImageView likeIv) {//计算三阶贝塞尔曲线中的起点 控制点1 控制点2 终点//起始点在屏幕底部中间位置//控制点1取下半屏幕的随机点//控制点2取上半屏幕的随机点//起始点在屏幕顶部中间位置//所有动画计算的基准是图片的左上角PointF statPoint = new PointF(mWidth / 2 - mDrawableWidth / 2, mHeight - mDrawableHeight);PointF controlPoint1 = new PointF(mRandom.nextInt(mWidth) - mDrawableWidth, mRandom.nextInt(mHeight / 2) + mHeight / 2);PointF controlPoint2 = new PointF(mRandom.nextInt(mWidth) - mDrawableWidth, mRandom.nextInt(mHeight / 2));PointF endPoint = new PointF(mRandom.nextInt(mWidth - mDrawableWidth), 0);BezierTypeEvaluator evaluator = new BezierTypeEvaluator(controlPoint1, controlPoint2);ValueAnimator bezierAnimator = ObjectAnimator.ofObject(evaluator, statPoint, endPoint);// 4.1加一些随机的插值器bezierAnimator.setInterpolator(mInterpolator[mRandom.nextInt(mInterpolator.length)]);bezierAnimator.addUpdateListener(animation -> {PointF pointF = (PointF) animation.getAnimatedValue();likeIv.setX(pointF.x);likeIv.setY(pointF.y);// 3.添加透明度变化动画,飘到顶部时颜色最淡float t = animation.getAnimatedFraction();likeIv.setAlpha(1 - t);});bezierAnimator.setDuration(3000);return bezierAnimator;}
}

2 自定义估值器
这块如果不熟悉 可以先看一下上一篇博客 https://blog.csdn.net/u011109881/article/details/112549820
后记的最后一条,那里的估值器比较简单 是线性的,容易理解。

class BezierTypeEvaluator implements TypeEvaluator<PointF> {private final PointF mControlPoint1;private final PointF mControlPoint2;public BezierTypeEvaluator(PointF controlPoint1, PointF controlPoint2) {mControlPoint1 = controlPoint1;mControlPoint2 = controlPoint2;}/*** This function returns the result of linearly interpolating the start and end values, with* <code>fraction</code> representing the proportion between the start and end values. The* calculation is a simple parametric calculation:* 注意下面的这段描述 计算结果result = x0 + fraction * (x1 - x0)* 其中x0代表起始值 x1代表终点值 t代表比值* <code>result = x0 + fraction * (x1 - x0)</code>,* where <code>x0</code> is <code>startPoint</code>, <code>x1</code> is <code>endPoint</code>,* and <code>fraction</code> is <code>fraction</code>.** @param fraction   The fraction from the starting to the ending values*                   从起点到终点的比值* @param startPoint The start value.*                   起始点的值* @param endPoint   The end value.*                   终点的值* @return A linear interpolation between the start and end values, given the* <code>fraction</code> parameter.* 此函数的意义是计算某个比值fraction时 中间点的状态(位置) 其中fraction的区间为[0,1] 比如fraction也可以理解为百分比,为0.5表示一半的意思* <p>* <p>* 以上的解释为通用解释* 对于求三阶贝塞尔曲线的本方法而言* 该方法用于计算在特定 起点,终点,控制点1,控制点2时,fraction从0变化到1,返回的PointF连接起来将构成三阶贝塞尔曲线* 至于计算方法 直接套用百度百科的三阶贝塞尔曲线的公式即可 fraction即时百科中的t*/@Overridepublic PointF evaluate(float fraction, PointF startPoint, PointF endPoint) {PointF pointOnBezier = new PointF();pointOnBezier.x = (float) (Math.pow((1 - fraction), 3) * startPoint.x + 3 * mControlPoint1.x * fraction * Math.pow(1 - fraction, 2) + 3 * mControlPoint2.x * fraction * fraction * (1 - fraction) + endPoint.x * Math.pow(fraction, 3));pointOnBezier.y = (float) (Math.pow((1 - fraction), 3) * startPoint.y + 3 * mControlPoint1.y * fraction * Math.pow(1 - fraction, 2) + 3 * mControlPoint2.y * fraction * fraction * (1 - fraction) + endPoint.y * Math.pow(fraction, 3));return pointOnBezier;}
}

3 Activity

public class MainActivity extends AppCompatActivity {private LikesLayout mLikesLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mLikesLayout = findViewById(R.id.likeLayout);}public void like(View view) {mLikesLayout.addLikes();}
}

4 布局

<?xml version="1.0" encoding="utf-8"?>
<com.example.likesview.LikesLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/likeLayout"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:id="@+id/like"android:onClick="like"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="点赞!" /></com.example.likesview.LikesLayout>

5 星星的布局(红色为例 是使用Android studio创建的)

<vector android:height="48dp"android:tint="#FF0000"android:viewportHeight="24"android:viewportWidth="24"android:width="48dp"xmlns:android="http://schemas.android.com/apk/res/android"><pathandroid:fillColor="@android:color/white"android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z" />
</vector>

后记:

视频中的随机数有问题,图片我们只看到两种颜色 视频有点问题 比如 mRandom.nextInt(5);取值可能是是[0,5)的整数,视频里面写道 mRandom.nextInt(mImageRes.length - 1) 其实-1是不必要的,正因为视频-1了 所以还有一种颜色没有出现

红橙Darren视频笔记 点赞效果 动画练习相关推荐

  1. 红橙Darren视频笔记 圆点loadingView 动画ANR

    效果 思路 思路比较简单 先自定义view 该view只是一个圆,可以设置绘制的颜色.再自定义一个ViewGroup,在里面放三个之前自定义好的view.初始化的部分就完成了.下面接着看动画部分,动画 ...

  2. 红橙Darren视频笔记 仿QQ侧滑效果

    这一篇没有什么新的内容 就是改写 红橙Darren视频笔记 仿酷狗侧滑效果 的侧滑的效果 1.去掉淡入淡出效果 2.加上黑色模板效果 效果: 去掉淡入淡出效果很简单 就是注释掉onScrollChan ...

  3. 红橙Darren视频笔记 UML图简介

    整体架构复制自红橙原视频的课堂笔记 因为他这一课没有博客,所以没有转载链接,CSDN没有转载地址是无法作为转载类型的文章发表的,暂时标记为原创 参考链接 https://blog.csdn.net/r ...

  4. 红橙Darren视频笔记 代理模式 动态代理和静态代理

    红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...

  5. 红橙Darren视频笔记 类加载机制(API28) 自己写个热修复 查看源码网站

    第一部分 类加载机制 一个Activity是如何被Android虚拟机找到的? 在之前的文章 红橙Darren视频笔记 自定义View总集篇(https://blog.csdn.net/u011109 ...

  6. 红橙Darren视频笔记 利用阿里巴巴AndFix进行热修复

    注意 由于AndFix在2017年左右就停止更新了,在最新版本的apk上遇到很多问题,我最终也没有成功进行热修复.本节主要是学习热修复的原理 在上一篇 红橙Darren视频笔记 自己捕获异常并保存到本 ...

  7. 红橙Darren视频笔记 Behavior的工作原理源码分析

    主要coordinatorlayout的代码来自coordinatorlayout-1.0.0-sources.jar 本文从源码介绍 CoordinatorLayout 的 behavior 怎么工 ...

  8. 红橙Darren视频笔记 ViewGroup事件分发分析 基于API27

    本节目标,通过案例,先看程序运行结果,然后跟踪源码,理解为什么会有这样的输出,继而理解view group的分发机制,感觉和证明题很像呢. 考虑以下程序的运行结果: case1: public cla ...

  9. 红橙Darren视频笔记 CoordinatorLayout:实现自定义behavior

    效果: 目标:利用CoordinatorLayout实现自定义behavior ,顶部的TitleBar和底部的ActionBar实现能够随着手势自由显示和隐藏 activity中使用了recycle ...

最新文章

  1. 拒收苹果超10万元赏金!程序员小哥找出iCloud账户漏洞后,发文直指苹果不够公开透明...
  2. 使用log4jdbc记录SQL信息
  3. 为什么在EOS上的DApp对开发人员来说不盈利?
  4. 【MySQL】记录 Navicat连接 docker mysql 容器,备份docker mysql 注意事项
  5. java transaction cn,JAVA中如何用TRANSACTION来对数据库进行
  6. python杂记-RSA加解密实现(4)-加解密消息及文件
  7. boost::basic_string_ref相关的测试程序
  8. 程序员太牛了 公司年会整成代码讨论会
  9. 国内最缺的架构实践,DDD领域驱动设计排第一!
  10. 【Java数据结构与算法】第六章 算法的时间复杂度、算法的空间复杂度和排序算法的介绍
  11. 联发科推出5G处理器天玑720 采用台积电7nm工艺制造
  12. 非刚性人脸跟踪 —— 面部特征检测器
  13. 算法学习之路|方格分割
  14. 最新数据:微博Q1季度数据分析报告来了!
  15. 晶体二极管 三极管 MOS原理
  16. 用.NET开发MSN聊天机器人(转载)
  17. 从官方下载IAR方法
  18. java实现12306查票_java抓取12306信息实现火车余票查询示例
  19. python xlrd pandas_Python:Pandas pd.read_excel提供ImportError:为Excel supp安装xlrd = 0.9.0
  20. python处理can协议文件_二、如何解决:python:Can't reopen .pyc file

热门文章

  1. kafka怎么监听oracle,Rango_lhl:Spark+Kafka实时监控Oracle数据预警
  2. jQuery与JavaScript与ajax三者的区别与联系
  3. Arc076_E Connected?
  4. 资产模型数据初始化时应注意的事项
  5. 解决 Python2 和 Python3 的共存问题
  6. BFC的布局规则以及触发条件
  7. 权限管理系统之用户管理
  8. 关于oracle的物理dg,oracle物理DG管理-redo数据传输,应用与三种模式
  9. java中for的增强用法,Java中增强for循环的用法
  10. C语言课后习题(11)