前言

最近逛Dribbble的时候,看到了一个非常酷的Switcher动画,特别喜欢,本想着试着用代码在Android平台来实现一下,没想到已经有实现的版本,并且作者还写了文章分享,思路清晰,各个实现关键点都讲的特别清楚,因此就译诚中文,分享大家,正如作者最后所说,大家一定要运行试试,效果非常赞!

原作者:Alexander Kolpakov
译者:依然范特稀西
地址:http://suo.im/60UJjT

正文开始

最近,我写了一篇关于实现Dribbble上的一个漂亮设计的文章。得到了很多积极的反馈,对我来说,这给了我很大的动力。我非常高兴能获得这些反馈,同时我也很乐意分享我的经验。

在本文中,我们将尝试逐步实现由Oleg Frolov创建的另一个精美的动画。这与上一篇文章中的复杂动画UI无关,它是一个自定义小控件。但是它有着非常精美漂亮的动画设计,如下所示:

乍一看,实现这样的切换似乎并不简单,但我认为那是因为动画非常漂亮。如 你所见,创建相同的动画并不难。让我们一步一步地来实现它。

第一步,我们需要自定义View,并且实现它的3个构造方法:

class Switcher @JvmOverloads constructor(context: Context,attrs: AttributeSet ? = null,defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {init {attrs?.let { retrieveAttributes(attrs, defStyleAttr) }}private fun retrieveAttributes(attrs: AttributeSet, defStyleAttr: Int) {// retrieve cutom attributes}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {// setup switcher width and height}override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {// setup helper sizes every time switcher size changed (radius, icon width...)}override fun onDraw(canvas: Canvas ?) {// just draw}
}

接下来开始绘制

在默认(选中)状态下,我们的开关由2个圆角矩形(绿色和白色)组成

绘制它们非常简单,我们只需要计算白色矩形的位置并将偏移量iconTranslateX传递给Android KTX Canvas.withTranslation扩展即可:

override fun onDraw(canvas: Canvas ?) {// draw switcher (green rect)canvas?.drawRoundRect(switcherRect, switcherCornerRadius, switcherCornerRadius, switcherPaint)// draw icon (white rect)canvas?.withTranslation(x = iconTranslateX) {drawRoundRect(iconRect, switcherCornerRadius, switcherCornerRadius, iconPaint)}
}

开始分解动画

动画部分,我们使用ValueAnimator来实现,使用它的ofFloat(float... values)方法,我们需要三个动画:

  • 1、switcherAnimator: 切换器图标动画,从白色矩形到圆形,反之亦然

  • 2、translateAnimator: 为切换器图标从左到右的过渡设置动画,反之亦然;

  • 3、colorAnimator: 将颜色从绿色(选中)更改为红色,反之亦然。

让我们先看一下switcherAnimator动画,设置0为动画的开始值,1为动画的结束值。

// ...
var amplitude = BOUNCE_ANIM_AMPLITUDE_IN
var frequency = BOUNCE_ANIM_FREQUENCY_IN
var newProgress = 1fif (!checked) {amplitude = BOUNCE_ANIM_AMPLITUDE_OUTfrequency = BOUNCE_ANIM_FREQUENCY_OUTnewProgress = 0f
}val switcherAnimator = ValueAnimator.ofFloat(iconProgress, newProgress).apply {addUpdateListener {iconProgress = it.animatedValue as Float}interpolator = BounceInterpolator(amplitude, frequency)duration = SWITCHER_ANIMATION_DURATION
}
// ...

我们可以使用 Evgenii Neumerzhitckii 写的BounceInterpolator来实现反弹效果,这非常适合我们的动画场景,不了解的可以看一下这片文章:https://evgenii.com/blog/spring-button-animation-on-android/,它解释了BounceInterpolator是如何工作的。

在Android KTX addUpdateListener扩展中,我们更新了progress的值,然后触发invalidate方法,最后重新绘制了视图。

private var iconProgress = 0fset(value) {if (field != value) {field = valueval iconOffset = lerp(0f, iconRadius - iconCollapsedWidth / 2, value)iconRect.left = width - switcherCornerRadius - iconCollapsedWidth / 2 - iconOffseticonRect.right = width - switcherCornerRadius + iconCollapsedWidth / 2 + iconOffsetpostInvalidateOnAnimation()}}

lerp方法类似一个线性插值器,它用于计算iconOffset,反过来,它也用于计算Swicher图标的圆角矩形坐标。此图标的矩形从一个圆角矩形变为一个圆形(圆角半径较大的圆角矩形)。

我们使用了postInvalidateOnAnimation()代替postIvalidate,是因为我们需要平滑的动画,并且第一个方法有优势,详情请看:https://stackoverflow.com/questions/29219372/postinvalidateonanimation-vs-postinvalidate/42648958#42648958

translateAnimator的工作方式相同,但是会更新Swicher图标的x位置。

如你所见,我们的白色圆圈就像百吉饼。我们有2种制作方法:

  • 裁剪一个较小的圆圈
  • 最简单的圆圈,只需在顶部绘制另一个小圆圈,然后用切换器颜色填充即可。

我选择较简单的一种。

这一切,没什么难的!我们现在有一个漂亮的自定义小控件并且带有精美的动画!

至此,我们一切都可以了

现在,我们可以使用任何类型的动画来创建自定义视图,而且我们可以稍微更改代码以创建另一个由Oleg Frolov设计的Swicher小部件。仅需将视图轮廓从圆角矩形更新为圆形,并禁用平移动画。就是这么简单。

Talk is Chep,Just show Code

随意获取GitHub上的源代码,查看我的其他实现,别忘了尝试一下!
Github: https://github.com/bitvale/Switcher

以上就是全部内容,感谢你的阅读,最后,别忘了点赞和收藏!

如果你喜欢我的文章,就关注下我的公众号 Android技术杂货铺 、 简书 或者Github!
微信公众号:Android技术杂货铺

简书:https://www.jianshu.com/u/35167a70aa39

GitHub:https://github.com/pinguo-zhouwei

炫酷!从未见过如此Q弹的Switcher相关推荐

  1. android的底部弹出框炫酷的样式,Android自定义底部弹出框ButtomDialog

    本文实例为大家分享了Android自定义底部弹出框的具体代码,供大家参考,具体内容如下 先看看效果和你要的是否一样 一 .先来配置自定义控件需要的资源 1.在res文件夹下创建一个anim文件夹并创建 ...

  2. 【Qt炫酷动画】专栏导航目录

    历时小半年,经过总结积累,详细剖析了Qt框架如何制作动画. 通过本专栏学习,可以学会如何diy窗体动画.控件动画 Qt动画 [Qt炫酷动画]专栏导航目录 [Qt炫酷动画]0.动画类简介 [Qt炫酷动画 ...

  3. 作为一名程序猿应如何入手一款实用 + 炫酷的键盘(keychron)

    作为一名程序猿应如何入手一款实用 + 炫酷的键盘(keychron) 1. 个人使用感受 2. keychron 产品背景 3. 产品特点 有线&蓝牙 Keychron的Mac键盘布局 兼容所 ...

  4. macos 字体_巧用 iTerm2 zsh oh-my-zsh 打造炫酷的 MacOS 终端环境

    MacOS 系统自带的 Bash 虽然已经很强大,但是对于一些细节功能的支持并不完美,重点是对于一个颜控来说,原生 Bash 真的很丑--可塑性也不高.本文将使用 iTerm2 这款被各路大牛吹爆的 ...

  5. Python爬取热搜数据之炫酷可视化

    可视化展示 看完记得点个赞哟 炫酷可视化音乐组合版来了! 项目介绍 背景 现阶段.抖音.快手.哗哩哗哩.微信公众号已经成为不少年轻人必备的"生活神器".在21世纪的今天,你又是如何 ...

  6. Flutter自定义Widget实例 -如何创建炫酷粒子时钟效果!

    周末发表了一篇文章<这个项目也太屌了吧>,给大家推荐了一个炫酷的Flutter粒子时钟项目,不过没有将具体实现思路和代码,所幸,作者自己写了一篇博客将这个项目的背景.实现思路.和所遇到的问 ...

  7. Flutter自定义Widget之炫酷粒子时钟效果

    周末发表了一篇文章<这个项目也太屌了吧>,给大家推荐了一个炫酷的Flutter粒子时钟项目,不过没有将具体实现思路和代码,所幸,作者自己写了一篇博客将这个项目的背景.实现思路.和所遇到的问 ...

  8. IDEA的一些炫酷的插件

    最近项目比较忙,很久没有更新IDEA系列了,今天介绍一下IDEA的一些炫酷的插件,IDEA强大的插件库,不仅能给我们带来一些开发的便捷,还能体现我们的与众不同. 打开setting文件选择Plugin ...

  9. 好看又炫酷的网页特效例子收集

    1.鼠标点击系列 1.1鼠标点击弹出爱心 <!DOCTYPE html> <html lang="en"> <head><meta cha ...

最新文章

  1. RIA开发权威指南 基于JavaFX(赠品)
  2. pycharm更改为系统python3_今天配置好python3 装好了pycharm 就新建一个django一直改不好...
  3. GIS基础知识汇总篇(五)-无人机真正射影像的概念和制作原理
  4. php post修改字段,单个{customposttype}.php中的函数wp_insert_post()清除自定义字段
  5. matlab 高级函数
  6. 压测瓶颈在mysql_MySQL的性能基线收集及压力测试
  7. biee12c连接hive_BIEE 12c Linux下连接Hadoop Hive
  8. WinForm软件开机自动启动详细方法
  9. 【博客搬家】【转】matlab 6.5和7.0中simulink模型的兼容问题
  10. spirng 事物只支持 dml语句 update,insert delete
  11. HTML网上书店静态HTML网页作业作品 大学生三联书店网页设计制作成品 简单DIV CSS布局网站
  12. android studio更改代码字体,Android Studio怎么改变代码字体大小?
  13. java 代码走查_Java代码走查具体考察点
  14. 社区之星任玉刚:Android开发者的职场规划
  15. 微软模拟飞行10厦门航空涂装_《微软飞行模拟》或很快迎来技术公测
  16. python安装结巴_python jieba(结巴)小模块精讲
  17. CentOS7使用Yum安装k8s
  18. deeplearning.14深度学习猫咪识别阶段性检测记录
  19. 学习笔记 | 零基础平面设计入门
  20. python 重试—retry库的使用和自定义超时retry

热门文章

  1. 如何彻底的删除计算机多余的 CD驱动器盘符
  2. (加入显示电量功能)模仿魅族、华为、小米电池续航管理软件, 动态水波纹滚动的圆形小球View
  3. 【Python自动化测试】:模拟鼠标操作
  4. 071.魔王语言翻译
  5. 动态规划题目——背包
  6. go-pitaya学习笔记(9)-rate_limiting demo分析
  7. 制作手札---RPG是怎样做成的 (三)
  8. PHP+Mysql 实现最简单的注册登录
  9. 基于httpx和pyside2的哔哩哔哩(bilibili)-视频下载程序
  10. Extjs处理客户复制三位一撇到numberfield里面