热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

Android中模仿抖音加载框之两颗小球转动效果

这篇文章主要介绍了Android仿抖音加载框之两颗小球转动控件,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

安卓版抖音v2.5加载框:

效果图如下所示:

抖音加载框

本控件效果图:

本控件

使用方法

源码地址:Android仿抖音加载框之两颗小球转动控件

1、xml引用:

 

2、java使用:

 @BindView(R.id.dy1)
 DYLoadingView dy1;
 @OnClick(R.id.b1)
 void start() {
 dy1.setXXXXX; //设置属性(可选)
 dy1.start(); //开始动画
 }
 @OnClick(R.id.b2)
 void stop() {
 dy1.stop(); //停止动画
 }

就酱。

可用属性

名称 对应xml属性 对应java方法 默认值
球1半径 radius1 setRadius() 6dp
球2半径 radius2 setRadius() 6dp
两球间隔 gap setRadius() 0.8dp
球1颜色 color1 setColors() 0XFFFF4040
球2颜色 color2 setColors() 0XFF00EEEE
叠加色 mixColor setColors() 0XFF000000
从右往左移动时小球最大缩放倍数 rtlScale setScales() 0.7f
从左往右移动时小球最大缩放倍数 ltrScale setScales() 1.3f
一次移动动画时长 duration setDuration() 350ms
一次移动动画后停顿时长 pauseDuration setDuration() 80ms
动画进度在[0,scaleStartFraction]期间,小球大小逐渐缩放 scaleStartFraction setStartEndFraction() 0.2f
动画进度在[scaleEndFraction,1]期间,小球大小逐渐恢复 scaleEndFraction setStartEndFraction() 0.8f

(rtl = right to left, ltr = left to right)

部分属性说明:

•color格式为32位ARGB
•scaleStartFraction范围[0,0.5];scaleEndFraction范围[0.5,1]
•假设ltrScale = 1.3,scaleStartFraction = 0.2,scaleEndFraction = 0.8;那么实际效果就是一颗小球从左边开始向右移动

期间,进度在0%~20%时半径逐渐从1倍放大到1.3倍,在20%~80%期间大小保持1.3倍,在80%~100%时半径逐渐从1.3倍恢复至1倍

实现思路

要让小球动,当然要有一个动画,通过动画来获得一个进度百分比fraction,然后小球在动画过程中的坐标、大小就可以通过这个值来计算:

   

 private void initAnim() {
 fraction = 0.0f;
 stop();
 anim = ValueAnimator.ofFloat(0.0f, 1.0f);
 anim.setDuration(duration);
 if (pauseDuration > 0) {
  anim.setStartDelay(pauseDuration);
  anim.setInterpolator(new AccelerateDecelerateInterpolator());
 } else {
  anim.setRepeatCount(ValueAnimator.INFINITE);
  anim.setRepeatMode(ValueAnimator.RESTART);
  anim.setInterpolator(new LinearInterpolator());
 }
 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
  public void onAnimationUpdate(ValueAnimator animation) {
  fraction = animation.getAnimatedFraction();
  invalidate();
  }
 });
 anim.addListener(new AnimatorListenerAdapter() {
  @Override
  public void onAnimationStart(Animator animation) {
  isLtr = !isLtr;
  }
  @Override
  public void onAnimationRepeat(Animator animation) {
  isLtr = !isLtr;
  }
  @Override
  public void onAnimationCancel(Animator animation) {
  isAnimCanceled = true;
  }
  @Override
  public void onAnimationEnd(Animator animation) {
  if (!isAnimCanceled) {
   anim.start();
  }
  }
 });
 }

代码中看到,如果小球一次移动后不需要停顿(pauseDuration = 0),那么直接通过anim.setRepeatCount(ValueAnimator.INFINITE)让动画无限循环,否则的话就要通过anim.setStartDelay(pauseDuration)来设置停顿时间,然后在监听的onAnimationEnd里重启动画,以此实现每一次移动后小球能停顿一定时间。在onAnimationUpdate里,我们记录了当前动画百分比fraction,然后通过invalidate()重绘,在之后的onDraw里将通过该值画出小球。另外,每次动画开始时(或是重复时),会将isLtr取反,这个标志位的作用是标明当前哪颗球在【从左往右】移动,因为两颗球的颜色、初始半径是不一样的嘛,onDraw里画小球时是需要这个标志位协助的。

