android 简易3d菜单(伪3d)


转载请注明出处:(http://blog.csdn.net/qq_35071078/article/details/53158376














本人学android也有几个月了,最近开始了我的第一个项目,由于项目需要,要实现一个类似于这种的3d菜单,可以滑动。对于一个菜鸟来说,想实现这种效果肯定很难啊,所以就想在网上找源码来学习一下。可是啊,这个东西真的不好找啊,找了几天,在各个android论坛上都发了帖子,基本上没人告诉我准确的解决方法,但是基本上就这三个方向:3d画廊、Rotate3dAnimation、opengl。可以,那就先看下3d画廊吧,看了之后发现网上各种各样的关于3d画廊的帖子,但是根本就不是我想要的效果,我要的是整体的3d效果,可以旋转的。然后又看Rotate3dAnimation,试了很久,发现它只能绕某个坐标轴进行旋转,不知道是不是我没弄懂,毕竟这里面包含了Camera还有Matrix,还要涉及到矩阵的运算,我的天,pass掉。最后又看了两天opengl,好了可以直接pass掉了(具体原因我就不说了,这个东西一两天是学不好的)。很着急啊,过了一个星期了一点进展都没有,最后听了一个网友的话,做一个伪3d算了(其实就是2d),花了半天时间写了这个东西,虽然很预期差的很远,不过看上去还是可以的。下面奉上我的代码(毕竟菜鸟,哈哈,有可能写的很糟,实现了GesturListener基本上没用),另外这只实现了基本上的旋转的效果,对于imageView的Touch事件没有做任何处理。

基本思路: 就是用了属性动画,用一个AnimatorSet来同时播放每个ImageView的动画。

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;

/**
 * Created by cx on 2016/11/10.
 */

public class My3dView extends ViewGroup implements GestureDetector.OnGestureListener{

    /**
     * 三个imageView
     */
    ImageView[] items = new ImageView[3];
    /**
     *
     */
    GestureDetector gestureDetector;
    /**
     * 动画集合
     */
    AnimatorSet animatorSet = new AnimatorSet();
    AnimatorSet animatorSetBackFirst = new AnimatorSet();
    AnimatorSet animatorSetBackSecond = new AnimatorSet();
    /**
     * 判断动画是否正在运行
     */
    boolean isAnimating = false;

    /**
     * 控件的宽和高
     */
    int mWidth;
    int mHeight;

    /**
     * 自定义的单位宽度。(为了后面方便计算控件的各个位置)
     */
    int unitWidth;

    /**
     * 当前item所在的位置
     */
    int centerItem = 1;
    int leftItem = 0;
    int rightItem = 2;

    public My3dView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setWillNotDraw(false);
        gestureDetector  = new GestureDetector(context, this);
    }

    public My3dView(Context context) {
        super(context,null);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        /**
         * 获取当前控件的宽高,并将高分为8小块(分为8小块,主要是为了方便后面对动画参数的计算)。
         */
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        unitWidth = mHeight / 8;
    }

    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        /**
         * 获取三个item
         */
        items[0] = (ImageView) getChildAt(0);
        items[1] = (ImageView) getChildAt(1);
        items[2] = (ImageView) getChildAt(2);

        /**
         * 给三个item指定初始大小
         * 左边的item和右边的item都设置alpha为0.5
         */
        items[0].layout((mWidth/2-unitWidth*8),unitWidth*1,(mWidth/2-unitWidth*4),unitWidth*5);
        items[0].setAlpha(0.5f);

        items[1].layout((mWidth-unitWidth*4)/2,unitWidth*4,(mWidth/2+unitWidth*2),mHeight);

        items[2].layout((mWidth/2+unitWidth*4),unitWidth*1,(mWidth/2+unitWidth*8),unitWidth*5);
        items[2].setAlpha(0.5f);
    }

    @Override
    public boolean onDown(MotionEvent motionEvent) {
        Log.e("infoo","onDown");
        return true;
    }

    @Override
    public void onShowPress(MotionEvent motionEvent) {
        Log.e("infoo","onShowPress");
    }

    @Override
    public boolean onSingleTapUp(MotionEvent motionEvent) {
        Log.e("infoo","onSingleTapUp");
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
        Log.e("infoo","onScroll    motionX = "+motionEvent.getX()+"  motion1X=="+motionEvent1.getX());
        return false;
    }

    @Override
    public void onLongPress(MotionEvent motionEvent) {
        Log.e("infoo","onLongPress");
    }

    @Override
    public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
        Log.e("infoo","onFling");
        return false;
    }

