(三)实现菜单点击动画

在上一篇中,我们已经处理好了菜单的折叠和展开。如果你还没读过,可以点击下面的链接:
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。下面我们实现点击按钮,弹出提示框吧。进入下一节。

时间: 2024-11-03 03:26:18

(三)实现菜单点击动画的相关文章

Cocos2d-x 3.2 大富翁游戏项目开发-第三部分 菜单场景

上一部分介绍到片头动画介绍后进入到菜单场景,场景效果如图 MenuScene.h头文件如下: class MenuScene : public LayerColor { public: static Scene* createScene(); virtual bool init(); CREATE_FUNC(MenuScene); private: Size visibleSize; //窗口尺寸 LabelTTF* settingsGameTTF; //场景文字 void menuTouchD

(三十九)android动画 Animation四大属性 详解(转载:http://www.android100.org/html/201304/25/2295.html)

一.Animation主要有四大属性,分别是淡入淡出,绕轴旋转,变化大小,位移变化 二.四大属性的共同的方法 1.setDuration(long durationMills):设置动画持续的时间(单位:毫秒) 2.setFillAfter(boolean fillAfter):如果fillAfter的值为true,则动画执行后看,控件将停留在执行结束的状态 3.setFillBefore(boolean fillBefore):如果fillBefore的值为true,则动画执行后看,控件将停留

基于jQuery CSS3鼠标点击动画效果

分享基于jQuery CSS3鼠标点击动画效果支持图片或内容滑动,允许设置动画延迟效果.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="container"> <div class="clearfix"> <div class="grid12 small12"> <div class="demos fl" id="demos&quo

Waves – 赞!超炫交互体验的点击动画效果

Waves 点击效果的灵感来自于谷歌的材料设计,很容易使用.只需要引入 waves.min.css 和 waves.min.js 到 HTML 文件中可以使用了.采用 touchstart 与 touchend 事件,支持移动设备.赶紧来体验吧! 效果演示     插件下载 您可能感兴趣的相关文章 Web 开发中很实用的10个效果[源码下载] 精心挑选的优秀jQuery Ajax分页插件和教程 12个让人惊叹的的创意的 404 错误页面设计 让网站动起来!12款优秀的 jQuery 动画插件 十

AnimCheckBox按钮点击动画效果《IT蓝豹》

AnimCheckBox按钮点击动画效果 AnimCheckBox按钮点击动画效果,点击选中后勾选框选择效果,很不错的动画功能.项目来源:https://github.com/lguipeng/AnimCheckBox本项目主要介绍:本项目主要自定义AnimCheckBox 集成View,提供选择的监听接口OnCheckedChangeListener主要由drawCircle()方法和drawHook(Canvas canvas):  private void drawCircle(Canva

[cocos2d-x]如何自动发送菜单点击回调事件?

我们在工作中经常会碰到一些随机的bug,如果bug发生的概率很低,用手工重现就很麻烦.这时就必须考虑自动化执行有问题的代码段.如果是顺序执行的代码,加上一个循环就可以了.但如果是异步执行的回调事件,就不能简单的加上循环.比如,在httpclient的测试例中,有一个http get的测试菜单,点击一次这个菜单,就会执行下面的回调事件: void HttpClientTest::onMenuGetTestClicked(cocos2d::CCObject *sender) { //test1 ..

基于jQuery+CSS3点击动画弹出表单代码

分享一款基于jQuery+CSS3点击动画弹出表单代码是一款鼠标点击图标按钮动画弹出表单特效代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="buttonCollection"> <div class="qutton" id="qutton_upload"> <div class="qutton_dialog" id="uploadDial

react-navigation createDrawerNavigator 抽屉菜单 点击其他地方 无法关闭菜单的解决方案

react-native接入插件react-navigation 创建的抽屉菜单后  无法关闭抽屉菜单,只能再加一项“关闭”调用代码关闭菜单 点击其他地方无法关闭抽屉菜单 看了一下源码 没想到好办法后  在网上找到这样一个解决方案 现在贴出来: 下面是android的解决方案,在java中的MainActivity加入下面带+号的行代码: import com.facebook.react.ReactActivity;+ import com.facebook.react.ReactActivi

Android 开发第三弹:自定义左右菜单(滑动动画+蒙版效果)

下面的截图--哎,因为1080P在Windows 10上虽然适配了,但大部分软件并没有跟上,比如某个录制GIF的软件,所以这里有一定的偏移导致画面不完整,但效果大概就是这么一个效果了. MainUI.java 首先需要这么一个类,在这里一些UI的滑动呀之类的都会定义.首先吧,定义好这些变量,当然了,实际开发过程中肯定需要哪一个就添加上哪一个的. private Context context; // 上下文 private FrameLayout leftMenu; // 左边部分 privat