文档章节

实现Path2.0中绚丽的的旋转菜单

小克898
 小克898
发布于 2012/11/01 10:15
字数 1348
阅读 92
收藏 0
上图先:
画面.gif 

那么下面开始吧~首先,将整个菜单动画分解开来。
1. 一级菜单按钮的旋转动画2个,十字和叉叉状态的转换。
2. 二级菜单按钮的平移动画2个,弹簧效果的in和out
3. 二级菜单按钮的点击效果,放大消失,其他未点击按钮缩小消失。
4. 一级菜单按钮的恢复效果,放大出现
好的  逐一去实现:
首先是一级菜单按钮的旋转动画,这2 个动画可以直接在xml 中定义,然后load 到代码中来,具体代码如下:
rotate_story_add_button_in.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <rotate
  3.      xmlns:android="http://schemas.android.com/apk/res/android"
  4.           android:interpolator="@android :anim/linear_interpolator"
  5.           android:duration="150"
  6.           android:fromDegrees="0.0"
  7.           android:toDegrees="-225.0"
  8.           android:pivotX="50.0%"
  9.           android:pivotY="50.0%"
  10.           android:fillAfter="true"
  11.           android:fillEnabled="true"
  12.           />
复制代码
rotate_story_add_button_out.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <rotate
  3.      xmlns:android="http://schemas.android.com/apk/res/android"
  4.           android:interpolator="@android :anim/linear_interpolator"
  5.           android:duration="150"
  6.           android:fromDegrees="-225.0"
  7.           android:toDegrees="0.0"
  8.           android:pivotX="50.0%"
  9.           android:pivotY="50.0%"
  10.           android:fillAfter="true"
  11.           android:fillEnabled="true"
  12.            />
复制代码
2 段没什么好说的,定义好角度即可。
接下来是需要我们在代码中定义的动画部分,这几个动画的部分需要定义一个基类,作为统一的调用接口,这个基类被称作InOutAnimation, 继承自AnimationSet ,这个基类的主要工作是为view 提供in out 两种不同的状态时的动画效果。其子类需要实现2 个方法:

  1. protected abstract void addInAnimation(View aview[]);
  2. protected abstract void addOutAnimation(View aview[]);
复制代码
从而进行view 的入场和离场动画。 下面是InOutAnimation 的代码部分:


  1. public abstract class InOutAnimation extends AnimationSet {
  2.   
  3.           public Direction        direction;
  4.   
  5.           public enum Direction {
  6.                     IN, OUT;
  7.           }
  8.   
  9.           public InOutAnimation(Direction direction, long l, View[] aview) {
  10.                     super(true);
  11.                     this.direction = direction;
  12.                     switch (this.direction) {
  13.                     case IN:
  14.                              addInAnimation(aview);
  15.                              break;
  16.                     case OUT:
  17.                              addOutAnimation(aview);
  18.                              break;
  19.                     }
  20.                     setDuration(l);
  21.           }
  22.   
  23.           protected abstract void addInAnimation(View aview[]);
  24.           protected abstract void addOutAnimation(View aview[]);
  25.   
  26. }

复制代码
接下来就是重头戏啦,二级菜单按钮的平移动画。
这部分动画看起来可能会比较复杂和神秘,其实不然,当把整个动画过程分解开来的时候,都是最最简单的平移而已,我们要做的只是定义一下平移的起点和终点、开始动画的顺序以及插值(Interpolator),让整个过程看起来很炫。
先说动画的起点和终点吧,起点很简单,就是整个view的左下角,即0,0点,为了效果漂亮一些,我们稍微的将左下角位置定义的有一些偏移,经验上的值是16-13,这个点的位置看你心情而定咯 终点就是你想让他在的点上就好了,终点我们将定义到layout中去,为这个2级菜单指定一个margin的值就好。
还是上代码比较直观:
动画如下:


  1. 收缩部分:TranslateAnimation(xOffset + -mlp.leftMargin, 0F,yOffset + mlp.bottomMargin, 0F)
  2. 扩张部分:TranslateAnimation(0F, xOffset + -mlp.leftMargin, 0F,yOffset + mlp.bottomMargin)
