zoukankan      html  css  js  c++  java
  • (三)实现菜单点击动画

          在上一篇中,我们已经处理好了菜单的折叠和展开。如果你还没读过,可以点击下面的链接:
    http://www.cnblogs.com/fuly550871915/p/4930654.html

           贴出上一篇文章的效果图吧,如下:

          折叠和展开还不错。所写的代码也越来越简单,主要就是动画的添加而已。下面我们为每一个菜单添加点击动画。即,点击的时候,,让被点击的菜单放大消失,其他菜单缩小消失。

         我们还是直接看代码,然后在做解释吧。还是修改ArcMenu中的代码,如下:

      1 package com.example.menu;
      2 
      3 import android.content.Context;
      4 import android.content.res.TypedArray;
      5 import android.util.AttributeSet;
      6 import android.util.TypedValue;
      7 import android.view.View;
      8 import android.view.View.OnClickListener;
      9 import android.view.animation.Animation;
     10 import android.view.animation.Animation.AnimationListener;
     11 import android.view.animation.AlphaAnimation;
     12 import android.view.animation.AnimationSet;
     13 import android.view.animation.RotateAnimation;
     14 import android.view.animation.ScaleAnimation;
     15 import android.view.animation.TranslateAnimation;
     16 import android.view.ViewGroup;
     17 
     18 public class ArcMenu extends ViewGroup implements OnClickListener{
     19     /**
     20      * 菜单按钮
     21      */
     22     private View mCBMenu;
     23     /**
     24      * 菜单的位置,为枚举类型
     25      * @author fuly1314
     26      *
     27      */
     28     private enum Position
     29     {
     30         LEFT_TOP,LEFT_BOTTOM,RIGHT_TOP,RIGHT_BOTTOM
     31     }
     32     /**
     33      * 菜单的状态
     34      * @author fuly1314
     35      *
     36      */
     37     private enum Status
     38     {
     39         OPEN,CLOSE
     40     }
     41     /**
     42      * 菜单为当前位置,默认为RIGHT_BOTTOM,在后面我们可以获取到
     43      */
     44     private Position mPosition = Position.RIGHT_BOTTOM;
     45     /**
     46      * 菜单的当前状态,默认为关闭
     47      */
     48     private Status mCurStatus = Status.CLOSE;
     49     
     50     /**
     51      * 菜单的半径,默认为120dp
     52      */
     53     private int mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150,
     54             getResources().getDisplayMetrics());
     55 
     56     
     57     
     58     public ArcMenu(Context context) {
     59         this(context,null);
     60     }
     61     public ArcMenu(Context context, AttributeSet attrs) {
     62         this(context,attrs,0);
     63     }
     64     public ArcMenu(Context context, AttributeSet attrs, int defStyle) {
     65         super(context, attrs, defStyle);
     66         
     67         TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ArcMenu, defStyle, 0);
     68         //获取到菜单设置的位置
     69         int position = ta.getInt(R.styleable.ArcMenu_position, 3);
     70         
     71         switch(position){
     72         case 0:
     73             mPosition = Position.LEFT_TOP;
     74             break;
     75         case 1:
     76             mPosition = Position.LEFT_BOTTOM;
     77             break;
     78         case 2:
     79             mPosition = Position.RIGHT_TOP;
     80             break;
     81         case 3:
     82             mPosition = Position.RIGHT_BOTTOM;
     83             break;
     84         }
     85         
     86         //获取到菜单的半径
     87         mRadius = (int) ta.getDimension(R.styleable.ArcMenu_radius,
     88                 TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 120,
     89                         getResources().getDisplayMetrics()));            
     90         ta.recycle();
     91         
     92     }
     93     
     94     
     95     
     96     /**
     97      * 测量各个子View的大小
     98      */
     99     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    100     {
    101         int count = getChildCount();//获取子view的数量
    102         
    103         for(int i=0;i<count;i++)
    104         {
    105             //测量子view的大小
    106             measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
    107         }
    108         
    109         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    110     }
    111 
    112     /**
    113      * 摆放各个子view的位置
    114      */
    115     protected void onLayout(boolean changed, int l, int t, int r, int b) {
    116         
    117         if(changed)//如果发生了改变,就重新布局
    118         {
    119             layoutMainMenu();//菜单按钮的布局
    120             /**
    121              * 下面的代码为菜单的布局
    122              */
    123             int count = getChildCount();
    124             
    125             for(int i=0;i<count-1;i++)
    126             {
    127                 View childView = getChildAt(i+1);//注意这里过滤掉菜单按钮,只要菜单选项view
    128                 
    129                 childView.setVisibility(GONE);//先让菜单消失
    130                 
    131                 int left = (int) (mRadius*Math.cos(Math.PI/2/(count-2)*i));
    132                 int top = (int) (mRadius*Math.sin(Math.PI/2/(count-2)*i));
    133 
    134                 
    135                 
    136                 switch(mPosition)
    137                 {
    138                 
    139                 case LEFT_TOP:
    140                     break;
    141                 case LEFT_BOTTOM:
    142                     top = getMeasuredHeight() - top-childView.getMeasuredHeight();
    143                     break;
    144                 case RIGHT_TOP:
    145                     left = getMeasuredWidth() - left-childView.getMeasuredWidth();
    146                     break;
    147                 case RIGHT_BOTTOM:
    148                     left = getMeasuredWidth() - left-childView.getMeasuredWidth();
    149                     top = getMeasuredHeight() - top-childView.getMeasuredHeight();
    150                     break;
    151                 }
    152                 
    153                 childView.layout(left, top, left+childView.getMeasuredWidth(),
    154                         top+childView.getMeasuredHeight());
    155             }
    156         }
    157 
    158         
    159     }
    160     /**
    161      * 菜单按钮的布局
    162      */
    163     private void layoutMainMenu() {
    164         
    165          mCBMenu = getChildAt(0);//获得主菜单按钮
    166          
    167          mCBMenu.setOnClickListener(this);
    168         
    169         int left=0;
    170         int top=0;
    171         
    172         switch(mPosition)
    173         {
    174         case LEFT_TOP:
    175             left = 0;
    176             top = 0;
    177             break;
    178         case LEFT_BOTTOM:
    179             left = 0;
    180             top = getMeasuredHeight() - mCBMenu.getMeasuredHeight();
    181             break;
    182         case RIGHT_TOP:
    183             left = getMeasuredWidth() - mCBMenu.getMeasuredWidth();
    184             top = 0;
    185             break;
    186         case RIGHT_BOTTOM:
    187             left = getMeasuredWidth() - mCBMenu.getMeasuredWidth();
    188             top = getMeasuredHeight() - mCBMenu.getMeasuredHeight();
    189             break;
    190         }
    191         
    192         mCBMenu.layout(left, top, left+mCBMenu.getMeasuredWidth(), top+mCBMenu.getMeasuredHeight());
    193     }
    194     /**
    195      * 菜单按钮的点击事件
    196      * @param v
    197      */
    198     public void onClick(View v) {
    199         //为菜单按钮设置点击动画
    200         RotateAnimation rAnimation = new RotateAnimation(0f, 720f, Animation.RELATIVE_TO_SELF, 0.5f, 
    201                 Animation.RELATIVE_TO_SELF, 0.5f);
    202         
    203         rAnimation.setDuration(300);
    204         
    205         rAnimation.setFillAfter(true);
    206         
    207         v.startAnimation(rAnimation);
    208         
    209         dealChildMenu(300);//处理菜单选项,比如折叠菜单或者展开菜单
    210         
    211     }
    212     /**
    213      * 处理菜单选项,比如折叠菜单或者展开菜单
    214      * @param duration 菜单选项的动画时间
    215      */
    216     private void dealChildMenu(int duration) 
    217     {
    218         
    219         //下面的代码为菜单选项设置动画
    220         
    221         int count = getChildCount();
    222         
    223         for(int i=0;i<count-1;i++)
    224         {
    225             final View childView = getChildAt(i+1);
    226             
    227             AnimationSet set = new AnimationSet(true);
    228             
    229             //1.首先是平移动画
    230             TranslateAnimation tAnimation = null;
    231             
    232             //平移的x方向和y方向的距离
    233             int x = (int) (mRadius*Math.cos(Math.PI/2/(count-2)*i));
    234             int y = (int) (mRadius*Math.sin(Math.PI/2/(count-2)*i));
    235             
    236             
    237             
    238             
    239             //平移的标志,是平移一个正数还以一个负数
    240             int xflag =1;
    241             int yflag =1;
    242         
    243             if(mPosition == Position.LEFT_TOP||mPosition == Position.LEFT_BOTTOM)
    244             {
    245                 xflag = -1;
    246             }
    247             if(mPosition == Position.LEFT_TOP||mPosition == Position.RIGHT_TOP)
    248             {
    249                 yflag = -1;
    250             }
    251             
    252             if(mCurStatus == Status.CLOSE)//如果当前状态为关闭则应该打开
    253             {
    254                  tAnimation = new TranslateAnimation(xflag*x, 0,
    255                         yflag*y, 0);
    256                 tAnimation.setDuration(duration);
    257                 tAnimation.setFillAfter(true);
    258                 
    259                 childView.setVisibility(VISIBLE);//设置菜单可见
    260                 
    261                 
    262             }else//否则为打开状态,就应该关闭
    263             {
    264                  tAnimation = new TranslateAnimation( 0,xflag*x,
    265                             0,yflag*y);
    266                     tAnimation.setDuration(duration);
    267                     tAnimation.setFillAfter(true);
    268                     //为打开状态,则菜单是可点击和获得焦点
    269                     childView.setClickable(true);
    270                     childView.setFocusable(true);
    271             }
    272             tAnimation.setStartOffset((i * 100) / count);
    273             tAnimation.setAnimationListener(new AnimationListener() {
    274                 
    275 
    276                 public void onAnimationStart(Animation animation) {
    277     
    278                     
    279                 }
    280                 
    281 
    282                 public void onAnimationRepeat(Animation animation) {
    283         
    284                     
    285                 }
    286                 
    287 
    288                 public void onAnimationEnd(Animation animation) {
    289 
    290                     if(mCurStatus == Status.CLOSE)
    291                     {
    292                         childView.setVisibility(GONE);
    293                         childView.setClickable(false);
    294                         childView.setFocusable(false);
    295                     }
    296                     
    297                 }
    298             });
    299             
    300             //2.然后是旋转动画
    301             RotateAnimation rAnimation = new RotateAnimation(0f, 0, Animation.RELATIVE_TO_SELF, 0.5f, 
    302                     Animation.RELATIVE_TO_SELF, 0.5f);
    303             rAnimation.setDuration(duration);
    304             rAnimation.setFillAfter(true);//动画结束是画面停留在此动画的最后一帧
    305             
    306             
    307             set.addAnimation(rAnimation);//一定要注意顺序,先旋转动画,然后再平移
    308             set.addAnimation(tAnimation);
    309             
    310             childView.startAnimation(set);
    311             
    312             //为菜单项设置点击事件
    313             final int cPos = i+1;
    314             childView.setOnClickListener(new OnClickListener() {
    315                 
    316                 @Override
    317                 public void onClick(View v) {
    318                     
    319                     clickAnimation(cPos);//点击动画
    320                     changeStatus();
    321                     
    322                     
    323                 }
    324             });
    325             
    326             
    327         }
    328         
    329         changeStatus();//动画完成后,要改变状态
    330         
    331     }
    332     /**
    333      * 改变状态
    334      */
    335     private void changeStatus() {
    336         
    337         mCurStatus = (mCurStatus == Status.CLOSE?Status.OPEN:Status.CLOSE);
    338         
    339     }
    340     /**
    341      * 菜单项的点击动画
    342      * @param cPos  用来判断当前点击的是哪一个菜单
    343      */
    344     private void clickAnimation(int cPos) {
    345         
    346         for(int i=0;i<getChildCount()-1;i++)
    347         {
    348             View childView = getChildAt(i+1);
    349             
    350             if(i+1== cPos)
    351             {
    352                 AnimationSet set = new AnimationSet(true);
    353                 ScaleAnimation sAnimation = new ScaleAnimation(1.0f, 3.0f, 1.0f, 3.0f,
    354                         Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
    355                 sAnimation.setFillAfter(true);
    356                 AlphaAnimation alAnimation = new AlphaAnimation(1.0f, 0f);
    357                 alAnimation.setFillAfter(true);
    358                 
    359                 set.addAnimation(sAnimation);
    360                 set.addAnimation(alAnimation);
    361                 
    362                 set.setDuration(300);
    363                 childView.startAnimation(set);
    364                 
    365             }else
    366             {
    367                 AnimationSet set = new AnimationSet(true);
    368                 ScaleAnimation sAnimation = new ScaleAnimation(1.0f, 0.0f, 1.0f, 0.0f,
    369                         Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
    370                 sAnimation.setFillAfter(true);
    371                 AlphaAnimation alAnimation = new AlphaAnimation(1.0f, 0f);
    372                 alAnimation.setFillAfter(true);
    373                 
    374                 set.addAnimation(sAnimation);
    375                 set.addAnimation(alAnimation);
    376                 
    377                 set.setDuration(300);
    378                 childView.startAnimation(set);
    379             }
    380             childView.setVisibility(GONE);
    381         }
    382         
    383     }
    384 
    385 }

          红色部分是我们主要添加的代码。无非就是两个动画的添加,即缩放动画和透明度动画。没什么好说的,代码都写的很清晰了。然后要注意点击菜单后,要改变一下状态。因此点击菜单,所有的菜单都要消失。这个时候把状态改为关闭,是恰当的。然后我们运行一下效果,如下:

          好吧,模拟器上的效果还是不流畅。能在真机上实验要好一点。是不是越来越感觉代码写起来轻松了呢?确实是,主要的难点,也就是一个自定义的ViewGroup。下面我们实现点击按钮,弹出提示框吧。进入下一节。

  • 相关阅读:
    2018.09.08什么是ajax
    2018.09.03怎样让网页自适应所有屏幕宽度
    2018.08.25字符串和二维数组之间的转换
    2018.08.20MySQL常用命令总结(二)
    2018.08.15解决MySQL1290问题
    2018.08.13MySQL常用命令总结(一)
    2018.08.11MySQL无法启动错误码1067的解决方法
    2018.08.10 css中position定位问题
    2018.08.10jQuery导航栏置顶
    2018.08.07css实现图片放大
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4930699.html
Copyright © 2011-2022 走看看