Android Launcher桌面3D实现和原理分析


by: andy.xie   转载请注明出处 http://blog.csdn.net/xiexh0921/article/details/7929847


1,概述:

Launcher桌面由Workspace.java包含Celllayout.java构成,一个celllayout就是一个桌面,默认5个。 Workspace和celllayout都继承于viewgroup。


2,获得Touch坐标:

Launcher.java为activity,workspace是viewgroup。所以在activity中会注册一个scroller来记录滑动状态,scroller start后workspace中的computeScroll() 会接收到scroller的状态。这里获取到 mTouchX = mScrollX = mScroller.getCurrX();。Launcher会对滑动事件进行管理使得每次都能切屏或返回,而不会出现滑动到一半的状态。


3,重绘view:

scroller start的时候会不断重绘view直到scroller结束(mScroller.computeScrollOffset()返回false),所以要实现效果只需直接修改dispathDraw函数。dispathDraw和onDraw的区别是一个是画自己一个是画子view,dispathDraw在onDraw之后执行。

这里我们要实现伪3D效果,所以不用opengl,根据上面得到的mTouchX直接用camera和matrix配合就可以实现了。根据上面得到的mTouchX计算出子view需要旋转的角度,隐藏childview后,1)用drawchild画子view;2)直接抓取子view的bitmap(getChildAt(0).buildDrawingCache();Bitmap bitmap = getChildAt(0).getDrawingCache();)然后画到workspace的canvas。


4,实现代码:

上面大概的讲了下原理,下面给出实现代码,其实很简单,只需要修改Launcher2中的workspace.java就可以实现了。


@Override
    protected void dispatchDraw(Canvas canvas) {
        boolean restore = false;
        int restoreCount = 0;

        // ViewGroup.dispatchDraw() supports many features we don't need:
        // clip to padding, layout animation, animation listener, disappearing
        // children, etc. The following implementation attempts to fast-track
        // the drawing dispatch by drawing only what we know needs to be drawn.

        boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN;
        // If we are not scrolling or flinging, draw only the current screen
        if (fastDraw) {
            //add by andy.xie 20120831
            getChildAt(mCurrentScreen).setBackgroundResource(android.R.color.transparent);
            drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());
        } else {
            final long drawingTime = getDrawingTime();
            final float scrollPos = (float) mScrollX / getWidth();
            final int leftScreen = (int) scrollPos;
            final int rightScreen = leftScreen + 1;
         //edit by andy.xie 20120831
//            if (leftScreen >= 0) {
//                drawChild(canvas, getChildAt(leftScreen), drawingTime);
//            }
//            if (scrollPos != leftScreen && rightScreen < getChildCount()) {
//                drawChild(canvas, getChildAt(rightScreen), drawingTime);
//            }
            //add by andy.xie 20120831
            Camera camera = new Camera();
                Matrix matrix = new Matrix();
                int width = getWidth();
                int height = getHeight();

                float rotateY = ((float)(mTouchX % width) / width) * 90;
                if(rotateY < 0) rotateY = 0;
                if(rotateY > 90) rotateY = 90;
if(rotateY > 90) rotateY = 90;

                //
                Log.d("xxh", "x=" + mTouchX + " rotateY=" + rotateY + " scrollPos=" + scrollPos);

            if (leftScreen >= 0) {
                        //
                        canvas.save();
                        camera.save();
                        //camera.translate(0, 0, mWidth/2);
                        camera.rotateY(-rotateY);
                        camera.getMatrix(matrix);
                        camera.restore();
                        matrix.preTranslate(-width * ((int)scrollPos + 1), -height/2);
                        matrix.postTranslate(width * ((int)scrollPos + 1), height/2);
                        //
                        canvas.concat(matrix);
                getChildAt(leftScreen).setBackgroundResource(android.R.drawable.screen_background_dark_transparent);
                        drawChild(canvas, getChildAt(leftScreen), drawingTime);
getChildAt(leftScreen).setBackgroundResource(android.R.drawable.screen_background_dark_transparent);
                        drawChild(canvas, getChildAt(leftScreen), drawingTime);
                        canvas.restore();
            }


            if (scrollPos != leftScreen && rightScreen < getChildCount()) {
                Matrix matrix2 = new Matrix();
                canvas.save();
                        camera.save();
                        //camera.translate(0, 0, mWidth/2);
                        camera.rotateY(90-rotateY);
                        camera.getMatrix(matrix2);
                        camera.restore();
                        matrix2.preTranslate(-width * ((int)scrollPos + 1), -height/2);
                        matrix2.postTranslate(width * ((int)scrollPos + 1), height/2);
                        //
                        canvas.concat(matrix2);
                getChildAt(rightScreen).setBackgroundResource(android.R.drawable.screen_background_dark_transparent);
canvas.concat(matrix2);
                getChildAt(rightScreen).setBackgroundResource(android.R.drawable.screen_background_dark_transparent);
                drawChild(canvas, getChildAt(rightScreen), drawingTime);
                canvas.restore();
            }
        }

        if (restore) {
            canvas.restoreToCount(restoreCount);
        }
    }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值