多语言展示
当前在线:1562今日阅读:155今日分享:35

Android实现弹力伸缩式菜单

利用Android中自带的动画效果来实现弹力伸缩式菜单,默认情况下,菜单项为隐藏状态,当点击某一图标,打开菜单项,则通过一系列动画效果实现菜单项的展示;当再次点击该图标时,关闭菜单项,则通过一系列动画实现菜单项的隐藏。效果图如下:
工具/原料
1

利用Android设置动画的同时,并使用插入器(interpolator)来实现弹力

2

OvershootInterpolator插入器,表示向前甩出一定值后再回到之前的位置

3

AnticipateOvershootInterpolator插入器,表示开始的时候向后,然后向前甩

方法/步骤
1

自定义相对布局I114gBoxRelativeLayout类,源码如下:/** *  */package com.i114gbox.sdk.ui;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.animation.Animation;import android.widget.RelativeLayout;import com.i114gbox.sdk.animation.I114gBoxZoomAnimation;import com.i114gbox.sdk.utils.I114gBoxLogUtils;/** * 自定义相对布局 *  * @author shenjichao@vivagame.cn *  */public class I114gBoxRelativeLayout extends RelativeLayout { private static String TAG = 'I114gBoxRelativeLayout'; private Animation mAnimation;// 动画对象 public I114gBoxRelativeLayout(Context ctx) { super(ctx); } public I114gBoxRelativeLayout(Context ctx, AttributeSet attrs) { super(ctx, attrs); } public I114gBoxRelativeLayout(Context ctx, AttributeSet attrs, int defStyle) { super(ctx, attrs, defStyle); } /** 开始指定的动画 **/ @Override public void startAnimation(Animation animation) { I114gBoxLogUtils.d(TAG, 'The startAnimation method execute.'); super.startAnimation(animation); this.mAnimation = animation; this.getRootView().postInvalidate();// 刷新界面,不需要Handler,是工作者线程 // this.getRootView().invalidate();//刷新界面,需要被主线程调用,需要Handler } /** 通知和目前有关的视图动画开始 **/ @Override protected void onAnimationStart() { I114gBoxLogUtils.d(TAG, 'The onAnimationStart method execute.'); super.onAnimationStart(); if (this.mAnimation instanceof I114gBoxZoomAnimation) { setVisibility(View.VISIBLE); } } /** 通知和目前有关的视图动画结束 **/ @Override protected void onAnimationEnd() { I114gBoxLogUtils.d(TAG, 'The onAnimationEnd method execute.'); super.onAnimationEnd(); if (this.mAnimation instanceof I114gBoxZoomAnimation) { setVisibility(((I114gBoxZoomAnimation) mAnimation).mDirection != I114gBoxZoomAnimation.Direction.HIDE ? View.GONE : View.VISIBLE); } }}

2

自定义图片按钮控件I114gBoxImageButton类,源码如下:/** *  */package com.i114gbox.sdk.ui;import com.i114gbox.sdk.animation.I114gBoxZoomAnimation;import com.i114gbox.sdk.utils.I114gBoxLogUtils;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.animation.Animation;import android.widget.ImageButton;/** * 自定义ImageButton *  * @author shenjichao@vivagame.cn *  */public class I114gBoxImageButton extends ImageButton { private static String TAG = 'I114gBoxImageButton'; private Animation mAnimation;// 动画对象 public I114gBoxImageButton(Context ctx) { super(ctx); } public I114gBoxImageButton(Context ctx, AttributeSet attrs) { super(ctx, attrs); } public I114gBoxImageButton(Context ctx, AttributeSet attrs, int defStyle) { super(ctx, attrs, defStyle); } @Override public void startAnimation(Animation animation) { I114gBoxLogUtils.d(TAG, 'The startAnimation method execute.'); super.startAnimation(animation); this.mAnimation = animation; this.getRootView().postInvalidate(); } @Override protected void onAnimationStart() { I114gBoxLogUtils.d(TAG, 'The onAnimationStart method execute.'); super.onAnimationStart(); if (this.mAnimation instanceof I114gBoxZoomAnimation) { setVisibility(View.VISIBLE); } } @Override protected void onAnimationEnd() { I114gBoxLogUtils.d(TAG, 'The onAnimationEnd method execute.'); super.onAnimationEnd(); if (this.mAnimation instanceof I114gBoxZoomAnimation) { setVisibility(((I114gBoxZoomAnimation) mAnimation).mDirection != I114gBoxZoomAnimation.Direction.HIDE ? View.GONE : View.VISIBLE); } }}

3

include到主layout中的布局文件如下:                                                                                                                           

4

实现菜单项打开时的动画效果:// 获取菜单添加视图 imageViewPlus = findViewById(I114gBoxResourceUtils.getId(ctx, 'iv_menu_main_plus')); // 获取菜单包裹视图组,存放多个菜单项 menusWrapper = (ViewGroup) findViewById(I114gBoxResourceUtils.getId( ctx, 'rl_menus_wrapper')); // 获取菜单添加视图的布局 menuShrinkView = findViewById(I114gBoxResourceUtils.getId(ctx, 'rl_menu_main_shrink')); // layoutMain = (RelativeLayout) findViewById(R.id.layout_content); // 打开菜单时,顺时针动画 animRotateClockwise = AnimationUtils.loadAnimation(ctx, I114gBoxResourceUtils.getAnimId(ctx, 'menu_rotate_clockwise')); // 关闭菜单时,逆时针动画 animRotateAntiClockwise = AnimationUtils.loadAnimation(ctx, I114gBoxResourceUtils.getAnimId(ctx, 'menu_rotate_anticlockwise')); // 添加监听事件 menuShrinkView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showLinearMenus();// 显示菜单项 } }); for (int i = 0; i < menusWrapper.getChildCount(); i++) { menusWrapper.getChildAt(i).setOnClickListener( new SpringMenuLauncher(intentActivity[i])); }/** * 显示菜单项 */ private void showLinearMenus() { int[] size = I114gBoxSystemManagerUtils.getScreenSize(ctx);// 获取屏幕高度和宽度 if (!areMenusShowing) {// 当菜单未打开时 I114gBoxAnimation.startAnimations(this.menusWrapper, Direction.SHOW, size); this.imageViewPlus.startAnimation(this.animRotateClockwise); } else {// 当菜单已打开时 I114gBoxAnimation.startAnimations(this.menusWrapper, Direction.HIDE, size); this.imageViewPlus.startAnimation(this.animRotateAntiClockwise); } areMenusShowing = !areMenusShowing; } private class I114gBoxMenuLauncher implements OnClickListener { private final Class cls; private int resource; private I114gBoxMenuLauncher(Class c, int resource) { this.cls = c; this.resource = resource; } private I114gBoxMenuLauncher(Class c) { this.cls = c; } public void onClick(View v) { MainActivity.this.startOpenMenuAnimations(v);// 打开菜单项动画 Intent intent = new Intent(ctx, cls); ctx.startActivity(intent); } } /** 打开菜单项动画 **/ private void startOpenMenuAnimations(View view) { areMenusShowing = true; Animation inAnimation = new I114gBoxShrinkAnimationOut(300); Animation outAnimation = new I114gBoxEnlargeAnimationOut(300); inAnimation.setInterpolator(new AnticipateInterpolator(2.0F)); // inAnimation.setInterpolator(new CycleInterpolator(2.0F)); inAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationEnd(Animation animation) { MainActivity.this.imageViewPlus.clearAnimation(); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } }); view.startAnimation(outAnimation); }

5

顺时针动画定义:逆时针动画定义:

注意事项
1

需要定义顺时针和逆时针动画文件

2

需要将动画效果和插入器相结合

推荐信息