最近真的是忙死了,作了好久的這個菜單動畫特效,都沒有時間寫博客,今天在機場等飛機終於有了空閒時間。 html
上圖先: java
本人推薦學習技術資料百搜技術網:http://www.baisoujs.com/list_android_andarticle.html android
各類電子書下載:http://www.baisoujs.com/book_new.html ide
那麼下面開始吧~ 佈局
首先,將整個菜單動畫分解開來。 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