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
4,实现代码:
上面大概的讲了下原理,下面给出实现代码,其实很简单,只需要修改Launcher2中的workspace.java就可以实现了。
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. 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. new Camera();
31. 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. "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. int)scrollPos + 1), -height/2);
52. 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. new Matrix();
65. canvas.save();
66. camera.save();
67. //camera.translate(0, 0, mWidth/2);
68. 90-rotateY);
69. camera.getMatrix(matrix2);
70. camera.restore();
71. int)scrollPos + 1), -height/2);
72. 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. }