zoukankan      html  css  js  c++  java
  • 【特效】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

  • 相关阅读:
    《TCP/IP 详解 卷1:协议》第 10 章:用户数据报协议
    《TCP/IP 详解 卷1:协议》第 9 章:广播和本地组播(IGMP 和 MLD)
    在新的电脑上部署 Hexo,保留原有博客的方法
    当你不知道变量类型的完整定义时可以采取的操作
    python learning GUI
    python learning Network Programming.py
    python learning Process and Thread.py
    【2017级面向对象程序设计】第2次成绩排行
    python learning IO.py
    python learning Exception & Debug.py
  • 原文地址:https://www.cnblogs.com/androidsj/p/3119431.html
Copyright © 2011-2022 走看看