有了动画进度fraction和标志位isLtr后,就可以在onDraw里画出小球了。

**首先要计算小球当前的坐标**。y坐标永远是固定的,不谈,x坐标随着`fraction`的变化而变化。两颗球之间最远距离为球1半径+球2半径+两球间隔,即`distance = gap + radius1 + radius2;`,这个值就是两颗球的移动范围,由此可计算出,当前【从左往右】移动的小球的x坐标和当前【从右往左】移动的小球x坐标分别为:

float ltrX = getMeasuredWidth() / 2.0f - distance / 2.0f;
ltrX = ltrX + (distance * fraction);
float rtlX = getMeasuredWidth() / 2.0f + distance / 2.0f;
rtlX = rtlX - (distance * fraction);

**接下来要计算小球当前的大小**。小球的大小也是随着动画进度变化的,上面已经说明了`scaleStartFraction`和`scaleEndFraction`属性的含义。 以当前小球【从左往右】移动为例,当动画进度为0时,小球大小为初始1倍大小;当动画进度到scaleStartFraction时,小球大小将缩放到`ltrScale`倍,当动画进度为[scaleStartFraction,scaleEndFraction]范围时,小球大小保持`ltrScale`倍,当动画进度到[scaleEndFraction,1]范围时,小球则从`ltrScale`倍逐渐恢复至1倍。 为了便于计算,首先将`[0,scaleStartFraction]`转换为`[0,1.0]`的真实百分比,根据`y = kx + b`(就这么个入门公式。。我都要在纸上算一遍T-T),可以得出:`float scaleFraction = 1.0f / scaleStartFraction * fraction; `,有了这个真实百分比,那么该区间里小球当前半径就好计算了:

ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction);
rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);

应该好懂的吧。另外[scaleEndFraction,1]区间里小球当前半径计算思路是一样的,不谈。

最后就是要画出小球。这里主要是如何画出实现两球叠加的部分的颜色。

 思路1:通过xfermode方式实现:

xfermode

从上图可以看出用Darken、Lighten、Screen模式可以做到让叠加处上色,但是颜色不能自定义。

 思路2:通过path的OP操作实现(API19):

op

(图片摘自http://www.gcssloop.com/customview/Path_Over)

 因此,可以先构造两个小球的Path,然后再将这两个Path进行INTERSECT操作,即可获得叠加处的Path,这样就可以做到自定义叠加处的颜色了。

onDraw完整代码:

@Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 float centerY = getMeasuredHeight() / 2.0f;
 float ltrInitRadius, rtlInitRadius;
 Paint ltrPaint, rtlPaint;
 //确定当前【从左往右】移动的是哪颗小球
 if (isLtr) {
  ltrInitRadius = radius1;
  rtlInitRadius = radius2;
  ltrPaint = paint1;
  rtlPaint = paint2;
 } else {
  ltrInitRadius = radius2;
  rtlInitRadius = radius1;
  ltrPaint = paint2;
  rtlPaint = paint1;
 }
 float ltrX = getMeasuredWidth() / 2.0f - distance / 2.0f;
 ltrX = ltrX + (distance * fraction);//当前从左往右的球的X坐标
 float rtlX = getMeasuredWidth() / 2.0f + distance / 2.0f;
 rtlX = rtlX - (distance * fraction);//当前从右往左的球的X坐标
 //计算小球移动过程中的大小变化
 float ltrBallRadius, rtlBallRadius;
 if (fraction <= scaleStartFraction) { //动画进度[0,scaleStartFraction]时,球大小由1倍逐渐缩放至ltrScale/rtlScale倍
  float scaleFraction = 1.0f / scaleStartFraction * fraction; //百分比转换 [0,scaleStartFraction]] -> [0,1]
  ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction);
  rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);
 } else if (fraction >= scaleEndFraction) { //动画进度[scaleEndFraction,1],球大小由ltrScale/rtlScale倍逐渐恢复至1倍
  float scaleFraction = (fraction - 1) / (scaleEndFraction - 1); //百分比转换,[scaleEndFraction,1] -> [1,0]
  ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction);
  rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);
 } else { //动画进度[scaleStartFraction,scaleEndFraction],球保持缩放后的大小
  ltrBallRadius = ltrInitRadius * ltrScale;
  rtlBallRadius = rtlInitRadius * rtlScale;
 }
 ltrPath.reset();
 ltrPath.addCircle(ltrX, centerY, ltrBallRadius, Path.Direction.CW);
 rtlPath.reset();
 rtlPath.addCircle(rtlX, centerY, rtlBallRadius, Path.Direction.CW);
 mixPath.op(ltrPath, rtlPath, Path.Op.INTERSECT);
 canvas.drawPath(ltrPath, ltrPaint);
 canvas.drawPath(rtlPath, rtlPaint);
 canvas.drawPath(mixPath, mixPaint);
 }

