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

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

上圖先: java

本人推薦學習技術資料百搜技術網:http://www.baisoujs.com/list_android_andarticle.html android

各類電子書下載:http://www.baisoujs.com/book_new.html ide

Android實現Path2.0中絢麗的的旋轉菜單 - 1Android實現Path2.0中絢麗的的旋轉菜單 - 2

那麼下面開始吧~ 佈局

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

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

2. 二級菜單按鈕的平移動畫2個,彈簧效果的in和out。 動畫

3. 二級菜單按鈕的點擊效果,放大消失,其餘未點擊按鈕縮小消失。 this

4. 一級菜單按鈕的恢復效果,放大出現。 spa


 


rotate_story_add_button_out.xml


 


這2段沒什麼好說的,定義好角度便可。

接下來是須要咱們在代碼中定義的動畫部分,這幾個動畫的部分須要定義一個基類,做爲統一的調用接口,這個基類被稱做InOutAnimation,繼承自AnimationSet,這個基類的主要工做是爲view提供in和out兩種不一樣的狀態時的動畫效果。其子類須要實現2個方法:

好的 逐一去實現:

首先是一級菜單按鈕的旋轉動畫,這2個動畫能夠直接在xml中定義,而後load到代碼中來,具體代碼以下:

rotate_story_add_button_in.xml


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


從而進行view的入場和離場動畫。

下面是InOutAnimation的代碼部分:


//百搜技術:http://www.baisoujs.com

public abstract class InOutAnimation extends AnimationSet {
  
          public Direction        direction;
  
          public enum Direction {
                    IN, OUT;
          }
  
          public InOutAnimation(Direction direction, long l, View[] aview) {
                    super(true);
                    this.direction = direction;
                    switch (this.direction) {
                    case IN:
                             addInAnimation(aview);
                             break;
                    case OUT:
                             addOutAnimation(aview);
  
                             break;
                    }
                    setDuration(l);
          }
  
          protected abstract void addInAnimation(View aview[]);
  
          protected abstract void addOutAnimation(View aview[]);
  
 }


接下來就是重頭戲啦,二級菜單按鈕的平移動畫。

這部分動畫看起來可能會比較複雜和神祕,其實否則,當把整個動畫過程分解開來的時候,都是最最簡單的平移而已,咱們要作的只是定義一下平移的起點和終點、開始動畫的順序以及插值(Interpolator),讓整個過程看起來很炫。

先說動畫的起點和終點吧,起點很簡單,就是整個view的左下角,即0,0點,爲了效果漂亮一些,咱們稍微的將左下角位置定義的有一些偏移,經驗上的值是16,-13,這個點的位置看你心情而定咯~ 好 終點就是你想讓他在的點上就行了,終點咱們將定義到layout中去,爲這個2級菜單指定一個margin的值就好。

仍是上代碼比較直觀:

動畫以下:


收縮部分:TranslateAnimation(xOffset + -mlp.leftMargin, 0F,yOffset + mlp.bottomMargin, 0F)
擴張部分:TranslateAnimation(0F, xOffset + -mlp.leftMargin, 0F,yOffset + mlp.bottomMargin)


位置定義部分:

例如:

android:layout_marginBottom="142dp" android:layout_marginLeft="10.667dp"

這個位置你們能夠直觀的在佈局文件中看到,詳細的佈局文件也將在下面展現。

以上是單獨的每個二級按鈕的動畫,而組合的動畫就是指定了一下開始的時間差以及插值:

這個就是奧妙所在了,OvershootInterpolator AnticipateInterpolator 這2個插值器提供了彈力效果。

整段的代碼以下:


//百搜技術:http://www.baisoujs.com

public class ComposerButtonAnimation extends InOutAnimation {
  
          public static final int                  DURATION       = 500;
          private static final int       xOffset              = 16;
          private static final int       yOffset              = -13;
  
          public ComposerButtonAnimation(Direction direction, long l, View view) {
                    super(direction, l, new View[] { view });
          }
  
          public static void startAnimations(ViewGroup viewgroup,
                             InOutAnimation.Direction direction) {
                    switch (direction) {
                    case IN:
                             startAnimationsIn(viewgroup);
                             break;
                    case OUT:
                             startAnimationsOut(viewgroup);
                             break;
                    }
          }
  
          private static void startAnimationsIn(ViewGroup viewgroup) {
                    for (int i = 0; i < viewgroup.getChildCount(); i++) {
                             if (viewgroup.getChildAt(i) instanceof InOutImageButton) {
                                      InOutImageButton inoutimagebutton = (InOutImageButton) viewgroup
                                                         .getChildAt(i);
                                      ComposerButtonAnimation animation = new ComposerButtonAnimation(
                                                         InOutAnimation.Direction.IN, DURATION, inoutimagebutton);
                                      animation.setStartOffset((i * 100)
                                                         / (-1 + viewgroup.getChildCount()));
                                      animation.setInterpolator(new OvershootInterpolator(2F));
                                      inoutimagebutton.startAnimation(animation);
                             }
                    }
          }
  
