Android实现骨架屏占位加载效果(二)
这篇的内容是介绍Piccolo的思路以及主要实现过程。
实现思路
要实现骨架屏占位加载,要解决以下几个问题:
- 实现占位效果
- 标记显示位置
- 对列表的支持
实现占位效果
为了便于自定义占位效果,以及更低的内存消耗,选择比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实现骨架屏占位加载效果(二)相关推荐
- 【微信技术-微信小程序】------- 渐进式骨架屏(加载流)(第二篇)
提示:看如下内容需要了解第一篇:简单入门(骨架屏(加载流) 简单入门(第一篇)) 目录 一.什么是渐进式骨架屏? 二.实现渐进式骨架屏 三.效果展示 下载示例代码地址: 渐进式骨架屏示例代码-下载 一 ...
- android仿微博头像_Android 自定义 View 集锦|自定义圆形旋转进度条,仿微博头像加载效果...
微博 App 的用户头像有一个圆形旋转进度条的加载效果,看上去效果非常不错,如图所示: 据说 Instagram 也采用了这种效果.最近抽空研究了一下,最后实现的效果是这样: 基本上能模拟出个大概,代 ...
- android 百分比loading,牛逼的loading加载效果
牛逼的loading加载效果 介绍: AnimatedCircleLoadingView一个不错的loading加载效果,自定义AnimatedCircleLoadingView设置startDete ...
- android 仿快递步骤_Android实现仿美团、顺丰快递数据加载效果
我们都知道在Android中,常见的动画模式有两种:一种是帧动画(Frame Animation),一种是补间动画(Tween Animation).帧动画是提供了一种逐帧播放图片的动画方式,播放事先 ...
- Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果)...
Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果) 首句依然是那句老话,你懂得! finddreams :(http://blog.csdn.net/finddr ...
- android listview左右滑动动画效果,Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果...
本文实例讲述了Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果.分享给大家供大家参考,具体如下: 1. 滚动加载 listView.setOnScrollListener(n ...
- android progressdialog 背景色,怎么在android中利用ProgressDialog实现一个加载效果
怎么在android中利用ProgressDialog实现一个加载效果 发布时间:2020-12-07 17:00:07 来源:亿速云 阅读:77 作者:Leah 怎么在android中利用Progr ...
- android 自定义加载动画效果,Android自定义View实现loading动画加载效果
项目开发中对Loading的处理是比较常见的,安卓系统提供的不太美观,引入第三发又太麻烦,这时候自己定义View来实现这个效果,并且进行封装抽取给项目提供统一的loading样式是最好的解决方式了. ...
- android菊花动画,Android实现仿iOS菊花加载圈动画效果
常见的实现方式 切图,做旋转动画 自定义View,绘制效果 gif图 1.切图会增加体积,但相对简单,不过在换肤的场景下,会使用不同颜色,需要准备多张图,不够灵活. 2.由于自定义的好处,不同颜色只需 ...
最新文章
- 2022-2028年中国输配电设备全产业链投资分析及前景预测报告
- 分享Hadoop处理大数据工具及优势
- springboot HBase操作工具类
- devops开发运维一体化_进阶 | 中国电信系统集成公司:100% 应用 DevOps 理念,做好企业级行业应用...
- okhttp初识拦截器
- C++ 预编译头文件stdafx.h
- pytorch 神经网络构造
- ffmpeg实现摄像头拉流_ffmpeg推流拉流的几种方式
- Django入门,,适用小白
- matlab常用插值函数
- 中大计算机研究生华为,考上中山大学很厉害吗?毕业后有机会去华为吗?本文有答案...
- Mac自定义触控栏 Touch Bar的显示教程
- 尝试关闭阿里云ESC的阿里云盾相关服务
- 七自由度机械臂设计分析——待更新
- ios传值给js_深入剖析 iOS 与 JS 交互
- 谷歌浏览器F12抓包如何过滤只显示接口请求不显示图片、js那些请求
- Bluehost注册流程与问题
- 【转载】基于Office Online Server 2016 的office在线编辑
- opencv中使用摄像头录制视频
- IntelliJ IDEA 之 配置JDK 的 4种方式
热门文章
- CCRC信息安全服务资质六大方向申请条件----安全集成,安全运维 风险评估 应急处理 软件安全 灾难备份与恢复
- matlab上机操作作业指导书,[转载]烧毛工段作业指导书
- 倒相孔音箱和密闭音箱的知识介绍
- 服务器管理和信息安全责任书,网络与信息安全责任书.doc
- 基于stm32mp157 linux开发板ARM裸机开发教程4:Cortex-A7 内核存储系统与流水线(连载中)
- 实例浅谈Linux环境下搭建Web服务器与创建个人主页
- c语言链表动态分配内存,链表的C语言实现(含动态内存分配)
- 2009年民大美国全球大学预科中心第二届篮球赛
- 原神风行迷踪猎人角色玩法 分享猎人必胜秘技
- python爬取天气数据_用python爬取历史天气数据的方法示例