这篇的内容是介绍Piccolo的思路以及主要实现过程。

实现思路

要实现骨架屏占位加载,要解决以下几个问题:

  1. 实现占位效果
  2. 标记显示位置
  3. 对列表的支持

实现占位效果

为了便于自定义占位效果,以及更低的内存消耗,选择比View更轻量级的Drawable实现占位效果。

Piccolo提供了两种加载效果ImageShiningDrawable和TextShiningDrawable,其主要实现都是基于ShiningDrawable。类图关系如下:

ShiningDrawable实现了Shining接口,Shining接口对外提供动画控制方法。如果自定义有动效的Drawable,那么只需要实现Shining接口框架便会正确处理。

ShiningDrawable主要是让shader(着色器)平移变换,每次变换重新绘制来实现动效:

public ShiningDrawable(Shape s) {super(s);mMatrix = new Matrix();ValueAnimator.AnimatorUpdateListener listener = animation -> {mMatrix.setTranslate((Integer) animation.getAnimatedValue(), 0);if (mShader != null) {mShader.setLocalMatrix(mMatrix);}invalidateSelf();};mAnimator = ValueAnimator.ofInt().setDuration(1000);mAnimator.setRepeatCount(ValueAnimator.INFINITE);mAnimator.setRepeatMode(ValueAnimator.RESTART);mAnimator.addUpdateListener(listener);setShape(new RectShape());
}

在bounds改变时设置平移范围:

protected void onBoundsChange(Rect bounds) {super.onBoundsChange(bounds);mAnimator.setIntValues(-bounds.width(), bounds.width());if (mStarted && mPendingAnimator) {mAnimator.start();mPendingAnimator = false;}
}

根据当前shader绘制显示内容:

@Override
protected void onDraw(Shape shape, Canvas canvas, Paint paint) {paint.setShader(mShader);getShape().draw(canvas, paint);
}

TextShinigDrawable基于ShiningDrawable实现文本多行显示效果,ImageShiningDrawable则是基于TextShiningDrawable实现的单行显示效果。

标记显示位置

用一个继承FrameLayout的子类PiccoloLayout将需要显示占位效果的View包裹起来。PiccoloLayout有两个作用,一个是标记需要显示占位效果的view,另一个是作为占位Drawable的容器。类图如下:

占位Drawable需要在最顶层显示,所以使用FrameLayout的前景属性实现:

public void setMaskDrawable(Drawable drawable) {mMaskDrawable = drawable;if (mShowing) {setForeground(mMaskDrawable);}
}

PiccoloLayout同时提供对实现Shining接口的Drawable的控制:

public void setShining(boolean shining) {if (mShining == shining) {return;}mShining = shining;if (mMaskDrawable instanceof Shining) {Shining drawable = ((Shining) mMaskDrawable);if (mShining && !drawable.isStarted()) {drawable.start();} else if (!mShining && drawable.isStarted()) {drawable.cancel();}}
}

显示骨架屏:

public void show() {if (mShowing) {return;}for (int i = 0; i < getChildCount(); i++) {getChildAt(i).setVisibility(View.INVISIBLE);}mShowing = true;if (mMaskDrawable instanceof Shining) {Shining drawable = ((Shining) mMaskDrawable);if (mShining && !drawable.isStarted()) {drawable.start();}}setForeground(mMaskDrawable);
}

隐藏骨架屏:

public void hide() {if (!mShowing) {return;}for (int i = 0; i < getChildCount(); i++) {getChildAt(i).setVisibility(View.VISIBLE);}mShowing = false;if (mMaskDrawable instanceof Shining) {Shining drawable = ((Shining) mMaskDrawable);if (mShining && drawable.isStarted()) {drawable.cancel();}}setForeground(null);
}

在显示占位效果时,拦截事件:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {if (mShowing) {return true;} else {return super.onInterceptTouchEvent(ev);}
}

对列表的支持

对RecyclerView这类通过Adapter生成View的情况,通过show和hide两种状态对Adapter进行替换的思路实现。框架提供ConductorForAdapter来方便应对这种情况。类图结构如下:

替换核心流程:

public void play(){if(mVisible){if (mView instanceof RecyclerView) {((RecyclerView) mView).setAdapter(new PiccoloAdapter1(mItems));} else if (mView instanceof ViewPager) {((ViewPager) mView).setAdapter(new PiccoloAdapter3(mItems));} else if (mView instanceof AbsListView) {((AbsListView) mView).setAdapter(new PiccoloAdapter2(mView.getContext(), mItems));} else {throw new UnsupportedViewException();}}else{if (mView instanceof RecyclerView) {((RecyclerView) mView).setAdapter(mRecyclerAdapter);} else if (mView instanceof ViewPager) {((ViewPager) mView).setAdapter(mPagerAdapter);} else if (mView instanceof AbsListView) {((AbsListView) mView).setAdapter(mListAdapter);} else {throw new UnsupportedViewException();}}
}

为了统一使用api,对于单个View使用的情况也提供ConductorForView类。不再赘述。