          private static void startAnimationsOut(ViewGroup viewgroup) {
                    for (int i = 0; i < viewgroup.getChildCount(); i++) {
                             if (viewgroup.getChildAt(i) instanceof InOutImageButton) {
                                      InOutImageButton inoutimagebutton = (InOutImageButton) viewgroup
                                                         .getChildAt(i);
                                      ComposerButtonAnimation animation = new ComposerButtonAnimation(
                                                         InOutAnimation.Direction.OUT, DURATION,
                                                         inoutimagebutton);
                                      animation.setStartOffset((100 * ((-1 + viewgroup
                                                         .getChildCount()) - i))
                                                         / (-1 + viewgroup.getChildCount()));
                                       animation.setInterpolator(new AnticipateInterpolator(2F));
                                      inoutimagebutton.startAnimation(animation);
                             }
                    }
          }
  
          @Override
          protected void addInAnimation(View[] aview) {
                    MarginLayoutParams mlp = (MarginLayoutParams) aview[0]
                                      .getLayoutParams();
                    addAnimation(new TranslateAnimation(xOffset + -mlp.leftMargin, 0F,
                                      yOffset + mlp.bottomMargin, 0F));
          }
  
          @Override
          protected void addOutAnimation(View[] aview) {
                    MarginLayoutParams mlp = (MarginLayoutParams) aview[0]
                                      .getLayoutParams();
                    addAnimation(new TranslateAnimation(0F, xOffset + -mlp.leftMargin, 0F,
                                      yOffset + mlp.bottomMargin));
          }
 }


剩下的增大出現、增大消失及縮小消失都是scale和alpha的組合動畫。

例如增大出現爲:

ComposerButtonAnimation.java


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



//百搜技術:http://www.baisoujs.com

public class ComposerButtonGrowAnimationIn extends InOutAnimation {
  
          public ComposerButtonGrowAnimationIn(int i) {
                    super(InOutAnimation.Direction.IN, i, new View[0]);
          }
  
          @Override
          protected void addInAnimation(View[] aview) {
                    addAnimation(new ScaleAnimation(0F, 1F, 0F, 1F, 1, 0.5F, 1, 0.5F));
                    addAnimation(new AlphaAnimation(0F, 1F));
  
          }
  
          @Override
          protected void addOutAnimation(View[] aview) {}
  
 }
  
 public class ComposerButtonGrowAnimationOut extends InOutAnimation {
  
          public ComposerButtonGrowAnimationOut(int i) {
                    super(InOutAnimation.Direction.OUT, i, new View[0]);
          }
  
          @Override
          protected void addInAnimation(View[] aview) {}
  
          @Override
          protected void addOutAnimation(View[] aview) {
                    addAnimation(new ScaleAnimation(1F, 5F, 1F, 5F, 1, 0.5F, 1, 0.5F));
                    addAnimation(new AlphaAnimation(1F, 0F));
          }
  
 } public class ComposerButtonShrinkAnimationOut extends InOutAnimation {
  
          public ComposerButtonShrinkAnimationOut(int i) {
                    super(InOutAnimation.Direction.OUT, i, new View[0]);
          }
  
          @Override
          protected void addInAnimation(View[] aview) {
  
          }
  
          @Override
          protected void addOutAnimation(View[] aview) {
                    addAnimation(new ScaleAnimation(1F, 0F, 1F, 0F, 1, 0.5F, 1, 0.5F));
                    addAnimation(new AlphaAnimation(1F, 0F));
          }
 }


接下來咱們須要爲這些控件作一下擴展,以便其能夠再動畫完成後顯示或消失。

很簡單:


public class InOutImageButton extends ImageButton {
  
          private Animation    animation;
  
          public InOutImageButton(Context context, AttributeSet attrs, int defStyle) {
                    super(context, attrs, defStyle);
          }
  
          public InOutImageButton(Context context, AttributeSet attrs) {
                    super(context, attrs);
          }
  
          public InOutImageButton(Context context) {
                    super(context);
          }
  
          @Override
          protected void onAnimationEnd() {
                    super.onAnimationEnd();
                    if ((this.animation instanceof InOutAnimation)) {
                             setVisibility(((InOutAnimation) this.animation).direction != InOutAnimation.Direction.OUT ? View.VISIBLE
                                                : View.GONE);
                    }
          }
  
          @Override
          protected void onAnimationStart() {
                    super.onAnimationStart();
                    if ((this.animation instanceof InOutAnimation))
                             setVisibility(View.VISIBLE);
          }
  
          @Override
          public void startAnimation(Animation animation) {
                    super.startAnimation(animation);
                    this.animation = animation;
                    getRootView().postInvalidate();
          }
 }


那麼到這裏基本上就已經搞定了全部的事情了,剩下點沒作的事就是把這些動畫效果設置給對應的控件了,這裏就不詳細描述了。

源碼下載:http://files.cnblogs.com/mudoot/PureComposerDemo.rar

原文出自: http://www.baisoujs.com/detail_137434192591287.html
您正在訪問的是 百搜技術 !但願百搜技術能協助您解決問題。如需提問,請移步 百搜論壇 (http://bbs.baisoujs.com)進行提問!
相關文章
相關標籤/搜索