/*    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        getParent().requestDisallowInterceptTouchEvent(true); // 先告诉父Viewgroup,不要拦截我我
        gestureDetector.onTouchEvent(ev); // 通过GestureDetector将MotionEvent事件交给监听器OnGestureListener
        return super.dispatchTouchEvent(ev);
    }*/

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            /**
             * 判断当前动画是否正在执行
             */
            if (!isAnimating){
                animatorSet.removeAllListeners();
                animatorSetBackFirst = new AnimatorSet();
                animatorSetBackSecond = new AnimatorSet();

                /**
                 * 计算当前的三个item各在什么位置
                 */
                if(centerItem == 0){
                    leftItem = 2;
                    rightItem = 1;
                }else{
                    leftItem = (centerItem-1)>=0?(centerItem-1):2;
                    rightItem = (centerItem-2)>=0?(centerItem-2):2;
                }
                if((event.getX()<mWidth/2)&&!isAnimating){

                    /**
                     * 控制三个item的动画,包括x轴平移,y轴平移,alpha动画
                     */
                    ObjectAnimator ob_center = new ObjectAnimator().ofFloat(items[centerItem],"x",(mWidth-unitWidth*4)/2,(mWidth/2+unitWidth*4));
                    ObjectAnimator ob_center2 = new ObjectAnimator().ofFloat(items[centerItem],"y",unitWidth*4,unitWidth*1);
                    ObjectAnimator ob_center3 = new ObjectAnimator().ofFloat(items[centerItem],"alpha",1.0f,0.5f);
                    ob_center.setInterpolator(new DecelerateInterpolator());

                    ObjectAnimator ob_left = new ObjectAnimator().ofFloat(items[leftItem],"x",(mWidth/2-unitWidth*8),(mWidth-unitWidth*4)/2);
                    ObjectAnimator ob_left2 = new ObjectAnimator().ofFloat(items[leftItem],"y",unitWidth*1,unitWidth*4);
                    ObjectAnimator ob_left3 = new ObjectAnimator().ofFloat(items[leftItem],"alpha",0.5f,1.0f);
                    ob_left2.setInterpolator(new DecelerateInterpolator());

                    ObjectAnimator ob_right = new ObjectAnimator().ofFloat(items[rightItem],"x",(mWidth/2+unitWidth*4),(mWidth-unitWidth*4)/2);
                    ObjectAnimator ob_right2 = new ObjectAnimator().ofFloat(items[rightItem],"y",unitWidth*1,-unitWidth);
                    ObjectAnimator ob_right3 = new ObjectAnimator().ofFloat(items[rightItem],"alpha",0.5f,0.5f);
                    ob_right.setInterpolator(new AccelerateInterpolator());

                    ObjectAnimator ob_back = new ObjectAnimator().ofFloat(items[rightItem],"x",(mWidth-unitWidth*4)/2,(mWidth/2-unitWidth*8));
                    ObjectAnimator ob_back2 = new ObjectAnimator().ofFloat(items[rightItem],"y",-unitWidth,unitWidth*1);
                    ObjectAnimator ob_back3 = new ObjectAnimator().ofFloat(items[rightItem],"alpha",0.5f,0.5f);
                    ob_back.setInterpolator(new DecelerateInterpolator());

                    animatorSetBackSecond.playTogether(ob_back,ob_back2,ob_back3);
                    animatorSetBackSecond.setDuration(500);
                    animatorSetBackFirst.playTogether(ob_right,ob_right2,ob_right3);
                    animatorSetBackFirst.setDuration(500);
                    animatorSetBackFirst.addListener(new Animator.AnimatorListener() {
                        @Override
                        public void onAnimationStart(Animator animator) {

                        }

                        @Override
                        public void onAnimationEnd(Animator animator) {
                            animatorSetBackSecond.start();
                        }

                        @Override
                        public void onAnimationCancel(Animator animator) {

                        }

                        @Override
                        public void onAnimationRepeat(Animator animator) {

                        }
                    });


                    animatorSet.playTogether(ob_center,ob_center2,ob_center3,ob_left,ob_left2,ob_left3);
                    /**
                     * 给animatorSet指定Interpolator
                     */
                    //animatorSet.setInterpolator(new DecelerateInterpolator());
                    animatorSet.setDuration(1000);

                    /**
                     * 给animatorSet添加监听器
                     */
                    animatorSet.addListener(new Animator.AnimatorListener() {
                        @Override
                        public void onAnimationStart(Animator animator) {
                            animatorSetBackFirst.start();
                            isAnimating = true;
                        }

                        @Override
                        public void onAnimationEnd(Animator animator) {
                            centerItem = ((centerItem-1)>=0?(centerItem-1):2);
                            isAnimating = false;
                        }

                        @Override
                        public void onAnimationCancel(Animator animator) {

                        }

                        @Override
                        public void onAnimationRepeat(Animator animator) {

                        }

                    });
                    animatorSet.start();
                }else if((event.getX()>mWidth/2)&&!isAnimating){
                   // animatorSet.removeAllListeners();
                    /**
                     * 控制三个item的动画,包括x轴平移,y轴平移,alpha动画
                     */
                    ObjectAnimator ob_center = new ObjectAnimator().ofFloat(items[centerItem],"x",(mWidth-unitWidth*4)/2,(mWidth/2-unitWidth*8));
                    ObjectAnimator ob_center2 = new ObjectAnimator().ofFloat(items[centerItem],"y",unitWidth*4,unitWidth*1);
                    ObjectAnimator ob_center3 = new ObjectAnimator().ofFloat(items[centerItem],"alpha",1.0f,0.5f);
                    ob_center.setInterpolator(new DecelerateInterpolator());

                    ObjectAnimator ob_left = new ObjectAnimator().ofFloat(items[leftItem],"x",(mWidth/2-unitWidth*8),(mWidth-unitWidth*4)/2);
                    ObjectAnimator ob_left2 = new ObjectAnimator().ofFloat(items[leftItem],"y",unitWidth*1,-unitWidth);
                    ObjectAnimator ob_left3 = new ObjectAnimator().ofFloat(items[leftItem],"alpha",0.5f,0.5f);
                    ob_left.setInterpolator(new AccelerateInterpolator());

                    ObjectAnimator ob_right = new ObjectAnimator().ofFloat(items[rightItem],"x",(mWidth/2+unitWidth*4),(mWidth-unitWidth*4)/2);
                    ObjectAnimator ob_right2 = new ObjectAnimator().ofFloat(items[rightItem],"y",unitWidth*1,unitWidth*4);
                    ObjectAnimator ob_right3 = new ObjectAnimator().ofFloat(items[rightItem],"alpha",0.5f,1.0f);
                    ob_right2.setInterpolator(new DecelerateInterpolator());

                    ObjectAnimator ob_back = new ObjectAnimator().ofFloat(items[leftItem],"x",(mWidth-unitWidth*4)/2,(mWidth/2+unitWidth*4));
                    ObjectAnimator ob_back2 = new ObjectAnimator().ofFloat(items[leftItem],"y",-unitWidth,unitWidth*1);
                    ObjectAnimator ob_back3 = new ObjectAnimator().ofFloat(items[leftItem],"alpha",0.5f,0.5f);
                    ob_back.setInterpolator(new DecelerateInterpolator());

                    animatorSetBackSecond.playTogether(ob_back,ob_back2,ob_back3);
                    animatorSetBackSecond.setDuration(500);
                    animatorSetBackFirst.playTogether(ob_left,ob_left2,ob_left3);
                    animatorSetBackFirst.setDuration(500);
                    animatorSetBackFirst.addListener(new Animator.AnimatorListener() {
                        @Override
                        public void onAnimationStart(Animator animator) {

                        }

                        @Override
                        public void onAnimationEnd(Animator animator) {
                            animatorSetBackSecond.start();
                        }

                        @Override
                        public void onAnimationCancel(Animator animator) {

                        }

                        @Override
                        public void onAnimationRepeat(Animator animator) {

                        }
                    });

                    animatorSet.playTogether(ob_center,ob_center2,ob_center3,ob_right,ob_right2,ob_right3);
                    animatorSet.setDuration(1000);
                    /**
                     * 给animatorSet指定Interpolator
                     */
                   // animatorSet.setInterpolator(new DecelerateInterpolator());
                    /**
                     * 给animatorSet添加监听器
                     */
                    animatorSet.addListener(new Animator.AnimatorListener() {
                        @Override
                        public void onAnimationStart(Animator animator) {
                            isAnimating = true;
                            animatorSetBackFirst.start();
                        }

                        @Override
                        public void onAnimationEnd(Animator animator) {
                            centerItem = ((centerItem+1)<=2?(centerItem+1):0);
                            isAnimating = false;
                        }

                        @Override
                        public void onAnimationCancel(Animator animator) {

                        }

                        @Override
                        public void onAnimationRepeat(Animator animator) {

                        }
                    });
                    animatorSet.start();

                }
            }

        }
        return gestureDetector.onTouchEvent(event);
    }

使用的话直接在布局文件中引用这个自定义View,另外在子布局中添加三个imageView:

<com.example.liuzhiyang.test3d.My3dView
    android:id="@+id/id_3dView"
    android:layout_width="match_parent"
    android:layout_height="150dp">
    <ImageView
        android:src="@drawable/ic_launcher"
        android:id="@+id/id_img1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <ImageView
        android:src="@drawable/ic_launcher"
        android:id="@+id/id_img2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <ImageView
        android:src="@drawable/ic_launcher"
        android:id="@+id/id_img3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</com.example.liuzhiyang.test3d.My3dView>



  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值