总结

以上所述是小编给大家介绍的Android中模仿抖音加载框之两颗小球转动控件效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


推荐阅读
  • Vue 2 中解决页面刷新和按钮跳转导致导航栏样式失效的问题
    本文介绍了如何通过配置路由的 meta 字段,确保 Vue 2 项目中的导航栏在页面刷新或内部按钮跳转时,始终保持正确的 active 样式。具体实现方法包括设置路由的 meta 属性,并在 HTML 模板中动态绑定类名。 ... [详细]
  • 本文探讨了如何通过最小生成树(MST)来计算严格次小生成树。在处理过程中,需特别注意所有边权重相等的情况,以避免错误。我们首先构建最小生成树,然后枚举每条非树边,检查其是否能形成更优的次小生成树。 ... [详细]
  • QUIC协议:快速UDP互联网连接
    QUIC(Quick UDP Internet Connections)是谷歌开发的一种旨在提高网络性能和安全性的传输层协议。它基于UDP,并结合了TLS级别的安全性,提供了更高效、更可靠的互联网通信方式。 ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • 2023 ARM嵌入式系统全国技术巡讲旨在分享ARM公司在半导体知识产权(IP)领域的最新进展。作为全球领先的IP提供商,ARM在嵌入式处理器市场占据主导地位,其产品广泛应用于90%以上的嵌入式设备中。此次巡讲将邀请来自ARM、飞思卡尔以及华清远见教育集团的行业专家,共同探讨当前嵌入式系统的前沿技术和应用。 ... [详细]
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 本文介绍了如何使用jQuery根据元素的类型(如复选框)和标签名(如段落)来获取DOM对象。这有助于更高效地操作网页中的特定元素。 ... [详细]
  • 如何在WPS Office for Mac中调整Word文档的文字排列方向
    本文将详细介绍如何使用最新版WPS Office for Mac调整Word文档中的文字排列方向。通过这些步骤,用户可以轻松更改文本的水平或垂直排列方式,以满足不同的排版需求。 ... [详细]
  • 理解存储器的层次结构有助于程序员优化程序性能,通过合理安排数据在不同层级的存储位置,提升CPU的数据访问速度。本文详细探讨了静态随机访问存储器(SRAM)和动态随机访问存储器(DRAM)的工作原理及其应用场景,并介绍了存储器模块中的数据存取过程及局部性原理。 ... [详细]
  • 几何画板展示电场线与等势面的交互关系
    几何画板是一款功能强大的物理教学软件,具备丰富的绘图和度量工具。它不仅能够模拟物理实验过程,还能通过定量分析揭示物理现象背后的规律,尤其适用于难以在实际实验中展示的内容。本文将介绍如何使用几何画板演示电场线与等势面之间的关系。 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • MySQL中枚举类型的所有可能值获取方法
    本文介绍了一种在MySQL数据库中查询枚举(ENUM)类型字段所有可能取值的方法,帮助开发者更好地理解和利用这一数据类型。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 本文介绍如何在应用程序中使用文本输入框创建密码输入框,并通过设置掩码来隐藏用户输入的内容。我们将详细解释代码实现,并提供专业的补充说明。 ... [详细]
author-avatar
黑白
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有