参考链接
https://www.jianshu.com/p/e4de28b4d8ac
效果

一.动画分类介绍

帧动画 和 补间动画
帧动画:一张一张的图片不断轮巡播放
补间动画:位移,透明度,像缩放,改变的是View的属性(属性动画属于补间动画)

二.效果分析

2.1 加载显示组合控件(布局) 布局三个部分 = ShapeView + View(阴影背景 shape=“oval”) + TextView
2.2 编写自定view ShapeView
2.3 将布局加载到自定义ViewGroup LoadView中
2.3 分析实现动画
2.3.1第一部分 关于阴影:下落位移的时候配合中间阴影缩小,上抛的时候配合中间阴影放大
2.3.2第二部分 关于形状 1.下落动画+上抛动画 2.差值器,动画速率的问题,下落的时候如果是小球在真实生活中,下落的速度应该是越来越快,上抛的速度应该是越来越慢 3.下落的时候改变形状 4.旋转动画,正方形 180 圆形 三角120

三.性能优化

当后台数据返回的时候我们要把当前页面,设置成 gone (隐藏),只是用代码设置为了隐藏,但是动画View的内存还在跑,怎么办?
释放动画资源

四.部分实现代码

xml部分

<?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="match_parent"android:background="#fff"><com.example.custom58loadview.ShapeViewandroid:id="@+id/shape_view"android:layout_width="40dp"android:layout_height="40dp"android:layout_marginBottom="80dp"android:layout_above="@+id/image_shadow"android:layout_centerInParent="true" /><ImageViewandroid:id="@+id/image_shadow"android:layout_width="50dp"android:layout_height="4dp"android:layout_centerInParent="true"android:layout_margin="15dp"android:src="@drawable/shadow_view" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/image_shadow"android:layout_centerInParent="true"android:layout_marginTop="5dp"android:text="玩命加载中..." /></RelativeLayout><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><com.example.custom58loadview.CustomLoadViewandroid:id="@+id/load_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true" /></RelativeLayout>

Java部分