Android骨架屏占位加载效果(一)

github地址

piccolo

Communication

等你来Android泡泡群冒泡哦!

QQ: 905487701

Android实现骨架屏占位加载效果(二)相关推荐

  1. 【微信技术-微信小程序】------- 渐进式骨架屏(加载流)(第二篇)

    提示:看如下内容需要了解第一篇:简单入门(骨架屏(加载流) 简单入门(第一篇)) 目录 一.什么是渐进式骨架屏? 二.实现渐进式骨架屏 三.效果展示 下载示例代码地址: 渐进式骨架屏示例代码-下载 一 ...

  2. android仿微博头像_Android 自定义 View 集锦|自定义圆形旋转进度条,仿微博头像加载效果...

    微博 App 的用户头像有一个圆形旋转进度条的加载效果,看上去效果非常不错,如图所示: 据说 Instagram 也采用了这种效果.最近抽空研究了一下,最后实现的效果是这样: 基本上能模拟出个大概,代 ...

  3. android 百分比loading,牛逼的loading加载效果

    牛逼的loading加载效果 介绍: AnimatedCircleLoadingView一个不错的loading加载效果,自定义AnimatedCircleLoadingView设置startDete ...

  4. android 仿快递步骤_Android实现仿美团、顺丰快递数据加载效果

    我们都知道在Android中,常见的动画模式有两种:一种是帧动画(Frame Animation),一种是补间动画(Tween Animation).帧动画是提供了一种逐帧播放图片的动画方式,播放事先 ...

  5. Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果)...

    Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果) 首句依然是那句老话,你懂得! finddreams :(http://blog.csdn.net/finddr ...

  6. android listview左右滑动动画效果,Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果...

    本文实例讲述了Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果.分享给大家供大家参考,具体如下: 1. 滚动加载 listView.setOnScrollListener(n ...

  7. android progressdialog 背景色,怎么在android中利用ProgressDialog实现一个加载效果

    怎么在android中利用ProgressDialog实现一个加载效果 发布时间:2020-12-07 17:00:07 来源:亿速云 阅读:77 作者:Leah 怎么在android中利用Progr ...

  8. android 自定义加载动画效果,Android自定义View实现loading动画加载效果

    项目开发中对Loading的处理是比较常见的,安卓系统提供的不太美观,引入第三发又太麻烦,这时候自己定义View来实现这个效果,并且进行封装抽取给项目提供统一的loading样式是最好的解决方式了. ...

  9. android菊花动画,Android实现仿iOS菊花加载圈动画效果

    常见的实现方式 切图,做旋转动画 自定义View,绘制效果 gif图 1.切图会增加体积,但相对简单,不过在换肤的场景下,会使用不同颜色,需要准备多张图,不够灵活. 2.由于自定义的好处,不同颜色只需 ...

最新文章

  1. 2022-2028年中国输配电设备全产业链投资分析及前景预测报告
  2. 分享Hadoop处理大数据工具及优势
  3. springboot HBase操作工具类
  4. devops开发运维一体化_进阶 | 中国电信系统集成公司:100% 应用 DevOps 理念,做好企业级行业应用...
  5. okhttp初识拦截器
  6. C++ 预编译头文件stdafx.h
  7. pytorch 神经网络构造
  8. ffmpeg实现摄像头拉流_ffmpeg推流拉流的几种方式
  9. Django入门,,适用小白
  10. matlab常用插值函数
  11. 中大计算机研究生华为,考上中山大学很厉害吗?毕业后有机会去华为吗?本文有答案...
  12. Mac自定义触控栏 Touch Bar的显示教程
  13. 尝试关闭阿里云ESC的阿里云盾相关服务
  14. 七自由度机械臂设计分析——待更新
  15. ios传值给js_深入剖析 iOS 与 JS 交互
  16. 谷歌浏览器F12抓包如何过滤只显示接口请求不显示图片、js那些请求
  17. Bluehost注册流程与问题
  18. 【转载】基于Office Online Server 2016 的office在线编辑
  19. opencv中使用摄像头录制视频
  20. IntelliJ IDEA 之 配置JDK 的 4种方式

热门文章

  1. CCRC信息安全服务资质六大方向申请条件----安全集成,安全运维 风险评估 应急处理 软件安全 灾难备份与恢复
  2. matlab上机操作作业指导书,[转载]烧毛工段作业指导书
  3. 倒相孔音箱和密闭音箱的知识介绍
  4. 服务器管理和信息安全责任书,网络与信息安全责任书.doc
  5. 基于stm32mp157 linux开发板ARM裸机开发教程4:Cortex-A7 内核存储系统与流水线(连载中)
  6. 实例浅谈Linux环境下搭建Web服务器与创建个人主页
  7. c语言链表动态分配内存,链表的C语言实现(含动态内存分配)
  8. 2009年民大美国全球大学预科中心第二届篮球赛
  9. 原神风行迷踪猎人角色玩法 分享猎人必胜秘技
  10. python爬取天气数据_用python爬取历史天气数据的方法示例