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

来源:互联网 发布:卖家如何淘宝客推广 编辑:程序博客网 时间:2024/05/20 23:33

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

上图先:

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

那么下面开始吧~

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

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

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

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

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

View Row Code
1<?xml version="1.0" encoding="UTF-8"?>2<rotate3     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

View Row Code
1<?xml version="1.0" encoding="UTF-8"?>2<rotate3     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

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

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

下面是InOutAnimation的代码部分:

View Row Code
1public abstract class InOutAnimationextends AnimationSet {2  3          publicDirection        direction;4  5          publicenum Direction {6                    IN,OUT;7          }8  9          publicInOutAnimation(Direction direction,long l, View[] aview) {10                    super(true);11                    this.direction = direction;12                    switch (this.direction) {13                    caseIN:14                             addInAnimation(aview);15                             break;16                    caseOUT:17                             addOutAnimation(aview);18  19                             break;20                    }21                    setDuration(l);22          }23  24          protectedabstract void addInAnimation(View aview[]);25  26          protectedabstract void addOutAnimation(View aview[]);27  28}

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

这部分动画看起来可能会比较复杂和神秘,其实不然,当把整个动画过程分解开来的时候,都是最最简单的平移而已,我们要做的只是定义一下平移的起点和终点、开始动画的顺序以及插值(Interpolator),让整个过程看起来很炫。

先说动画的起点和终点吧,起点很简单,就是整个view的左下角,即0,0点,为了效果漂亮一些,我们稍微的将左下角位置定义的有一些偏移,经验上的值是16,-13,这个点的位置看你心情而定咯~ 好 终点就是你想让他在的点上就好了,终点我们将定义到layout中去,为这个2级菜单指定一个margin的值就好。

还是上代码比较直观:

动画如下:

View Row Code
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个插值器提供了弹力效果。

整段的代码如下:

View Row Code
1public class ComposerButtonAnimation extends InOutAnimation {2  3          publicstatic final int                  DURATION       = 500;4          privatestatic final int       xOffset              = 16;5          privatestatic final int       yOffset              = -13;6  7          publicComposerButtonAnimation(Direction direction,long l, View view) {8                    super(direction, l,new View[] { view });9          }10  11          publicstatic void startAnimations(ViewGroup viewgroup,12                             InOutAnimation.Direction direction) {13                    switch (direction) {14                    caseIN:15                             startAnimationsIn(viewgroup);16                             break;17                    caseOUT:18                             startAnimationsOut(viewgroup);19                             break;20                    }21          }22  23          privatestatic void startAnimationsIn(ViewGroup viewgroup) {24                    for (int i= 0; i < viewgroup.getChildCount(); i++) {25                             if (viewgroup.getChildAt(i) instanceof InOutImageButton) {26                                      InOutImageButton inoutimagebutton = (InOutImageButton) viewgroup27                                                         .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(newOvershootInterpolator(2F));33                                      inoutimagebutton.startAnimation(animation);34                             }35                    }36          }37  38          privatestatic void startAnimationsOut(ViewGroup viewgroup) {39                    for (int i= 0; i < viewgroup.getChildCount(); i++) {40                             if (viewgroup.getChildAt(i) instanceof InOutImageButton) {41                                      InOutImageButton inoutimagebutton = (InOutImageButton) viewgroup42                                                         .getChildAt(i);43                                      ComposerButtonAnimation animation = new ComposerButtonAnimation(44                                                        InOutAnimation.Direction.OUT,DURATION,45                                                         inoutimagebutton);46                                      animation.setStartOffset((100* ((-1+ viewgroup47                                                         .getChildCount())- i))48                                                        / (-1+ viewgroup.getChildCount()));49                                       animation.setInterpolator(newAnticipateInterpolator(2F));50                                      inoutimagebutton.startAnimation(animation);51                             }52                    }53          }54  55          @Override56          protectedvoid 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          @Override64          protectedvoid 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

View Row Code
1addAnimation(newScaleAnimation(0F, 1F, 0F, 1F, 1, 0.5F, 1, 0.5F));2addAnimation(newAlphaAnimation(0F, 1F));

View Row Code
1public class ComposerButtonGrowAnimationIn extends InOutAnimation {2  3          publicComposerButtonGrowAnimationIn(int i) {4                    super(InOutAnimation.Direction.IN, i,new View[0]);5          }6  7          @Override8          protectedvoid 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          @Override15          protectedvoid addOutAnimation(View[] aview) {}16  17}18  19public class ComposerButtonGrowAnimationOut extends InOutAnimation {20  21          publicComposerButtonGrowAnimationOut(int i) {22                    super(InOutAnimation.Direction.OUT, i,new View[0]);23          }24  25          @Override26          protectedvoid addInAnimation(View[] aview) {}27  28          @Override29          protectedvoid 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          publicComposerButtonShrinkAnimationOut(int i) {37                    super(InOutAnimation.Direction.OUT, i,new View[0]);38          }39  40          @Override41          protectedvoid addInAnimation(View[] aview) {42  43          }44  45          @Override46          protectedvoid 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}

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

很简单:

View Row Code
1public class InOutImageButton extendsImageButton {2  3          privateAnimation    animation;4  5          publicInOutImageButton(Context context,AttributeSet attrs, int defStyle) {6                    super(context, attrs, defStyle);7          }8  9          publicInOutImageButton(Context context,AttributeSet attrs) {10                    super(context, attrs);11          }12  13          publicInOutImageButton(Context context) {14                    super(context);15          }16  17          @Override18          protectedvoid onAnimationEnd() {19                    super.onAnimationEnd();20                    if ((this.animationinstanceof InOutAnimation)) {21                             setVisibility(((InOutAnimation) this.animation).direction !=InOutAnimation.Direction.OUT? View.VISIBLE22                                                :View.GONE);23                    }24          }25  26          @Override27          protectedvoid onAnimationStart() {28                    super.onAnimationStart();29                    if ((this.animationinstanceof InOutAnimation))30                             setVisibility(View.VISIBLE);31          }32  33          @Override34          publicvoid startAnimation(Animation animation) {35                    super.startAnimation(animation);36                    this.animation = animation;37                    getRootView().postInvalidate();38          }39}

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

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

原创粉丝点击