复制代码
位置定义部分:
例如:
android:layout_marginBottom="142dp" android:layout_marginLeft="10.667dp"
这个位置大家可以直观的在布局文件中看到,详细的布局文件也将在下面展示。
以上是单独的每一个二级按钮的动画,而组合的动画就是指定了一下开始的时间差以及插值:
这个就是奥妙所在了,OvershootInterpolator AnticipateInterpolator  2 个插值器提供了弹力效果。
整段的代码如下:
ComposerButtonAnimation.java

  1. public class ComposerButtonAnimation extends InOutAnimation {
  2.   
  3.           public static final int                  DURATION       = 500;
  4.           private static final int       xOffset              = 16;
  5.           private static final int       yOffset              = -13;
  6.   
  7.           public ComposerButtonAnimation(Direction direction, long l, View view) {
  8.                     super(direction, l, new View[] { view });
  9.           }
  10.   
  11.           public static void startAnimations(ViewGroup viewgroup,
  12.                              InOutAnimation.Direction direction) {
  13.                     switch (direction) {
  14.                     case IN:
  15.                              startAnimationsIn(viewgroup);
  16.                              break;
  17.                     case OUT:
  18.                              startAnimationsOut(viewgroup);
  19.                              break;
  20.                     }
  21.           }
  22.   
  23.           private static void startAnimationsIn(ViewGroup viewgroup) {
  24.                     for (int i = 0; i < viewgroup.getChildCount(); i++) {
  25.                              if (viewgroup.getChildAt(i) instanceof InOutImageButton) {
  26.                                       InOutImageButton inoutimagebutton = (InOutImageButton) viewgroup
  27.                                                          .getChildAt(i);
  28.                                       ComposerButtonAnimation animation = new ComposerButtonAnimation(
  29.                                                          InOutAnimation.Direction.IN, DURATION, inoutimagebutton);
  30.                                       animation.setStartOffset((i * 100)
  31.                                                          / (-1 + viewgroup.getChildCount()));
  32.                                       animation.setInterpolator(new OvershootInterpolator(2F));
  33.                                       inoutimagebutton.startAnimation(animation);
  34.                              }
  35.                     }
  36.           }
  37.   
  38.           private static void startAnimationsOut(ViewGroup viewgroup) {
  39.                     for (int i = 0; i < viewgroup.getChildCount(); i++) {
  40.                              if (viewgroup.getChildAt(i) instanceof InOutImageButton) {
  41.                                       InOutImageButton inoutimagebutton = (InOutImageButton) viewgroup
  42.                                                          .getChildAt(i);
  43.                                       ComposerButtonAnimation animation = new ComposerButtonAnimation(
  44.                                                          InOutAnimation.Direction.OUT, DURATION,
  45.                                                          inoutimagebutton);
  46.                                       animation.setStartOffset((100 * ((-1 + viewgroup
  47.                                                          .getChildCount()) - i))
  48.                                                          / (-1 + viewgroup.getChildCount()));
  49.                                        animation.setInterpolator(new AnticipateInterpolator(2F));
  50.                                       inoutimagebutton.startAnimation(animation);
  51.                              }
  52.                     }
  53.           }
  54.   
  55.           @Override
  56.           protected void addInAnimation(View[] aview) {
  57.                     MarginLayoutParams mlp = (MarginLayoutParams) aview[0]
  58.                                       .getLayoutParams();
  59.                     addAnimation(new TranslateAnimation(xOffset + -mlp.leftMargin, 0F,
  60.                                       yOffset + mlp.bottomMargin, 0F));
  61.           }
  62.   
  63.           @Override
  64.           protected void addOutAnimation(View[] aview) {
  65.                     MarginLayoutParams mlp = (MarginLayoutParams) aview[0]
  66.                                       .getLayoutParams();
  67.                     addAnimation(new TranslateAnimation(0F, xOffset + -mlp.leftMargin, 0F,
  68.                                       yOffset + mlp.bottomMargin));
  69.           }
  70. }

复制代码
剩下的增大出现、增大消失及缩小消失都是scale alpha 的组合动画
例如增大出现为:


  1. addAnimation(new ScaleAnimation(0F, 1F, 0F, 1F, 1, 0.5F, 1, 0.5F));
  2. addAnimation(new AlphaAnimation(0F, 1F));
复制代码
整段的代码如下:

  1. public class ComposerButtonGrowAnimationIn extends InOutAnimation {
  2.   
  3.           public ComposerButtonGrowAnimationIn(int i) {
  4.                     super(InOutAnimation.Direction.IN, i, new View[0]);
  5.           }
  6.   
  7.           @Override
  8.           protected void addInAnimation(View[] aview) {
  9.                     addAnimation(new ScaleAnimation(0F, 1F, 0F, 1F, 1, 0.5F, 1, 0.5F));
  10.                     addAnimation(new AlphaAnimation(0F, 1F));
  11.   
  12.           }
  13.   
  14.           @Override
  15.           protected void addOutAnimation(View[] aview) {}
  16.   
  17. }
  18.   
  19. public class ComposerButtonGrowAnimationOut extends InOutAnimation {
  20.   
  21.           public ComposerButtonGrowAnimationOut(int i) {
  22.                     super(InOutAnimation.Direction.OUT, i, new View[0]);
  23.           }
  24.   
  25.           @Override
  26.           protected void addInAnimation(View[] aview) {}
  27.   
  28.           @Override
  29.           protected void addOutAnimation(View[] aview) {
  30.                     addAnimation(new ScaleAnimation(1F, 5F, 1F, 5F, 1, 0.5F, 1, 0.5F));
  31.                     addAnimation(new AlphaAnimation(1F, 0F));
  32.           }
  33.   
  34. } public class ComposerButtonShrinkAnimationOut extends InOutAnimation {
  35.   
  36.           public ComposerButtonShrinkAnimationOut(int i) {
  37.                     super(InOutAnimation.Direction.OUT, i, new View[0]);
  38.           }
  39.   
  40.           @Override
  41.           protected void addInAnimation(View[] aview) {
  42.   
  43.           }
  44.   
  45.           @Override
  46.           protected void addOutAnimation(View[] aview) {
  47.                     addAnimation(new ScaleAnimation(1F, 0F, 1F, 0F, 1, 0.5F, 1, 0.5F));
  48.                     addAnimation(new AlphaAnimation(1F, 0F));
  49.           }
  50.   
  51. }
