• android 自定菜单功能


    转载:原文地址:

    http://www.cnblogs.com/mudoot/archive/2012/01/19/path_composer_menu.html

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

    2012-01-19 05:30 by MudooT, 3548 阅读, 13 评论, 收藏编辑

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

         上图先:

             那么下面开始吧~

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

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

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

    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提供in和out两种不同的状态时的动画效果。其子类需要实现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 }
    复制代码

    剩下的增大出现、增大消失及缩小消失都是scale和alpha的组合动画

    例如增大出现为: 

    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 }
    复制代码

    那么到这里基本上就已经搞定了所有的事情了,剩下点没做的事就是把这些动画效果设置给对应的控件了,这里就不详细描述了,大家有兴趣可以直接下载源码来搞一下啦~

      

  • 相关阅读:
    cookie的使用
    给定一个数组和一个目标值,找出和为目标值的整数,并返回他们的下标
    String详解
    阳哥讲面试题(四)生产调优
    springboot项目调优(针对特性的服务启动,定制化诉求)
    intern() 方法
    阳哥讲面试题(四)OOM,GC算法,垃圾收集器
    阳哥讲面试题(三)JVM,GC
    阳哥讲面试题(二)队列,线程池
    Semaphore用法
  • 原文地址:https://www.cnblogs.com/pengqinping/p/2802111.html
Copyright © 2020-2023  润新知