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(<span class="s1">mCurrentScreen</span>).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);
- }
- }