其实实现的思路就是利用Tween动画,通过对场景对象的不断变换(旋转,缩放,平移,改变透明度)效果来产生动画效果的。先来分析一下动画效果的形成,我们先把红色Button定义为一级菜单,弹出的子Button作为二级菜单。当点击一级菜单的时候,一级菜单旋转,同时弹出二级菜单。点击二级菜单,进入其他的Activity,不点击画面不变。点击一级菜单,二级菜单消失,一级菜单旋转到默认。所以就涉及到了一级菜单的旋转和二级菜单的缩放以及移动。
一级菜单的实现:
可以采用两种方式来实现,一种是xml布局,另一种就是硬编码了。我们采用第一种方法来实现,这样也比较符合标准。一级菜单是一个旋转效果,所以用Tween动画里的Rotate(旋转)来实现,在这里我们使用xml来定义动画效果,这样比较符合官方标准。
点击旋转动画:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillEnabled="true" android:fillAfter="true"> <rotate android:fromDegrees="0" android:duration="80" android:toDegrees="-45" android:pivotX="50%" android:pivotY="50%" android:interpolator="@android:anim/accelerate_decelerate_interpolator" > </rotate> </set>点击回复动画:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillEnabled="true" android:fillAfter="true"> <rotate android:fromDegrees="-45" android:duration="80" android:toDegrees="0" android:pivotX="50%" android:pivotY="50%" android:interpolator="@android:anim/accelerate_decelerate_interpolator" > </rotate> </set>通过这两个xml文件就可以实现一级菜单的旋转效果了,下面来说二级菜单的弹出效果,因为在path里它是在程序的左下角弹出的,当我们使用Tween动画的translate (移动)时,需要指定初始坐标以及终止坐标,这样一来就要弄清楚Android屏幕的坐标系,它是从右上角开始从左到右从上到下,如图:
我们的Button是从左下角弹出的,这样就可以根据屏幕的分辨率来动态的设置菜单坐标。我的手机分辨率是800*480,就以这个来说明。然后我们来看一下Button移动的xml文件。
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillEnabled="true" android:fillAfter="true"> <translate android:interpolator="@android:anim/cycle_interpolator" android:fromXDelta="0.0" android:toXDelta="50.0" android:fromYDelta="790" android:toYDelta="650.0" android:duration="80" > </translate> </set>这是最左边的那个Button,大家可以注意下坐标的设置。其他的xml文件就不展示了,原理和这个一样,只不过坐标不同。
最后看一下Activity的实现,
package com.example.imitatepathdemo; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.util.Log; import android.view.Display; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; import android.widget.Button; import android.widget.TextView; import android.widget.RelativeLayout.LayoutParams; public class ImitatePatn extends Activity { private static Boolean isClick = false; private LayoutParams params = new LayoutParams(0, 0); private TextView refresh; private static int width, height; private Animation animationTranslate1,animationTranslate2,animationTranslate3, animationTranslate4,animationTranslate5,animationTranslate6,animationRotate1,animationRotate2, animationScale1,animationScale2; private Button buttonCamera, buttonDelete, buttonWith, buttonPlace, buttonMusic, buttonThought, buttonSleep; private Intent intent1,intent2,intent3,intent4,intent5,intent6; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_imitate_patn); refresh=(TextView) this.findViewById(R.id.refresh); refresh.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent=new Intent(ImitatePatn.this,SleepActivity.class); startActivity(intent); } }); initialButton(); } private void initialButton() { Display display = getWindowManager().getDefaultDisplay(); height = display.getHeight(); width = display.getWidth(); Log.v("width & height is:", String.valueOf(width) + ", " + String.valueOf(height)); //padding是控件的内容相对控件的边缘的边距. //margin是控件边缘相对父控件,或者其他控件的边距. buttonSleep = (Button) findViewById(R.id.button_composer_sleep); buttonThought = (Button) findViewById(R.id.button_composer_thought); buttonMusic = (Button) findViewById(R.id.button_composer_music); buttonPlace = (Button) findViewById(R.id.button_composer_place); buttonWith = (Button) findViewById(R.id.button_composer_with); buttonCamera = (Button) findViewById(R.id.button_composer_camera); buttonDelete = (Button) findViewById(R.id.button_friends_delete); animationScale1=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.scale_animation1); animationScale2=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.scale_animation2); buttonDelete.setOnClickListener(new OnClickListener() { public void onClick(View v) { //一级菜单旋转,二级菜单弹出 if(isClick == false){ isClick=true; animationRotate1=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.rotate_animation1); buttonDelete.startAnimation(animationRotate1); animationTranslate1=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation1); animationTranslate1.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(10, 500, 0, 0); buttonSleep.setLayoutParams(params); buttonSleep.clearAnimation(); } }); buttonSleep.startAnimation(animationTranslate1); animationTranslate2=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation2); animationTranslate2.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(60, 510, 0, 0); buttonThought.setLayoutParams(params); buttonThought.clearAnimation(); } }); buttonThought.startAnimation(animationTranslate2); animationTranslate3=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation3); animationTranslate3.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(110, 540, 0, 0); buttonMusic.setLayoutParams(params); buttonMusic.clearAnimation(); } }); buttonMusic.startAnimation(animationTranslate3); animationTranslate4=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation4); animationTranslate4.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(150, 570, 0, 0); buttonPlace.setLayoutParams(params); buttonPlace.clearAnimation(); } }); buttonPlace.startAnimation(animationTranslate4); animationTranslate5=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation5); animationTranslate5.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(175, 610, 0, 0); buttonWith.setLayoutParams(params); buttonWith.clearAnimation(); } }); buttonWith.startAnimation(animationTranslate5); animationTranslate6=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation6); animationTranslate6.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(190, 660, 0, 0); buttonCamera.setLayoutParams(params); buttonCamera.clearAnimation(); } }); buttonCamera.startAnimation(animationTranslate6); }else{ isClick=false; animationRotate2=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.rotate_animation2); buttonDelete.startAnimation(animationRotate2); animationTranslate1=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation7); animationTranslate1.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(10, 790, 0, 0); buttonSleep.setLayoutParams(params); buttonSleep.clearAnimation(); } }); buttonSleep.startAnimation(animationTranslate1); animationTranslate2=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation8); animationTranslate2.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(10, 790, 0, 0); buttonThought.setLayoutParams(params); buttonThought.clearAnimation(); } }); buttonThought.startAnimation(animationTranslate2); animationTranslate3=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation9); animationTranslate3.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(10, 790, 0, 0); buttonMusic.setLayoutParams(params); buttonMusic.clearAnimation(); } }); buttonMusic.startAnimation(animationTranslate3); animationTranslate4=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation10); animationTranslate4.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(10, 790, 0, 0); buttonPlace.setLayoutParams(params); buttonPlace.clearAnimation(); } }); buttonPlace.startAnimation(animationTranslate4); animationTranslate5=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation11); animationTranslate5.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(10, 790, 0, 0); buttonWith.setLayoutParams(params); buttonWith.clearAnimation(); } }); buttonWith.startAnimation(animationTranslate5); animationTranslate6=AnimationUtils.loadAnimation(ImitatePatn.this, R.anim.translate_animation12); animationTranslate6.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(10, 790, 0, 0); buttonCamera.setLayoutParams(params); buttonCamera.clearAnimation(); } }); buttonCamera.startAnimation(animationTranslate6); } } }); buttonSleep.setOnClickListener(new OnClickListener() { public void onClick(View v) { buttonSleep.startAnimation(animationScale1); buttonPlace.startAnimation(animationScale2); buttonWith.startAnimation(animationScale2); buttonCamera.startAnimation(animationScale2); buttonMusic.startAnimation(animationScale2); buttonThought.startAnimation(animationScale2); buttonDelete.startAnimation(animationScale2); } }); buttonThought.setOnClickListener(new OnClickListener() { public void onClick(View v) { buttonThought.startAnimation(animationScale1); buttonSleep.startAnimation(animationScale2); buttonPlace.startAnimation(animationScale2); buttonWith.startAnimation(animationScale2); buttonCamera.startAnimation(animationScale2); buttonMusic.startAnimation(animationScale2); buttonDelete.startAnimation(animationScale2); } }); buttonMusic.setOnClickListener(new OnClickListener() { public void onClick(View v) { buttonMusic.startAnimation(animationScale1); buttonThought.startAnimation(animationScale2); buttonSleep.startAnimation(animationScale2); buttonPlace.startAnimation(animationScale2); buttonWith.startAnimation(animationScale2); buttonCamera.startAnimation(animationScale2); buttonDelete.startAnimation(animationScale2); } }); buttonPlace.setOnClickListener(new OnClickListener() { public void onClick(View v) { buttonPlace.startAnimation(animationScale1); buttonMusic.startAnimation(animationScale2); buttonThought.startAnimation(animationScale2); buttonSleep.startAnimation(animationScale2); buttonWith.startAnimation(animationScale2); buttonCamera.startAnimation(animationScale2); buttonDelete.startAnimation(animationScale2); } }); buttonWith.setOnClickListener(new OnClickListener() { public void onClick(View v) { buttonWith.startAnimation(animationScale1); buttonPlace.startAnimation(animationScale2); buttonMusic.startAnimation(animationScale2); buttonThought.startAnimation(animationScale2); buttonSleep.startAnimation(animationScale2); buttonCamera.startAnimation(animationScale2); buttonDelete.startAnimation(animationScale2); } }); buttonCamera.setOnClickListener(new OnClickListener() { public void onClick(View v) { buttonCamera.startAnimation(animationScale1); buttonWith.startAnimation(animationScale2); buttonPlace.startAnimation(animationScale2); buttonMusic.startAnimation(animationScale2); buttonThought.startAnimation(animationScale2); buttonSleep.startAnimation(animationScale2); buttonDelete.startAnimation(animationScale2); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_imitate_patn, menu); return true; } }布局文件是:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:background="#ffffff"> <Button android:id="@+id/button_composer_sleep" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/composer_sleep" android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:layout_alignParentBottom="true"> </Button> <Button android:id="@+id/button_composer_thought" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/composer_thought" android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:layout_alignParentBottom="true" android:layout_above="@id/button_composer_sleep"> </Button> <Button android:id="@+id/button_composer_music" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/composer_music" android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:layout_alignParentBottom="true"> </Button> <Button android:id="@+id/button_composer_place" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/composer_place" android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:layout_alignParentBottom="true" android:layout_above="@id/button_composer_music"> </Button> <Button android:id="@+id/button_composer_with" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/composer_with" android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:layout_alignParentBottom="true" android:layout_above="@id/button_composer_place"> </Button> <Button android:id="@+id/button_composer_camera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/composer_camera" android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:layout_alignParentBottom="true" android:layout_above="@id/button_composer_with"> </Button> <Button android:id="@+id/button_friends_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/friends_delete" android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:layout_alignParentBottom="true" android:layout_above="@id/button_composer_camera"> </Button> </RelativeLayout>
animationTranslate2.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { params = new LayoutParams(0, 0); params.height = 50; params.width = 50; params.setMargins(10, 790, 0, 0); buttonThought.setLayoutParams(params); buttonThought.clearAnimation(); } });
标题说到了是拓展,为什么呢,就是我们这个菜单可以放到其他的地方,可以做一个想ppt动画那样从上到下,淡入淡出等等的效果。实现原理和上面是一样的,大家可以发挥想象力,做出漂亮美观的程序。现在很多程序基本上都是静态的,我们可以像path这样,另辟蹊径,开启动态程序的大门,让我们的程序动起来!
下载地址