【特效】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

更多相关文章

  1. Android Activity页面跳转动画
  2. 给Android的音量按钮添加监听事件
  3. Android 判断动画结束
  4. android 使用动画实例[1]
  5. Android 同时播放缩放动画和位移动画
  6. android PopupWindow 阴影背景 、动画 、点击显示、隐藏
  7. Android实现点赞动画(27)
  8. Android 赞一下+1动画
  9. 收藏一个 漂亮的 Android加载中动画AVLoadingIndicatorView

随机推荐

  1. Mybaitis缓存的优化
  2. 分布式系统架构常见面试知识点梳理(每次面
  3. 图解源码 | SpringBoot中自动配置原理
  4. 单例模式你会几种写法?
  5. 一步为你的Springboot应用自定义banner
  6. 工厂模式理解了没有?
  7. 你的Springboot应用到底启动了哪些bean?这
  8. 单例模式的十种写法,你会几个?
  9. 我在一个构造方法中写了30个参数,老板看了
  10. android:windowSoftInputMode属性详解以