种草Dribbble:从未见过如此Q弹的Switcher

77 篇文章 0 订阅
4 篇文章 0 订阅

前言

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

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

正文开始

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

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

swicher.gif

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

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

class Switcher @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet ? = null,
        defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    init {
        attrs?.let { retrieveAttributes(attrs, defStyleAttr) }
    }  

    privatefun retrieveAttributes(attrs: AttributeSet, defStyleAttr: Int) {
        // retrieve cutom attributes
    }
  
    overridefun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        // setup switcher width and height
    }

    overridefun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        // setup helper sizes every time switcher size changed (radius, icon width...)
    }

    overridefun onDraw(canvas: Canvas ?) {
        // just draw
    }
}

接下来开始绘制

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

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

overridefun 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 = 1f

if (!checked) {
    amplitude = BOUNCE_ANIM_AMPLITUDE_OUT
    frequency = BOUNCE_ANIM_FREQUENCY_OUT
    newProgress = 0f
}

val switcherAnimator = ValueAnimator.ofFloat(iconProgress, newProgress).apply {
    addUpdateListener {
        iconProgress = it.animatedValue asFloat
    }
    interpolator = BounceInterpolator(amplitude, frequency)
    duration = SWITCHER_ANIMATION_DURATION
}
// ...

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

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

privatevar iconProgress = 0f
  set(value) {
      if (field != value) {
          field = value

          val iconOffset = lerp(0f, iconRadius - iconCollapsedWidth / 2, value)
          iconRect.left = width - switcherCornerRadius - iconCollapsedWidth / 2 - iconOffset
          iconRect.right = width - switcherCornerRadius + iconCollapsedWidth / 2 + iconOffset

           postInvalidateOnAnimation()
      }
  }

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

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

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

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

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

我选择较简单的一种。

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

至此,我们一切都可以了

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

swicherX.gif

Talk is Chep,Just show Code

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dribbble是一个设计师社区,平面设计师,创意工作者等,都可以在上面分享他们的作品。作品既为Shot,作者为Player 资源有Eclipse版和Android studio 两个版本,studio版本要好点 Dribbble是感谢作者Github NovelanceF 精美的UI流 一,项目是在Android Studio上构建的,版本是0.4.3,不同于官网上的0.3.2,引入时请做好Gradle各种傲娇的心理准备。。。。。(当初LZ被折腾得要死) 二,各种项目已经作为源码导入,帮大家减少了很多劳动,一下说一下这个项目用到的开源项目可以学习到的有 1. Volley,一个精悍的网络框架 2. SwipeBackLayout,activity侧滑返回 3. PagerSlidingTabStrip, 一个精简的Tab框架 4. SwipeListview,侧滑listview,类似于ios里面微信的效果 5. 大名鼎鼎的SlidingMenu,主要用在Comments的展示 6. ImageViewEx,一个大型的加载网络图片的框架,效率没有NetWorkImageview高,但是可以加载网络Gif () 7. aFinal,一个数据库框架,用来处理本地收藏 8. ShareSDK,用来处理社交平台的分享,本项目只用到了Weibo和Twitter的分享,但是我保留了所有jar包 (项目中其他我没有提到的开源框架大都是上述框架的依赖库) 三,整个项目由作者一人设计并完成,难免会出各种bug,和崩溃,还请谅解。。(前些日子我被反应在有些手机上。。图片加载不出来,全是黑框框。。。我百思不得其解,至今仍未找到解决的方法,Sina的审核又说我的app打开有错误,他不给审核通过,但是Lz在本地测试正常的呀,正常的呀混蛋!!!!) 我把apilevel限制到了4.0以上,不过这个问题还是会存在,还请高手解答,草民感激不尽呐!!! 四,由于Sina的审核还没有过,所以大家暂时不能用SinaWeibo分享,还请谅解,但是Twitter是不用审核,是可以用的,可以分享图片,如果图片没有加载出来就点了分享。。可能会出一些奇怪的bug。 五,虽说上面列了这么多bug,,不过正常浏览是没什么问题的,lz还是学生,玻璃心,轻喷。 简单的说一下源码导入,从github下载以后,直接在android studio引入 Dribbb这个文件夹,android studio会自己build整个项目,过程中可能会下载所需的Gradle,android studio 0.4.3所对应的Gradle版本是1.10,不是这个gradle版本可能会无法build,gradle的网站好像是被墙的,总之gradle比较傲娇,不好调教,如果成功build起来了,恭喜你, Github地址,https://github.com/NovelanceF/Dribbble_rebuild 如果只是想看看设计,可以下载apk,https://github.com/NovelanceF/Dribbble_rebuild/tree/master/Dribbb/build/apk, app还在不断更新当中,当前完成度75%左右。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值