# 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()
}
~~~
- 介绍
- UI
- MaterialButton
- MaterialButtonToggleGroup
- 字体相关设置
- Material Design
- Toolbar
- 下拉刷新
- 可折叠式标题栏
- 悬浮按钮
- 滑动菜单DrawerLayout
- NavigationView
- 可交互提示
- CoordinatorLayout
- 卡片式布局
- 搜索框SearchView
- 自定义View
- 简单封装单选
- RecyclerView
- xml设置点击样式
- adb
- 连接真机
- 小技巧
- 通过字符串ID获取资源
- 自定义View组件
- 使用系统控件重新组合
- 旋转菜单
- 轮播图
- 下拉输入框
- 自定义VIew
- 图片组合的开关按钮
- 自定义ViewPager
- 联系人快速索引案例
- 使用ListView定义侧滑菜单
- 下拉粘黏效果
- 滑动冲突
- 滑动冲突之非同向冲突
- onMeasure
- 绘制字体
- 设置画笔Paint
- 贝赛尔曲线
- Invalidate和PostInvalidate
- super.onTouchEvent(event)?
- setShadowLayer与阴影效果
- Shader
- ImageView的scaleType属性
- 渐变
- LinearGradient
- 图像混合模式
- PorterDuffXfermode
- 橡皮擦效果
- Matrix
- 离屏绘制
- Canvas和图层
- Canvas简介
- Canvas中常用操作总结
- Shape
- 圆角属性
- Android常见动画
- Android动画简介
- View动画
- 自定义View动画
- View动画的特殊使用场景
- LayoutAnimation
- Activity的切换转场效果
- 属性动画
- 帧动画
- 属性动画监听
- 插值器和估值器
- 工具
- dp和px的转换
- 获取屏幕宽高
- JNI
- javah命令
- C和Java相互调用
- WebView
- Android Studio快捷键
- Bitmap和Drawable图像
- Bitmap简要介绍
- 图片缩放和裁剪效果
- 创建指定颜色的Bitmap图像
- Gradle本地仓库
- Gradle小技巧
- RxJava+Okhttp+Retrofit构建网络模块
- 服务器相关配置
- node环境配置
- 3D特效