【特效】3D旋转环形菜单

【特效】3D旋转环形菜单

主页面的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>
View Code

点击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>
View Code

主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);



    }

}
View Code

 

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);

        }



    }

}
View Code

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;

    }



}
View Code

 

DEMO完整下载路径:http://download.csdn.net/detail/androidsj/5525583

 

 

 

 

你可能感兴趣的:(特效)