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

272 篇文章 0 订阅

 

 

 

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就可以实现了。

 

 

[java]  view plain copy
 
  1. @Override  
  2.     protected void dispatchDraw(Canvas canvas) {  
  3.         boolean restore = false;  
  4.         int restoreCount = 0;  
  5.   
  6.         // ViewGroup.dispatchDraw() supports many features we don't need:  
  7.         // clip to padding, layout animation, animation listener, disappearing  
  8.         // children, etc. The following implementation attempts to fast-track  
  9.         // the drawing dispatch by drawing only what we know needs to be drawn.  
  10.   
  11.         boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN;  
  12.         // If we are not scrolling or flinging, draw only the current screen  
  13.         if (fastDraw) {  
  14.             //add by andy.xie 20120831  
  15.             getChildAt(<span class="s1">mCurrentScreen</span>).setBackgroundResource(android.R.color.transparent);  
  16.             drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());  
  17.         } else {  
  18.             final long drawingTime = getDrawingTime();  
  19.             final float scrollPos = (float) mScrollX / getWidth();  
  20.             final int leftScreen = (int) scrollPos;  
  21.             final int rightScreen = leftScreen + 1;  
  22.          //edit by andy.xie 20120831  
  23. //            if (leftScreen >= 0) {  
  24. //                drawChild(canvas, getChildAt(leftScreen), drawingTime);  
  25. //            }  
  26. //            if (scrollPos != leftScreen && rightScreen < getChildCount()) {  
  27. //                drawChild(canvas, getChildAt(rightScreen), drawingTime);  
  28. //            }  
  29.             //add by andy.xie 20120831  
  30.             Camera camera = new Camera();  
  31.                 Matrix matrix = new Matrix();  
  32.                 int width = getWidth();  
  33.                 int height = getHeight();  
  34.   
  35.                 float rotateY = ((float)(mTouchX % width) / width) * 90;  
  36.                 if(rotateY < 0) rotateY = 0;  
  37.                 if(rotateY > 90) rotateY = 90;  
  38. if(rotateY > 90) rotateY = 90;  
  39.   
  40.                 //  
  41.                 Log.d("xxh""x=" + mTouchX + " rotateY=" + rotateY + " scrollPos=" + scrollPos);  
  42.   
  43.             if (leftScreen >= 0) {  
  44.                         //  
  45.                         canvas.save();  
  46.                         camera.save();  
  47.                         //camera.translate(0, 0, mWidth/2);  
  48.                         camera.rotateY(-rotateY);  
  49.                         camera.getMatrix(matrix);  
  50.                         camera.restore();  
  51.                         matrix.preTranslate(-width * ((int)scrollPos + 1), -height/2);  
  52.                         matrix.postTranslate(width * ((int)scrollPos + 1), height/2);  
  53.                         //  
  54.                         canvas.concat(matrix);  
  55.                 getChildAt(leftScreen).setBackgroundResource(android.R.drawable.screen_background_dark_transparent);  
  56.                         drawChild(canvas, getChildAt(leftScreen), drawingTime);  
  57. getChildAt(leftScreen).setBackgroundResource(android.R.drawable.screen_background_dark_transparent);  
  58.                         drawChild(canvas, getChildAt(leftScreen), drawingTime);  
  59.                         canvas.restore();  
  60.             }  
  61.   
  62.   
  63.             if (scrollPos != leftScreen && rightScreen < getChildCount()) {  
  64.                 Matrix matrix2 = new Matrix();  
  65.                 canvas.save();  
  66.                         camera.save();  
  67.                         //camera.translate(0, 0, mWidth/2);  
  68.                         camera.rotateY(90-rotateY);  
  69.                         camera.getMatrix(matrix2);  
  70.                         camera.restore();  
  71.                         matrix2.preTranslate(-width * ((int)scrollPos + 1), -height/2);  
  72.                         matrix2.postTranslate(width * ((int)scrollPos + 1), height/2);  
  73.                         //  
  74.                         canvas.concat(matrix2);  
  75.                 getChildAt(rightScreen).setBackgroundResource(android.R.drawable.screen_background_dark_transparent);  
  76. canvas.concat(matrix2);  
  77.                 getChildAt(rightScreen).setBackgroundResource(android.R.drawable.screen_background_dark_transparent);  
  78.                 drawChild(canvas, getChildAt(rightScreen), drawingTime);  
  79.                 canvas.restore();  
  80.             }  
  81.         }  
  82.   
  83.         if (restore) {  
  84.             canvas.restoreToCount(restoreCount);  
  85.         }  
  86.     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值