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

最近真的是忙死了,做了很久的这个菜单动画特效,都没有时间写博客,今天在机场等飞机终于有了空闲时间。

上图先:

Android实现Path2.0中绚丽的的旋转菜单 - 1Android实现Path2.0中绚丽的的旋转菜单 - 2

那么下面开始吧~

首先,将整个菜单动画分解开来。

1. 一级菜单按钮的旋转动画2个,十字和叉叉状态的转换。

2. 二级菜单按钮的平移动画2个,弹簧效果的in和out。

3. 二级菜单按钮的点击效果,放大消失,其他未点击按钮缩小消失。

4. 一级菜单按钮的恢复效果,放大出现。

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个方法:

好的 逐一去实现:

首先是一级菜单按钮的旋转动画,这2个动画可以直接在xml中定义,然后load到代码中来,具体代码如下:

rotate_story_add_button_in.xml

1protected abstract void addInAnimation(View aview[]);
2protected abstract void addOutAnimation(View aview[]);

从而进行view的入场和离场动画。

下面是InOutAnimation的代码部分:

1public 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 
19                             break;
20                    }
21                    setDuration(l);
22          }
23 
24          protected abstract void addInAnimation(View aview[]);
25 
26          protected abstract void addOutAnimation(View aview[]);
27 
28}

接下来就是重头戏啦,二级菜单按钮的平移动画。

这部分动画看起来可能会比较复杂和神秘,其实不然,当把整个动画过程分解开来的时候,都是最最简单的平移而已,我们要做的只是定义一下平移的起点和终点、开始动画的顺序以及插值(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个插值器提供了弹力效果。

整段的代码如下:

1public 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的组合动画。

例如增大出现为:

ComposerButtonAnimation.java

1addAnimation(new ScaleAnimation(0F, 1F, 0F, 1F, 1, 0.5F, 1, 0.5F));
2addAnimation(new AlphaAnimation(0F, 1F));

1public 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 
19public 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}

接下来我们需要为这些控件做一下扩展,以便其可以再动画完成后显示或消失。

很简单:

1public 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}

那么到这里基本上就已经搞定了所有的事情了,剩下点没做的事就是把这些动画效果设置给对应的控件了,这里就不详细描述了。

源码下载:http://files.cnblogs.com/mudoot/PureComposerDemo.rar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值