🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 1. 效果 展开为: ![](https://img.kancloud.cn/90/f8/90f81a05f76d07c8e3e8b461018d4def_371x196.png) 然后点击后可以旋转消失: ![](https://img.kancloud.cn/cb/86/cb8640c76af2ceba8ef9679df779de87_368x200.png) # 2. 分析 至于显示的东西其实就是图片,也就是说利用事先`PS`好的图片,然后按照位置定位。组成也就是三个圆环加其余的图标。对应的视频教程:[尚硅谷Android视频教程《自定义控件》](https://www.bilibili.com/video/BV1qW411L7Cp?p=1)。当然,资源文件在评论区有给出: >尚硅谷Android学科全套教程 链接:https://pan.baidu.com/s/1EegFNEv6X2yqi6cJ9iStJQ 提取码:f6zp 也就是说这个案例的重点就在于`Android`动画中的旋转实现。 # 3. 实现 ## 3.1 View动画 我们可以直接使用`View`提供的`RotateAnimation`来做,比如: ~~~ override fun onClick(v: View?) { when(v?.id){ R.id.icon_home -> { if (isShowLevel2) { // 关闭第二级菜单 hideView(level2) if(isShowLevel3) { hideView(level3, 20) isShowLevel3 = false } } else { // 打开第二级菜单 showView(level2) } isShowLevel2 = !isShowLevel2 } R.id.icon_menu -> { if (isShowLevel3) { // 关闭第二级菜单 hideView(level3) } else { // 打开第二级菜单 showView(level3) } isShowLevel3 = !isShowLevel3 } } } fun showView(view: View){ showView(view, 0) } fun showView(view: View, delayTime: Int){ rotateView(view, 180, 360, delayTime) } fun hideView(view: View){ hideView(view, 0) } fun hideView(view: View, delayTime: Int){ rotateView(view, 0, 180, delayTime) } fun rotateView(view: View, fromDegrees: Int, toDegrees: Int, delayTime: Int){ val rotateAnimation = RotateAnimation(fromDegrees*1f, toDegrees*1f, view.width / 2f, view.height * 1f) rotateAnimation.duration = 500 rotateAnimation.fillAfter = true // 设置延迟多久播放 rotateAnimation.startOffset = delayTime.toLong() view.startAnimation(rotateAnimation) } ~~~ 但是,我们知道对于`View`动画的效果只是视图层的动画,对于`View`的属性没有任何变化,常见的也就是还是会在原位置响应点击事件。针对这个问题,我们需要做一些额外的处理。也就是让控件不可点击即可。比如我们可以设置: ~~~ fun rotateViewByRoateAnimation(view: ViewGroup, fromDegrees: Int, toDegrees: Int, delayTime: Int){ val rotateAnimation = RotateAnimation(fromDegrees*1f, toDegrees*1f, view.width / 2f, view.height * 1f) rotateAnimation.duration = 500 rotateAnimation.fillAfter = true // 设置延迟多久播放 rotateAnimation.startOffset = delayTime.toLong() view.startAnimation(rotateAnimation) // 所有元素不可点击或可点击 val children = view.children for (child in children) { child.isEnabled = (fromDegrees!=0) } } ~~~ ## 3.2 属性动画 前面提到了,使用`View`动画需要额外处理,而属性动画就不需要。它自`API 11`,即`Android 3.0`后,就在每次属性发生变化后,自动调用`inviladate`进行重新绘制。这里我们直接使用属性动画来解决。 ~~~ fun roateViewByAttrAnimator(view: ViewGroup, fromDegrees: Int, toDegrees: Int, delayTime: Int){ val animator = ObjectAnimator.ofFloat(view, "rotation", fromDegrees*1f, toDegrees*1f) animator.duration = 500 animator.startDelay = delayTime.toLong() // 设置旋转中心 view.pivotX = view.width / 2f view.pivotY = view.height * 1f animator.start() } ~~~