复制代码
接下来我们需要为这些控件做一下扩展,以便其可以再动画完成后显示或消失。
很简单

  1. public class InOutImageButton extends ImageButton {
  2.   
  3.           private Animation    animation;
  4.   
  5.           public InOutImageButton(Context context, AttributeSet attrs, int defStyle) {
  6.                     super(context, attrs, defStyle);
  7.           }
  8.   
  9.           public InOutImageButton(Context context, AttributeSet attrs) {
  10.                     super(context, attrs);
  11.           }
  12.   
  13.           public InOutImageButton(Context context) {
  14.                     super(context);
  15.           }
  16.   
  17.           @Override
  18.           protected void onAnimationEnd() {
  19.                     super.onAnimationEnd();
  20.                     if ((this.animation instanceof InOutAnimation)) {
  21.                              setVisibility(((InOutAnimation) this.animation).direction != InOutAnimation.Direction.OUT ? View.VISIBLE
  22.                                                 : View.GONE);
  23.                     }
  24.           }
  25.   
  26.           @Override
  27.           protected void onAnimationStart() {
  28.                     super.onAnimationStart();
  29.                     if ((this.animation instanceof InOutAnimation))
  30.                              setVisibility(View.VISIBLE);
  31.           }
  32.   
  33.           @Override
  34.           public void startAnimation(Animation animation) {
  35.                     super.startAnimation(animation);
  36.                     this.animation = animation;
  37.                     getRootView().postInvalidate();
  38.           }
  39. }

© 著作权归作者所有

共有 人打赏支持
小克898
粉丝 37
博文 137
码字总数 132707
作品 0
朝阳
程序员
Android实现Path2.0中绚丽的的旋转菜单

最近真的是忙死了,做了很久的这个菜单动画特效,都没有时间写博客,今天在机场等飞机终于有了空闲时间。 上图先: 本人推荐学习技术资料百搜技术网:http://www.baisoujs.com/listandroid_an...

baisou
2013/07/27
0
0
给你的移动网站加点料:移动旋转菜单的实现方案

在github上看到有人用HTML5 + CSS3 + Javascript实现了jQuery Wheel Menu(旋转菜单),因为本人供职于移动网站的开发,又不是一个专业的前端开发,所以看到这么炫的东东肯定就垂涎三尺,想移...

幸福2胖纸
2013/08/31
0
0
Path去睡觉超炫特效

Path2.0 iOS应用中,用户有两种状态,分别是睡眠和唤醒状态。切换睡眠状态时,一个月亮会慢慢升起来,背景图案也会慢慢变化。唤醒之后,月亮慢慢消失。这份代码就是实现了这种超炫特效。需将...

匿名
2012/07/06
1K
0
Android卫星菜单:android-satellite-menu

android-satellite-menu实现点击主按钮,会弹出多个围绕着主按钮排列的子按钮,从而形成一个卫星弹出式菜单。子按钮弹出和消失的动画效果都很棒。这种弹出式菜单按钮应用在Path2.0中。 用法 ...

Remix_jx
2014/11/03
0
0
hi,大家好,我是pyui4win开源项目的发起者,欢迎大家关注该项目

pyui4win开源项目 目标:python做高效windows开发 20130721 增加编译为python扩展包,支持原生python调用 20130717 支持多线程运行 20130717 加入checkbox 20130617 新增饼图控件 20130613 新...

编码的风景
2013/07/21
0
6

没有更多内容

加载失败,请刷新页面

加载更多

[Hive]JsonSerde使用指南

注意: 重要的是每行必须是一个完整的JSON,一个JSON不能跨越多行,也就是说,serde不会对多行的Json有效。 因为这是由Hadoop处理文件的工作方式决定,文件必须是可拆分的,例如,Hadoop将在...

Mr_yul
10分钟前
0
0
54:mysql修改密码|连接mysql|mysql常用命令

1、mysql修改密码: root用户时mysql的超级管理员,默认mysql的密码是空的,直接可以连接上去的,不过这样不安全; 注释:为了方便的使用mysql,需要把mysql加入到环境变量里; #后续自己输入mys...

芬野de博客
17分钟前
0
0
鼠标单击复制粘贴标签中的内容

<span ref="spanContentOne" id="spanContentOne" style="font-size: 14px;">或许不是最亮眼,总比瞎买强一点</span><!--<input type="button" @click="copyClick('1')" value="复制" />-......

帝子兮
22分钟前
0
0
使用axel多线程疯狂下载

在Linux中比较常见见的下载工具是curl和wget,但是下载比较大的文件两者都不支持多线程, 断点续传的作用不见得能发挥到最大。今天介绍一个axel工具,开启多线程疯狂下载。 安装 Fedora/Cen...

linuxprobe16
24分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部