public class ShapeView extends View {@ShapeTypeprivate int mCurrentShape = ShapeType.CIRCLE;private Paint mCirclePaint, mTrianglePaint, mSquarePaint;private Path mPath;public ShapeView(Context context) {this(context, null);}public ShapeView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public ShapeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mCirclePaint = initPaintByColor(Color.RED);mTrianglePaint = initPaintByColor(Color.YELLOW);mSquarePaint = initPaintByColor(Color.GRAY);}private Paint initPaintByColor(int color) {Paint paint = new Paint();paint.setAntiAlias(true);paint.setDither(true);paint.setColor(color);return paint;}@Retention(RetentionPolicy.SOURCE)@IntDef({ShapeType.CIRCLE, ShapeType.SQUARE, ShapeType.TRIANGLE})public @interface ShapeType {int CIRCLE = 0;int SQUARE = 1;int TRIANGLE = 2;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(Math.min(width, height), Math.min(width, height));}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);switch (mCurrentShape) {case ShapeType.CIRCLE:// 画圆形int center = getWidth() / 2;canvas.drawCircle(center, center, center, mCirclePaint);break;case ShapeType.SQUARE:// 画正方形canvas.drawRect(0, 0, getWidth(), getHeight(), mSquarePaint);break;case ShapeType.TRIANGLE:// 画三角  Path 画路线if (mPath == null) {mPath = new Path();mPath.moveTo(getWidth() >> 1, 0);//勾股定理mPath.lineTo(0, (float) (Math.sqrt(3) * getWidth() / 2));mPath.lineTo(getWidth(), ((float) Math.sqrt(3) * getWidth() / 2));mPath.close();//直接连接到起点}canvas.drawPath(mPath, mTrianglePaint);break;}}public void exchange() {switch (mCurrentShape) {case ShapeType.CIRCLE:mCurrentShape = ShapeType.SQUARE;break;case ShapeType.SQUARE:mCurrentShape = ShapeType.TRIANGLE;break;case ShapeType.TRIANGLE:mCurrentShape = ShapeType.CIRCLE;break;}// 不断重新绘制形状invalidate();}public int getCurrentShape() {return mCurrentShape;}
}public class CustomLoadView extends RelativeLayout {private static final long ANIMATOR_DURATION = 1000;private ShapeView mShapeView;private ImageView mShadowView;private int mShapeTransactionY;//他的值为ShapeView的margin bottompublic CustomLoadView(Context context) {this(context, null);}public CustomLoadView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CustomLoadView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);inflate(context, R.layout.load_view, this);//上面的这句等价于下面的两句
//        LayoutInflater layoutInflater = LayoutInflater.from(context);
//        layoutInflater.inflate(R.layout.load_view,this,true);//初始化各个部件 用于后期动画mShapeView = findViewById(R.id.shape_view);mShadowView = findViewById(R.id.image_shadow);mShapeTransactionY = ((MarginLayoutParams) mShapeView.getLayoutParams()).bottomMargin;post(new Runnable() {@Overridepublic void run() {// onResume 之后View绘制流程执行完毕之后(View的绘制流程源码分析那一章)startFullDownAnimate();}});// onCreate() 方法中执行 ,布局文件解析 反射创建实例}//和下落动画相反private void startJumpUpAnimate() {//关于形状的动画// 1.下落动画+上抛动画// 这里是弹起// Y值越大 越在下方ObjectAnimator shapeTransactionAnimate = ObjectAnimator.ofFloat(mShapeView, "translationY", mShapeTransactionY, 0);// 2.差值器,动画速率的问题,下落的时候如果是小球在真实生活中,下落的速度应该是越来越快,上抛的速度应该是越来越慢// 这里是下落DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();// 3.下落的时候改变形状// mShapeView.exchange();// 4.旋转动画,正方形 180 圆形 三角120float rotationValue = -180;switch (mShapeView.getCurrentShape()) {case ShapeView.ShapeType.SQUARE:rotationValue = -180;break;case ShapeView.ShapeType.TRIANGLE:rotationValue = -120;break;}ObjectAnimator shapeRotateAnimate = ObjectAnimator.ofFloat(mShapeView, "rotation", rotationValue);ObjectAnimator shadowScaleAnimate = ObjectAnimator.ofFloat(mShadowView, "scaleX", 0.3f, 1);//从0.3增加到原有宽度AnimatorSet animatorSet = new AnimatorSet();animatorSet.setDuration(ANIMATOR_DURATION);animatorSet.setInterpolator(decelerateInterpolator);animatorSet.playTogether(shapeTransactionAnimate, shapeRotateAnimate, shadowScaleAnimate);animatorSet.start();//当动画下落完之后就下落了animatorSet.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {// 下落完之后就上抛了startFullDownAnimate();}});}private void startFullDownAnimate() {// 关于阴影的动画 下落位移的时候配合中间阴影缩小,上抛的时候配合中间阴影放大//mShadowView.setScaleX(); //里面的参数的定义可以拿出来直接作为ObjectAnimator.ofFloat的第二个参数 表示动画的类型//关于形状的动画// 1.下落动画+上抛动画// 这里是从高处落下 // Y值越大 越在下方ObjectAnimator shapeTransactionAnimate = ObjectAnimator.ofFloat(mShapeView, "translationY", 0, mShapeTransactionY);// 2.差值器,动画速率的问题,下落的时候如果是小球在真实生活中,下落的速度应该是越来越快,上抛的速度应该是越来越慢// 这里是下落AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();// 3.下落的时候改变形状mShapeView.exchange();// 4.旋转动画,正方形 180 圆形 三角120float rotationValue = 0;switch (mShapeView.getCurrentShape()) {case ShapeView.ShapeType.SQUARE:rotationValue = 180;break;case ShapeView.ShapeType.TRIANGLE:rotationValue = 120;break;}ObjectAnimator shapeRotateAnimate = ObjectAnimator.ofFloat(mShapeView, "rotation", rotationValue);ObjectAnimator shadowScaleAnimate = ObjectAnimator.ofFloat(mShadowView, "scaleX", 1, 0.3f);//从原有宽度缩短到0.3AnimatorSet animatorSet = new AnimatorSet();animatorSet.setDuration(ANIMATOR_DURATION);animatorSet.setInterpolator(accelerateInterpolator);animatorSet.playTogether(shapeTransactionAnimate, shapeRotateAnimate, shadowScaleAnimate);// 先执行 translationAnimator 接着执行 scaleAnimator// animatorSet.playSequentially(translationAnimator,scaleAnimator);animatorSet.start();//当动画下落完之后就上抛了animatorSet.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {// 下落完之后就上抛了startJumpUpAnimate();}});}//加载完毕调用 释放动画资源public void loadComplete() {mShapeView.clearAnimation();mShadowView.clearAnimation();// 把LoadingView从父布局移除ViewGroup parent = (ViewGroup) getParent();if (parent != null) {parent.removeView(this);// 从父布局移除removeAllViews();// 移除自己所有的View}}
}

