在上一篇博客中,我们分析了Android中四大动画的基本介绍、使用方法、特征。还没有浏览的童靴看这里:Android动画之旅一Android动画基本介绍
本篇博客,我将和大家一起使用Android动画来实现一个简单的实例:仿简聊App动画菜单。其实在好多App中都有使用了该动画的菜单。好啦,开始我们今天的主题。
首先,我们先来看一下要实现的效果,因为没有做成gif图,所以我分成了两部分来展示:
(1)初始状态:
(2)点击FloatingButton后,菜单向上依次展开,并伴有外弹的状态:
通过上面两幅截图可以看到,当我们点击按钮时,动画的执行和改变可以总结为以下流程:
点击按钮 →播放点击的声音 →按钮正方向旋转45度 → 4个菜单依次向上弹出 → 点击按钮 → 4个菜单依次回收 → 动画结束
有了动画的执行流程,大家是不是已经知道使用哪种Android动画来实现了呢?首先我们来回想上一篇博客中对Android动画的分析:
(1)逐帧动画(Frame Animation):将动画一帧帧播放出来。
(2)补间动画(Tween Animation):定义开始结束帧,中间播放帧由系统计算完成,不能改变View的属性,只是简单实现动画效果。
(3)属性动画(Property Animation):Android3.0后出现的动画框架,适用于大部分场景,能改变View的属性。
(4)布局动画(Layout Animation):对布局设置动画,子View去实现动画。
从上面分析我们可以看出,使用逐帧动画、补间动画、布局动画都是不合适的,因为在菜单弹出后,当我们点击菜单时需要响应事件,所以我们需要使用属性动画来实现。
首先,新建一个工程,名字为 AnimationTest(名字可任意)。
上面我们已经分析了动画的实现过程,首先我们需要6张图片,此处我只设置3个菜单按钮,然后一个FloatingButton。一共就是4张图片。
private int imageRes[] = new int[]{ R.id.iv_a, R.id.iv_b, R.id.iv_c, R.id.iv_d, R.id.iv_e};
上图中a是FloatingButton,下面是4个菜单按钮。此处我们用一个int型数组将图片的id存起来。for(int i = 0;i < imageRes.length;i++){ ImageView imageView = (ImageView) findViewById(imageRes[i]); imageView.setOnClickListener(this); imageViewList.add(imageView);}
我们遍历id数组,然后获取ImageView后,给每一个ImageView添加上单击事件,然后再用一个List<ImageView>数组将ImageView存起来。此处我们用List保存imageView的用处是因为我们需要给每一个按钮都设置动画,这样就有利于我们下面去循环的设置每一个ImageView,将动画设置进去。
@Overridepublic void onClick(View v) { switch(v.getId()) { case R.id.iv_a: if(!isShow){ startAnim1(); isShow = true; } else { closeAnim(); isShow = false; } break; default: Toast.makeText(MainActivity.this,v.getId()+"",Toast.LENGTH_SHORT).show();; break; }}
上面我们给FloatingButton注册了一个单击事件,然后用一个boolean 类型的 isShow变量来标示是展开动画还是关闭动画。/** * 菜单展开动画 */private void startAnim() { for (int i = 1; i < imageViewList.size(); i++) { ObjectAnimator anim = ObjectAnimator.ofFloat( imageViewList.get(i),"translationY",0F,-i * 100); anim.setDuration(500); anim.setStartDelay(200); anim.setInterpolator(new BounceInterpolator()); anim.start(); }}
上面这段代码是动画的核心方法,在方法中,我们从第二个图片遍历ImageView的List集合(此处我们从i=1开始,即把FloatingButton的动画单独去写),获取每一个ImageView然后用ObjectAnimator类的ofFloat动画去包装,想必大家都知道为什么用这个方式了吧?对的,Y轴移动。然后设置动画的时间,startDelay方法是延迟多少毫秒执行该动画,为什么这么做呢?还记得开头我们说的吧,要让菜单有次序的展开,哈哈,就是这个理!interpolator设置动画的运动速度,还不理解这块的小伙伴可以先去看第二篇博客,里面有对此进行了解释。
最后调用start方法去开启动画。到这里,展开动画就完成了,小伙伴们欢呼声在哪里!是不是超级简单的就实现了这么炫的一个动画效果!下面我们来实现关闭的动画:
/** * 关闭动画 */private void closeAnim() { for (int i = 1; i < imageViewList.size(); i++) { ObjectAnimator anim = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY",-i*100,0F); anim.setDuration(500); anim.setStartDelay(200); anim.setInterpolator(new DecelerateInterpolator()); anim.start(); }}
关闭动画其实也非常简单,上面我们对展开动画只需要取反向的移动就可以了,看上图代码,我们只改变了起始的Y,然后让其移动至0F,也就是图标展开时的起始位置。这样一个展开,关闭的动画就轻松实现了!下面我们对FloatingButton按钮进行一些动画装饰。
在开始的需求中,我们说到,在展开时,让按钮做正向旋转45度,关闭时反响旋转45度的动画效果,来看代码:
/** * 按钮正向旋转 */private void btnPositiveRotate(){ RotateAnimation mRotateAnimation = new RotateAnimation(0F,45F,50,50); mRotateAnimation.setFillAfter(true); mRotateAnimation.setDuration(500); imageViewList.get(0).startAnimation(mRotateAnimation);}/** * 按钮反向旋转 */private void btnReverseRotate(){ RotateAnimation mRotateAnimation = new RotateAnimation(45F,0F,50,50); mRotateAnimation.setFillAfter(true); mRotateAnimation.setDuration(500); imageViewList.get(0).startAnimation(mRotateAnimation);}
因为按钮没有移动,只是在原地 的做动画的效果,所以此处我们就可以使用补间动画来实现,此处我们使用RotateAnimation旋转动画,在其构造函数中传入旋转参数RotateAnimation有多个重载的构造函数:可以看到,fromDegress就是从哪个角度开始旋转,toDegrees是旋转到的角度值,pivotX,pivotY是以某个坐标点旋转。传入50就是按照自己的中心旋转。
到此为止,我们的动画就基本上完成了,距离最终完成就剩下最后一步,点击按钮播放声音。
其实在Android中Google为我们播放多媒体做了很多的封装类,此处我们使用MediaPlayer来实现:
//创建MediaPlayer来播放声音mMediaPlayer = MediaPlayer.create(this,R.raw.voice_pink05);工程默认情况下是res中没有创建raw文件夹的,需要我们去手动创建,然后将.wav后缀的文件放到raw:
MediaPlayer类为我们提供了start、stop、release等方法来完成基本操作。即在开始动画的方法中,我们只需要调用start方法来开始播放就OK啦!
/** * 单击按钮播放声音 */private void playSound() { mMediaPlayer.start();}最后,记得在窗口destory时,调用release方法来释放MediaPlayer的资源就可以啦!
@Overrideprotected void onDestroy() { super.onDestroy(); mMediaPlayer.release();//释放资源}
以上就是今天的全部内容,大家可以细细品味Android动画所带来的乐趣吧!最近有收到小伙伴们的一些来信,说想了解下App中用的比较多的下拉窗帘布局和上拉抽屉式布局,那么在下一篇,我将继续为大家带来Android动画实战 一 实现下拉式窗帘动画和上拉式抽屉动画
最后附上今天的源码链接:高仿简聊菜单动画
- 1楼liuguofeng719前天 23:00
- 写的不错哦。挺你
- Re: u013718120前天 09:52
- 回复liuguofeng719谢谢支持哈!