• (四)实现菜单点击弹出提示框


          在上一篇文章中,我们给菜单的点击设置了动画,如果你没有阅读过,可以单击下面的链接:
    http://www.cnblogs.com/fuly550871915/p/4930699.html

          贴出上一篇文章实现的效果图吧。如下:

          下面我们要实现的逻辑也很简单,点击菜单,弹出一个提示框。怎么实现呢,只需要在ArcMenu中提供一个回调接口即可。这样子,我们就可以在MainActivity中重写回调方法,然后再ArcMenu中点击菜单时调用即可。

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

           红色部分是我们添加的主要代码。无非就是一个回调接口,没事什么好解释的了。

          下面修改MainActivity中的代码即可,如下:

     1 package com.example.menu;
     2 
     3 import com.example.menu.ArcMenu.ArcMenuListener;
     4 
     5 import android.os.Bundle;
     6 import android.view.View;
     7 import android.widget.Toast;
     8 import android.app.Activity;
     9 
    10 public class MainActivity extends Activity implements ArcMenuListener {
    11 
    12     private ArcMenu menu;
    13     @Override
    14     protected void onCreate(Bundle savedInstanceState) {
    15         super.onCreate(savedInstanceState);
    16         setContentView(R.layout.activity_main);
    17         
    18         menu = (ArcMenu) findViewById(R.id.id_menu);
    19         menu.setOnArcMenuListener(this);
    20     }
    21 
    22 
    23     public void dealMenuClick(View v) {
    24         
    25         Toast.makeText(this, "这是"+v.getTag(), Toast.LENGTH_SHORT).show();
    26         
    27     }
    28     
    29 }

            我们看红色部分的代码,重写了回调方法。无非就是获取之前布局中ImageView中设置的tag,然后把它放在提示框中罢了。运行程序效果如下:

           至此,我们的这个案例终结了。主要难点就是自定义ViewGroup,相信你通过这个案例,对自定义ViewGroup应该有了很好的了解了。

  • 相关阅读:
    常用数据库validationQuery语句
    mysql 删除某一个数据库下面的所有表,但不删除数据库
    Mysql 删除数据表的三种方式详解
    Java Web应用开发工具
    无效的列类型:getTimestamp not implemented for class oracle.jdbc.driver.T4CNumberAccessor
    request获取当前用户
    tomcat配置https
    shiro标签的使用
    Maven常用命令
    在Maven仓库中添加Oracle数据库的JDBC驱动依赖
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4930877.html
Copyright © 2020-2023  润新知