實現Path2.0中絢麗的的旋轉菜單


最近真的是忙死了,做了很久的這個菜單動畫特效,都沒有時間寫博客,今天在機場等飛機終於有了空閑時間。

     上圖先:

         那么下面開始吧~

         首先,將整個菜單動畫分解開來。

1.       一級菜單按鈕的旋轉動畫2個,十字和叉叉狀態的轉換。

2.       二級菜單按鈕的平移動畫2個,彈簧效果的inout

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提供inout兩種不同的狀態時的動畫效果。其子類需要實現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  
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個插值器提供了彈力效果。

整段的代碼如下:

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 }

 

 

剩下的增大出現、增大消失及縮小消失都是scalealpha的組合動畫

例如增大出現為: 

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 }

那么到這里基本上就已經搞定了所有的事情了,剩下點沒做的事就是把這些動畫效果設置給對應的控件了,這里就不詳細描述了,大家有興趣可以直接下載源碼來搞一下啦~

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM