主页面的xml文件
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:id="@+id/layout_next" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/user_wizard_2" android:orientation="vertical" /> <LinearLayout android:id="@+id/layout_last" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/user_wizard_3" android:orientation="vertical" /> <RelativeLayout android:id="@+id/layout_main" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/user_wizard_1" android:orientation="vertical" > <include layout="@layout/bottom_button" /> </RelativeLayout> </FrameLayout>
点击Hone按钮弹出菜单xml文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <RelativeLayout android:id="@+id/composer_buttons_wrapper" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:clipChildren="false" android:clipToPadding="false" > <ImageButton android:id="@+id/composer_button_photo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="142dp" android:layout_marginRight="10.667dp" android:background="@drawable/composer_camera" android:visibility="gone" /> <ImageButton android:id="@+id/composer_button_people" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="135.333dp" android:layout_marginRight="52dp" android:background="@drawable/composer_with" android:visibility="gone" /> <ImageButton android:id="@+id/composer_button_place" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="116.666dp" android:layout_marginRight="89.33333333333333dp" android:background="@drawable/composer_place" android:visibility="gone" /> <ImageButton android:id="@+id/composer_button_music" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="87.33333333333333dp" android:layout_marginRight="118.6666666666667dp" android:background="@drawable/composer_music" android:visibility="gone" /> <ImageButton android:id="@+id/composer_button_thought" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="50dp" android:layout_marginRight="137.3333333333333dp" android:background="@drawable/composer_thought" android:visibility="gone" /> <ImageButton android:id="@+id/composer_button_sleep" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="8.666666666666667dp" android:layout_marginRight="144dp" android:background="@drawable/composer_sleep" android:visibility="gone" /> </RelativeLayout> <RelativeLayout android:id="@+id/composer_buttons_show_hide_button" android:layout_width="60dp" android:layout_height="57.33333333333333dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:background="@drawable/composer_button" > <ImageView android:id="@+id/composer_buttons_show_hide_button_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/composer_icn_plus" /> </RelativeLayout> </RelativeLayout>
主Activity页面
package cy.test.rotate3d; import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.RelativeLayout; public class RotateActivity extends Activity implements OnTouchListener { public final static int TYPE_ROTATING = 0; public final static int TYPE_ENDROTATE = 1; public final static int TYPE_VELROTATE = 2; public static float params = 1; private ViewGroup layoutmain; private ViewGroup layoutnext; private ViewGroup layoutlast; private ViewGroup currentView; private ViewGroup nextView; private ViewGroup lastView; private Rotate3D rotate3d; private Rotate3D rotate3d2; private Rotate3D rotate3d3; private int mCenterX; private int mCenterY; private float degree = (float) 0.0; private int currentTab = 0; private float perDegree; private VelocityTracker mVelocityTracker; private boolean areButtonsShowing; private RelativeLayout composerButtonsWrapper; private ImageView composerButtonsShowHideButtonIcon; private RelativeLayout composerButtonsShowHideButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initMain(); MyAnimations.initOffset(this); // 加号的动画 composerButtonsShowHideButton.startAnimation(MyAnimations .getRotateAnimation(0, 360, 200)); DisplayMetrics dm = new DisplayMetrics(); dm = getResources().getDisplayMetrics(); mCenterX = dm.widthPixels / 2; mCenterY = dm.heightPixels / 2; if (dm.widthPixels > 320) { params = 2.0f / 3; } perDegree = (float) (90.0 / dm.widthPixels); } private void setListener() { // 给大按钮设置点击事件 composerButtonsShowHideButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { if (!areButtonsShowing) { // 图标的动画 MyAnimations.startAnimationsIn(composerButtonsWrapper, 300); // 加号的动画 composerButtonsShowHideButtonIcon .startAnimation(MyAnimations.getRotateAnimation(0, -225, 300)); } else { // 图标的动画 MyAnimations .startAnimationsOut(composerButtonsWrapper, 300); // 加号的动画 composerButtonsShowHideButtonIcon .startAnimation(MyAnimations.getRotateAnimation( -225, 0, 300)); } areButtonsShowing = !areButtonsShowing; } }); // 给小图标设置点击事件 for (int i = 0; i < composerButtonsWrapper.getChildCount(); i++) { final ImageView smallIcon = (ImageView) composerButtonsWrapper .getChildAt(i); final int position = i; smallIcon.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { // 这里写各个item的点击事件 // 1.加号按钮缩小后消失 缩小的animation // 2.其他按钮缩小后消失 缩小的animation // 3.被点击按钮放大后消失 透明度渐变 放大渐变的animation // composerButtonsShowHideButton.startAnimation(MyAnimations.getMiniAnimation(300)); if (areButtonsShowing) { composerButtonsShowHideButtonIcon .startAnimation(MyAnimations .getRotateAnimation(-225, 0, 300)); smallIcon.startAnimation(MyAnimations .getMaxAnimation(400)); for (int j = 0; j < composerButtonsWrapper .getChildCount(); j++) { if (j != position) { final ImageView smallIcon = (ImageView) composerButtonsWrapper .getChildAt(j); smallIcon.startAnimation(MyAnimations .getMiniAnimation(300)); // MyAnimations.getMiniAnimation(300).setFillAfter(true); } } areButtonsShowing = !areButtonsShowing; } } }); } } private void initMain() { setContentView(R.layout.main); composerButtonsWrapper = (RelativeLayout) findViewById(R.id.composer_buttons_wrapper); composerButtonsShowHideButton = (RelativeLayout) findViewById(R.id.composer_buttons_show_hide_button); composerButtonsShowHideButtonIcon = (ImageView) findViewById(R.id.composer_buttons_show_hide_button_icon); layoutnext = (ViewGroup) findViewById(R.id.layout_next); layoutnext.setOnTouchListener(this); layoutlast = (ViewGroup) findViewById(R.id.layout_last); layoutlast.setOnTouchListener(this); layoutmain = (ViewGroup) findViewById(R.id.layout_main); layoutmain.setOnTouchListener(this); setListener(); currentView = layoutmain; nextView = layoutnext; lastView = layoutnext; } private int mLastMotionX; public boolean onTouch(View arg0, MotionEvent event) { int x = (int) event.getX(); if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain();// 获得VelocityTracker类实例 } mVelocityTracker.addMovement(event);// 将事件加入到VelocityTracker类实例中 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastMotionX = x; break; case MotionEvent.ACTION_MOVE: mVelocityTracker.computeCurrentVelocity(1000, 1000); int dx = x - mLastMotionX; if (dx != 0) { doRotate(dx, TYPE_ROTATING); if (degree > 90) { degree = 0; break; } } else { return false; } mLastMotionX = x; break; case MotionEvent.ACTION_UP: // 设置units的值为1000,意思为一秒时间内运动了多少个像素 mVelocityTracker.computeCurrentVelocity(1000); float VelocityX = mVelocityTracker.getXVelocity(); if (VelocityX > 500 || VelocityX < -500) { // endRotateByVelocity(); doRotate(0, TYPE_VELROTATE); } else { // endRotate(); doRotate(0, TYPE_ENDROTATE); } setView(); setViewVisibile(); degree = 0; releaseVelocityTracker(); break; case MotionEvent.ACTION_CANCEL: releaseVelocityTracker(); break; } return true; } private void setView() { if (currentTab == 0) { currentView = layoutmain; nextView = layoutnext; lastView = layoutlast; } else if (currentTab == 1) { currentView = layoutnext; nextView = layoutlast; lastView = layoutmain; } else if (currentTab == 2) { currentView = layoutlast; nextView = layoutmain; lastView = layoutnext; } } private void releaseVelocityTracker() { if (null != mVelocityTracker) { mVelocityTracker.clear(); mVelocityTracker.recycle(); mVelocityTracker = null; } } private void setViewVisibile() { if (currentTab == 0) { layoutmain.setVisibility(View.VISIBLE); layoutnext.setVisibility(View.GONE); layoutlast.setVisibility(View.GONE); } else if (currentTab == 1) { layoutmain.setVisibility(View.GONE); layoutnext.setVisibility(View.VISIBLE); layoutlast.setVisibility(View.GONE); } else if (currentTab == 2) { layoutmain.setVisibility(View.GONE); layoutnext.setVisibility(View.GONE); layoutlast.setVisibility(View.VISIBLE); } } private void doRotate(int dx, int type) { if (type == TYPE_ROTATING) { float xd = degree; degree += perDegree * dx; rotate3d = new Rotate3D(xd, degree, 0, mCenterX, mCenterY); rotate3d2 = new Rotate3D(90 + xd, 90 + degree, 0, mCenterX, mCenterY); rotate3d3 = new Rotate3D(-90 + xd, -90 + degree, 0, mCenterX, mCenterY); } else if (type == TYPE_ENDROTATE) { rotate3d2 = new Rotate3D(90 + degree, 0, 0, mCenterX, mCenterY); rotate3d3 = new Rotate3D(-90 + degree, 0, 0, mCenterX, mCenterY); if (degree > 45) { rotate3d = new Rotate3D(degree, 90, 0, mCenterX, mCenterY); currentTab = (currentTab - 1) % 3; if (currentTab < 0) { currentTab = 2; } } else if (degree < -45) { rotate3d = new Rotate3D(degree, -90, 0, mCenterX, mCenterY); currentTab = (currentTab + 1) % 3; } else { rotate3d = new Rotate3D(degree, 0, 0, mCenterX, mCenterY); rotate3d2 = new Rotate3D(90 + degree, 90, 0, mCenterX, mCenterY); rotate3d3 = new Rotate3D(-90 + degree, -90, 0, mCenterX, mCenterY); } } else if (type == TYPE_VELROTATE) { if (degree > 0) { rotate3d = new Rotate3D(degree, 90, 0, mCenterX, mCenterY); rotate3d3 = new Rotate3D(-90 + degree, 0, 0, mCenterX, mCenterY); currentTab = (currentTab - 1) % 3; if (currentTab < 0) { currentTab = 2; } } else if (degree < 0) { rotate3d = new Rotate3D(degree, -90, 0, mCenterX, mCenterY); rotate3d2 = new Rotate3D(90 + degree, 0, 0, mCenterX, mCenterY); currentTab = (currentTab + 1) % 3; } } rotate3d.setDuration(300); rotate3d2.setDuration(300); rotate3d3.setDuration(300); layoutmain.setVisibility(View.GONE); layoutnext.setVisibility(View.GONE); layoutlast.setVisibility(View.GONE); currentView.setVisibility(View.VISIBLE); if (degree < 0) {// 由右向左滑 nextView.setVisibility(View.VISIBLE); toDoAnimation(currentView, rotate3d, Rotate3D.BOUNDARY_RIGHT); toDoAnimation(nextView, rotate3d2, Rotate3D.BOUNDARY_LEFT); } else if (degree > 0) { lastView.setVisibility(View.VISIBLE); toDoAnimation(currentView, rotate3d, Rotate3D.BOUNDARY_LEFT); toDoAnimation(lastView, rotate3d3, Rotate3D.BOUNDARY_RIGHT); } } public void toDoAnimation(ViewGroup viewGroup, Rotate3D rotate3d, int type) { rotate3d.setType(type); viewGroup.startAnimation(rotate3d); } }
Rotate3D.java
package cy.test.rotate3d; import android.graphics.Camera; import android.graphics.Matrix; import android.view.animation.Animation; import android.view.animation.Transformation; public class Rotate3D extends Animation { public final static int BOUNDARY_LEFT = 0; public final static int BOUNDARY_RIGHT = 1; private int type; private float fromDegree; // 旋转起始角度 private float toDegree; // 旋转终止角度 private float mCenterX; // 旋转中心x private float mCenterY; // 旋转中心y private Camera mCamera; public void setType(int type) { this.type = type; } public Rotate3D(float fromDegree, float toDegree, float depthZ, float centerX, float centerY) { this.fromDegree = fromDegree; this.toDegree = toDegree; this.mCenterX = centerX; this.mCenterY = centerY; } public Rotate3D(float fromDegree, float toDegree, float depthZ, float centerX, float centerY, int type) { this.fromDegree = fromDegree; this.toDegree = toDegree; this.mCenterX = centerX; this.mCenterY = centerY; this.type = type; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final float FromDegree = fromDegree; // 旋转角度(angle) float degrees = FromDegree + (toDegree - fromDegree) * interpolatedTime; final float centerX = mCenterX; final float centerY = mCenterY; final Matrix matrix = t.getMatrix(); if (degrees <= -79.5f) { degrees = -90.0f; mCamera.save(); mCamera.rotateY(degrees); // 旋转 mCamera.getMatrix(matrix); mCamera.restore(); } else if (degrees >= 79.5f) { degrees = 90.0f; mCamera.save(); mCamera.rotateY(degrees); mCamera.getMatrix(matrix); mCamera.restore(); } else { mCamera.save(); mCamera.translate(degrees / 90 * centerX * 2, 0, 0); mCamera.rotateY(degrees * RotateActivity.params); // mCamera.translate(0, 0, centerX); // 位移x // mCamera.rotateY(degrees); // mCamera.translate(0, 0, -centerX); mCamera.getMatrix(matrix); mCamera.restore(); } if (type == BOUNDARY_LEFT) { matrix.preTranslate(0, -centerY); matrix.postTranslate(0, centerY); } else { matrix.preTranslate(-centerX * 2, -centerY); matrix.postTranslate(centerX * 2, centerY); } } }
MyAnimations.java
package cy.test.rotate3d; import android.content.Context; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.OvershootInterpolator; import android.view.animation.RotateAnimation; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; import android.widget.ImageButton; public class MyAnimations { // 用来适配不同的分辨率 private static int xOffset = 15; private static int yOffset = -13; public static void initOffset(Context context) { xOffset = (int) (10.667 * context.getResources().getDisplayMetrics().density); yOffset = -(int) (8.667 * context.getResources().getDisplayMetrics().density); } // 加号的动画 public static Animation getRotateAnimation(float fromDegrees, float toDegrees, int durationMillis) { RotateAnimation rotate = new RotateAnimation(fromDegrees, toDegrees, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(durationMillis); rotate.setFillAfter(true); return rotate; } // 图标的动画(入动画) public static void startAnimationsIn(ViewGroup viewgroup, int durationMillis) { for (int i = 0; i < viewgroup.getChildCount(); i++) { ImageButton inoutimagebutton = (ImageButton) viewgroup .getChildAt(i); inoutimagebutton.setVisibility(0); inoutimagebutton.setClickable(true); inoutimagebutton.setFocusable(true); MarginLayoutParams mlp = (MarginLayoutParams) inoutimagebutton .getLayoutParams(); Animation animation = new TranslateAnimation(mlp.rightMargin - xOffset, 0F, yOffset + mlp.bottomMargin, 0F); animation.setFillAfter(true); animation.setDuration(durationMillis); // 下一个动画的偏移时间 animation.setStartOffset((i * 100) / (-1 + viewgroup.getChildCount())); // 动画的效果 animation.setInterpolator(new OvershootInterpolator(2F)); // 弹出再回来的效果 inoutimagebutton.startAnimation(animation); } } // 图标的动画(出动画) public static void startAnimationsOut(ViewGroup viewgroup, int durationMillis) { for (int i = 0; i < viewgroup.getChildCount(); i++) { final ImageButton inoutimagebutton = (ImageButton) viewgroup .getChildAt(i); MarginLayoutParams mlp = (MarginLayoutParams) inoutimagebutton .getLayoutParams(); Animation animation = new TranslateAnimation(0F, mlp.rightMargin - xOffset, 0F, yOffset + mlp.bottomMargin); animation.setFillAfter(true); animation.setDuration(durationMillis); animation.setStartOffset(((viewgroup.getChildCount() - i) * 100) / (-1 + viewgroup.getChildCount()));// 下一个动画的偏移时间 animation.setAnimationListener(new Animation.AnimationListener() { public void onAnimationStart(Animation arg0) { } public void onAnimationRepeat(Animation arg0) { } public void onAnimationEnd(Animation arg0) { inoutimagebutton.setVisibility(8); inoutimagebutton.setClickable(false); inoutimagebutton.setFocusable(false); } }); inoutimagebutton.startAnimation(animation); } } // icon缩小消失的动画 public static Animation getMiniAnimation(int durationMillis) { Animation miniAnimation = new ScaleAnimation(1.0f, 0f, 1.0f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); miniAnimation.setDuration(durationMillis); miniAnimation.setFillAfter(true); return miniAnimation; } // icon放大渐变消失的动画 public static Animation getMaxAnimation(int durationMillis) { AnimationSet animationset = new AnimationSet(true); Animation maxAnimation = new ScaleAnimation(1.0f, 4.0f, 1.0f, 4.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); Animation alphaAnimation = new AlphaAnimation(1, 0); animationset.addAnimation(maxAnimation); animationset.addAnimation(alphaAnimation); animationset.setDuration(durationMillis); animationset.setFillAfter(true); return animationset; } }
DEMO完整下载路径:http://download.csdn.net/detail/androidsj/5525583