最近真的是忙死了,作了好久的这个菜单动画特效,都没有时间写博客,今天在机场等飞机终于有了空闲时间。 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