代码
https://github.com/caihuijian/learn_darren_android.git

红橙Darren视频笔记 动画讲解 仿58同城 加载动画相关推荐

  1. android 仿 动画,Android动画 - 仿58同城加载动画

    Android动画 - 仿58同城加载动画 效果图 58LoadingView.gif 分析动画 首先分析动画,如上图所示: 动画分为三部分,分别为上方跳动部分,中间阴影部分,和下方文字部分. 上方跳 ...

  2. 红橙Darren视频笔记setContentView源码分析 xml加载的过程

    setContentView过程分析 从继承Activity的类开始进行分析 MainActivity setContentView(R.layout.activity_main); Activity ...

  3. android 今日头条加载动画,高仿今日头条加载动画

    01 每每浏览手机app时,发现有的效果体验不错,作为一位程序员,总想要是自己来做,怎么实现. 今天我们来模仿今日头条的加载动画. 首先我们来看一下我们这个demo最终效果,有图有真相. 高仿今日头条 ...

  4. 学习自定义View(二)仿58同城加载

    之前用58同城app的时候看到它的加载界面不错,但是那时候还不知道如何实现~接触自定义View后,于是自己试着模仿写了一个 先看效果图: 录制的GIF上有一点卡,其实在真机上面运行很流畅的~ 其实感觉 ...

  5. 红橙Darren视频笔记 界面优化与屏幕适配(上)

    1. 内存泄漏,内存溢出与内存抖动 内存泄漏:GC在内存吃紧去回收内存的时候,无法回收某一块不再使用的内存.随着时间的推移会导致内存溢出,一般是强引用导致 之前有总结过内存泄漏的一些case和解决方案 ...

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

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

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

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

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

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

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

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

最新文章

  1. 华人斩获最佳Demo论文,Bengio获时间检验奖,最佳论文突破NLP传统测试方法 | ACL 2020...
  2. 前端新手学习记录2 -使用vscode编写个人网站首页
  3. Jenkins持续集成环境之插件管理和角色管理
  4. 基于visual Studio2013解决C语言竞赛题之0304整除数
  5. celery-02-安装与使用说明-for-redis
  6. 法定节假日违规组织培训,51talk被通报批评整改不到位
  7. 用DotNetOpenAuth实现基于OAuth 2.0的web api授权 (一)Getting Start
  8. LeetCode 70.爬楼梯(动态规划)
  9. UVA583 UVALive5406 Prime Factors【素数因子+筛选法】
  10. 视频教程-轻松搞定Spring全家桶(初识篇)-Java
  11. Origin 2022b | 更新及安装 | 中英文切换
  12. BMVC 2020 Keynote 消除数据集偏见
  13. 30本引进翻译版日本计算机技术书籍推荐
  14. 看完这一篇,智能家居的坑你至少避开80%(上)
  15. html文档字符间距怎么设置,Pages字符间距怎么设置 Pages字符间距设置教程
  16. win10家庭版系统 修改docker为国内镜像
  17. 华为计算机黑屏怎么办,华为电脑开机屏幕没反应(开机黑屏的3个原因及解决法)...
  18. 怎么用pdf压缩软件简单实现pdf压缩
  19. 第十三课 斗地主项目课③游戏音乐与音效及本地存储
  20. ei eo 功能类型_[转载]CMMI之功能点估算法:EI、EQ和EO

热门文章

  1. java 最少使用(lru)置换算法_「Redis源码分析」Redis中的LRU算法实现
  2. move语句java_java自动化代码优化
  3. SQLServer2008 查询分析器内容未保存,查找分析器内容
  4. vue开发 - 将方法绑定到window对象,给app端调用
  5. Dockder的CS模式:
  6. Linux基础操作-分区概念
  7. 最短路径之Dijkstra算法
  8. 凯撒密码和栅栏密码 - 密码学01
  9. 32位linux进程线程在内存中的样子
  10. RTT内核对象——对象理解