`
ishelf
  • 浏览: 107200 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Launcher 桌面的3D转屏效果实现(2)- Camera rotate

 
阅读更多

上篇主要是通过人工方式给出所要变形的matrix,而这篇则借助于camera进行变换得到matrix直接应用到cellLayout中去,不多说了直接代码带解释

    转载请注明http://ishelf.iteye.com/admin/blogs/836955

 

    @Override


    public void dispatchDraw(Canvas canvas) {
        long start_time = System.currentTimeMillis();
        startRotate(canvas, currentX, canvas.getWidth(), canvas.getHeight());
        super.dispatchDraw(canvas);
        canvas.restore();
        long end_time = System.currentTimeMillis();
        Log.d("CellLayout" + currentScrenn, (end_time - start_time) + " ms");
    }





    public void startRotate(Canvas mCanvas, float xCor, int width, int height) {
        boolean flag = true;
        if (isCurrentScrenn && xCor < 0) {
            xCor = width + xCor;
            flag = false;
        } else if (isCurrentScrenn && xCor >= 0) {
            // xCor = width - xCor;
        } else if (!isCurrentScrenn && xCor < 0) {
            xCor = width + xCor;
        } else if (!isCurrentScrenn && xCor >= 0) {
            flag = false;
        }
        if (xCor <= 0) {
            xCor = 10;
        }// the maximum left
        if (xCor > width) {
            xCor = width - 10;
        }// the maximum right
        float angle = 0;
        if (isBorder) {
            doDraw(mCanvas, width, height, angle, xCor);
        } else if (!flag) {
            angle = 90.0f - (xCor / (float) width) * 90.0f;
            doDraw(mCanvas, width, height, angle, xCor);
        } else {
            angle = -(xCor / (float) width) * 90.00f;
            doDraw(mCanvas, width, height, angle, xCor);
        }
    }

    private void doDraw(Canvas canvas, float width, float height, float angle, float cor) {
        canvas.save();
        mCamera.save();
        mCamera.rotateY(angle);
        mCamera.getMatrix(mMatrix);
        mCamera.restore();
        // Log.w("CellLayout" + currentScrenn, angle + " __  " + mMatrix);
        if (angle < 0) {
            mMatrix.preTranslate(-width, -height * 0.5f);
            mMatrix.postTranslate(width, height * 0.5f);
        } else {
            mMatrix.preTranslate(0f, -height * 0.5f);
            mMatrix.postTranslate(0f, height * 0.5f);
        }
       canvas.concat(mMatrix);
        switch (currentScrenn) {
            case 0:
                mPaint.setColor(Color.RED);
                break;
            case 1:
                mPaint.setColor(Color.BLUE);
                break;
            case 2:
                mPaint.setColor(Color.YELLOW);
                break;
            case 3:
                mPaint.setColor(Color.CYAN);
                break;
            case 4:
                mPaint.setColor(Color.GREEN);
                break;
        }

       mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.drawRect(0, 0, width, height, mPaint);
    }


 

 

    workspace的变化如上篇一样,这里就是引进了一个camera通过它进行变换绕Y轴的旋转变换并得到其matrix就可以了。camera使用了opengl的变化操作,所要控制效果要比人为控制matrix好些,但总体显示效果差不多。

     从效率上将,如果机器支持3D加速,其速度要比2D快,不过差别也不是很大,本文做了以下一个比较

 

log-0-2D.txt  18.291666
log-0-3D.txt  7.9088144
log-1-2D.txt  22.92562
log-1-3D.txt  22.818924
log-2-2D.txt  29.503529
log-2-3D.txt  27.178694

 

     每一行的数值表示canvas画图的时间,单位为毫秒,测试数据的平均执行次数在1000次左右,文件名中的0表示第1屏,2表示第二屏。从上面的数据可以看出,基本上相差不大,人工基本上感觉不出来。之所以第一屏差距有些大可能是因为第一屏有左边界。补充下测试的机器是真机, 大家以后来去数码市场悄悄 O(∩_∩)O哈哈~

      以上只是demo,供以学习和讨论。欢迎大家给以指正

 

 

2
0
分享到:
评论
11 楼 烧伤的火柴 2012-02-08  
不错,谢谢分享!
10 楼 yangzhihui_1171 2011-07-15  
    void moveToDefaultScreen(boolean animate) {
    Log.d(TAG, "moveToDefaultScreen");
        if (animate) {
            snapToScreen(mDefaultScreen);
        } else {
            setCurrentScreen(mDefaultScreen);
        }
        getChildAt(mDefaultScreen).requestFocus();
    }

    void setIndicators(Drawable previous, Drawable next) {
        mPreviousIndicator = previous;
        mNextIndicator = next;
        previous.setLevel(mCurrentScreen);
        next.setLevel(mCurrentScreen);
    }

    public static class SavedState extends BaseSavedState {
        int currentScreen = -1;

        SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            currentScreen = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(currentScreen);
        }

        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }
   
    //------------------------------
    public void calculateRotate(){
Log.d(TAG,"calculateRotate");
    if(flag){
    //get the start drag point
    flag=false;
    //when start drag, only set the backgound one time
    wallpaperDrawable = mWallpaperManager.getFastDrawable();
getChildAt(0).setBackgroundDrawable(wallpaperDrawable);
getChildAt(1).setBackgroundDrawable(wallpaperDrawable);
getChildAt(2).setBackgroundDrawable(wallpaperDrawable);
getChildAt(3).setBackgroundDrawable(wallpaperDrawable);
getChildAt(4).setBackgroundDrawable(wallpaperDrawable);

for(int i = 0; i < 5; i++){
    getChildAt(i).buildDrawingCache();
    s[i] = getChildAt(i).getDrawingCache();
    }
    }
        //judge the direction
    if(mdirection>0){//finger move from left to right
if(flag1){
flag2=false;
if(mCurrentScreen==0){
b1=4;
b2=0;
}
if(mCurrentScreen==1){
b1=0;
b2=1;
}
if(mCurrentScreen==2){
b1=1;
b2=2;
}
if(mCurrentScreen==3){
b1=2;
b2=3;
}
if(mCurrentScreen==4){
b1=3;
b2=4;
}
}
}
if(mdirection<0){//finger move from right to left
if(flag2){
flag1=false;
if(mCurrentScreen==0){
b1=0;
b2=1;
}
if(mCurrentScreen==1){
b1=1;
b2=2;
}
if(mCurrentScreen==2){
b1=2;
b2=3;
}
if(mCurrentScreen==3){
b1=3;
b2=4;
}
if(mCurrentScreen==4){
b1=4;
b2=0;
}
}
}
        invalidate();
}
   
    public void startRotate(Canvas mCanvas,float xCor,int width,int height){
Log.d(TAG,"startRotate");

/*boolean flag = true;
    if(isCurrentScreen && xCor < 0){
    xCor = width + xCor;
    flag = false;
    }else if(isCurrentScreen && xCor >= 0){
    //xCor = width - xCor;
    }else if(!isCurrentScreen && xCor < 0){
    xCor = width + xCor;
    }else if(!isCurrentScreen && xCor >= 0){
    flag = false;
    }
    if(xCor <= 0){
    xCor = 10;
    }
    if(xCor > width){
    xCor = width - 10;
    }
    float angle = 0;
    if(isBorder){
    doDraw(mCanvas,width,height,angle,xCor);
    }else if(!flag){
    angle = 90.0f - (xCor / (float)width) * 90.0f;
    doDraw(mCanvas,width,height,angle,xCor);
    }else{
    angle = -(xCor / (float)width) * 90.0f;
    doDraw(mCanvas,width,height,angle,xCor);
    }*/




final float SPAN = 0.000424f;
//begin to draw
float f = xCor - 10;
if(f <= 0) {
f=0;
xCor=10;
}//the maximum left

float value = f * SPAN;
/* if(f > 300) {
// xCor = 310;
xCor = width;
value = 0.127225f;
}//the maximum right
*/

if(f > width){
xCor = f - width;
value = 0.127225f;
}
Log.d(TAG,"width=" + width + ",height=" + height + ",xCor=" + xCor +",f=" + f);


mCanvas.save();
mCanvas.drawColor(Color.BLACK);
mCanvas.translate(mScrollX, 0);
    doDraw(mCanvas,s[b1],
    new float[] {0,0,width,0,width,height,0,height},
    new float[] {0,height*(1/7.0f-value),xCor,0,xCor,height,0,height*(6/7.0f+value)}
    );

    doDraw(mCanvas,s[b2],
    new float[] {0,0,width,0,width,height,0,height},
                new float[] {xCor,0,width,height*(1/64.0f+value),width,height*(63/64.0f-value), xCor,height}
    );
        mCanvas.restore();
}
   
   /* private void doDraw(Canvas canvas,float width,float height,float angle,float xCor){
    canvas.save();
    mCamera.save();
    mCamera.rotateY(angle);
    mCamera.getMatrix(mMatrix);
    mCamera.restore();
   
    //Log.d("CellLayout" + currentScreen, angle + " __  " + mMatrix);
    System.out.println("CellLayout="+currentScreen+ ",angle="+angle+",mMatrix=" + mMatrix);
    if(angle < 0){
    mMatrix.preTranslate(-width, -height * 0.5f);
    mMatrix.postTranslate(width, height * 0.5f);
    }else{
    mMatrix.preTranslate(0f, -height * 0.5f);
    mMatrix.postTranslate(0f, height * 0.5f);
    }
   
    canvas.concat(mMatrix);
    switch (currentScreen) {
    case 0: 
            mPaint.setColor(Color.RED); 
            break; 
        case 1: 
            mPaint.setColor(Color.BLUE); 
            break; 
        case 2: 
        mPaint.setAntiAlias(true);
            mPaint.setColor(Color.YELLOW);
            mPaint.setAlpha(80);
            break; 
        case 3: 
            mPaint.setColor(Color.CYAN); 
            break; 
        case 4: 
            mPaint.setColor(Color.GREEN); 
            break;
}
    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    canvas.drawRect(0, 0, width, height, mPaint);
    }*/
   
   
   
    public void doDraw(Canvas canvas,Bitmap bp, float src[], float dst[]) {
    mCanvas.save();
        mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);
       
        mCanvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
       
        mCanvas.concat(mMatrix);
       
        mCanvas.drawBitmap(bp, 0, 0, null);
        mCanvas.restore();
       
       
}

public void makeTargetScreen(){
Log.d(TAG,"makeTargetScreen");
//use the wall paper as the background, if we
    //don't have these, when we change the wall paper
    //the wall paper won't be changed until we drag the workspace
    getChildAt(0).setBackgroundDrawable(null);
getChildAt(1).setBackgroundDrawable(null);
getChildAt(2).setBackgroundDrawable(null);
getChildAt(3).setBackgroundDrawable(null);
getChildAt(4).setBackgroundDrawable(null);

    if(mdirection > 0 && flag1){//finger move from left to right
    //we can use whether the currentX > or < 160.0f to know how to change the screen
    if(mCurrentScreen >= 1){//if current screen is the second or third screen
    if(currentX > getWidth()/2.0f)
    mCurrentScreen = mCurrentScreen - 1;
    }else if(mCurrentScreen == 0){
    mCurrentScreen = 4;
    }
    }
    if(mdirection < 0 && flag2){//finger move from right to left
    if(mCurrentScreen <= 1){//if current screen is the first or second screen 
    if(currentX < getWidth()/2.0f)
    mCurrentScreen = mCurrentScreen + 1;
    }
    else if(mCurrentScreen == 2){
    mCurrentScreen = 3;
    }
    else if(mCurrentScreen == 3){
    mCurrentScreen = 4;
    }   
    else if(mCurrentScreen == 4){
    mCurrentScreen = 0;
    }
    }
    flag=true;
    flag1=true;
    flag2=true;
}
   
   
   
}
9 楼 yangzhihui_1171 2011-07-15  
我的桌面3D效果,只改了workspace.java一个文件
8 楼 yangzhihui_1171 2011-07-15  
lz,这是我改的workspace.java,我觉得改得不通用,在8寸机子(1280*768),3D效果不好,你帮我看看该怎么调。。。

public class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller {
    @SuppressWarnings({"UnusedDeclaration"})
    private static final String TAG = "Launcher.Workspace";
    private static final int INVALID_SCREEN = -1;
   
    /**
     * The velocity at which a fling gesture will cause us to snap to the next screen
     */
    private static final int SNAP_VELOCITY = 600;

    private final WallpaperManager mWallpaperManager;
   
    private int mDefaultScreen;

    private boolean mFirstLayout = true;

    private int mCurrentScreen;
    private int mNextScreen = INVALID_SCREEN;
    private Scroller mScroller;
    private VelocityTracker mVelocityTracker;

    /**
     * CellInfo for the cell that is currently being dragged
     */
    private CellLayout.CellInfo mDragInfo;
   
    /**
     * Target drop area calculated during last acceptDrop call.
     */
    private int[] mTargetCell = null;

    private float mLastMotionX;
    private float mLastMotionY;
   
    private final static int TOUCH_STATE_REST = 0;
    private final static int TOUCH_STATE_SCROLLING = 1;

    private int mTouchState = TOUCH_STATE_REST;

    private OnLongClickListener mLongClickListener;

    private Launcher mLauncher;
    private IconCache mIconCache;
    private DragController mDragController;
   
   
//add by yzh for HTCpreview
    private static final int SENSE_OPENING = 1;
    private static final int SENSE_CLOSING = 2;
    private static final int SENSE_OPEN = 3;
    private static final int SENSE_CLOSED = 4;
    // sense zoom variables
    private boolean mSensemode = false;
    private boolean isAnimating = false;
    private long startTime;
    private int mStatus = SENSE_CLOSED;
    private final int mAnimationDuration = 400;
    private final int[][] distro = { {1}, {2}, {1, 2}, {2, 2},
    {2, 1, 2}, {2, 2, 2}, {2, 3, 2}, {3, 2, 3}, {3, 3, 3} };
    private float previewScale = 1;

    private Paint mPaint;
//end by yzh for HTCpreview
   
   
   
   
   
   
    /**
     * Cache of vacant cells, used during drag events and invalidated as needed.
     */
    private CellLayout.CellInfo mVacantCache = null;
   
    private int[] mTempCell = new int[2];
    private int[] mTempEstimate = new int[2];

    private boolean mAllowLongPress = true;

    private int mTouchSlop;
    private int mMaximumVelocity;
   
    private static final int INVALID_POINTER = -1;
   
   
  //------------------------add by yzh for 3D
public static Bitmap[] s = new Bitmap[5];
//这两个位图,转成3D效果
private int b1 = 0;
private int b2 = 0;

//定义图片的大小
//private float width = 320.0f;
//private float height = 438.0f;
    private Matrix mMatrix = new Matrix();

    //当前手在屏幕上的X坐标值,通过它判断2张图片要如何绘制
private float currentX=0.0f;

//判断拖动屏幕时的拖动方向,大于0为向右拖,小于0为向左拖
float mdirection=0.0f;
boolean flag = true;
//当你从左向右拖动,或从右向左拖动,需要一个标识
boolean flag1 = true;
boolean flag2 = true;
Drawable wallpaperDrawable = null;
Canvas mCanvas = new Canvas();

    private boolean isCurrentScreen;
    private boolean isBorder;
    private Camera mCamera = new Camera();
    private int currentScreen;
//------------------------end by yzh for 3D

    private int mActivePointerId = INVALID_POINTER;
   
    private Drawable mPreviousIndicator;
    private Drawable mNextIndicator;
   
    private static final float NANOTIME_DIV = 1000000000.0f;
    private static final float SMOOTHING_SPEED = 0.75f;
    private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED));
    private float mSmoothingTime;
    private float mTouchX;

    private WorkspaceOvershootInterpolator mScrollInterpolator;

    private static final float BASELINE_FLING_VELOCITY = 2500.f;
    private static final float FLING_VELOCITY_INFLUENCE = 0.4f;
   
    private static class WorkspaceOvershootInterpolator implements Interpolator {
        private static final float DEFAULT_TENSION = 1.3f;
        private float mTension;

        public WorkspaceOvershootInterpolator() {
            mTension = DEFAULT_TENSION;
        }
       
        public void setDistance(int distance) {
            mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION;
        }

        public void disableSettle() {
            mTension = 0.f;
        }

        public float getInterpolation(float t) {
            // _o(t) = t * t * ((tension + 1) * t + tension)
            // o(t) = _o(t - 1) + 1
            t -= 1.0f;
            return t * t * ((mTension + 1) * t + mTension) + 1.0f;
        }
    }
   
    /**
     * Used to inflate the Workspace from XML.
     *
     * @param context The application's context.
     * @param attrs The attribtues set containing the Workspace's customization values.
     */
    public Workspace(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    /**
     * Used to inflate the Workspace from XML.
     *
     * @param context The application's context.
     * @param attrs The attribtues set containing the Workspace's customization values.
     * @param defStyle Unused.
     */
    public Workspace(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mWallpaperManager = WallpaperManager.getInstance(context);
       
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Workspace, defStyle, 0);
        mDefaultScreen = a.getInt(R.styleable.Workspace_defaultScreen, 1);
        a.recycle();

        setHapticFeedbackEnabled(false);
        initWorkspace();
    }

    /**
     * Initializes various states for this workspace.
     */
    private void initWorkspace() {
        Context context = getContext();
        mScrollInterpolator = new WorkspaceOvershootInterpolator();
        mScroller = new Scroller(context, mScrollInterpolator);
        mCurrentScreen = mDefaultScreen;
        Launcher.setScreen(mCurrentScreen);
        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
        mIconCache = app.getIconCache();
       
        //add by yzh for HTCpreview
        mPaint = new Paint();
    mPaint.setDither(false);
    //end by yzh for HTCpreview

        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
        mTouchSlop = configuration.getScaledTouchSlop();
        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
    }

    @Override
    public void addView(View child, int index, LayoutParams params) {
        if (!(child instanceof CellLayout)) {
            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
        }
        super.addView(child, index, params);
    }

    @Override
    public void addView(View child) {
        if (!(child instanceof CellLayout)) {
            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
        }
        super.addView(child);
    }

    @Override
    public void addView(View child, int index) {
        if (!(child instanceof CellLayout)) {
            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
        }
        super.addView(child, index);
    }

    @Override
    public void addView(View child, int width, int height) {
        if (!(child instanceof CellLayout)) {
            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
        }
        super.addView(child, width, height);
    }

    @Override
    public void addView(View child, LayoutParams params) {
        if (!(child instanceof CellLayout)) {
            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
        }
        super.addView(child, params);
    }

    /**
     * @return The open folder on the current screen, or null if there is none
     */
    Folder getOpenFolder() {
        CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen);
        int count = currentScreen.getChildCount();
        for (int i = 0; i < count; i++) {
            View child = currentScreen.getChildAt(i);
            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
            if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
                return (Folder) child;
            }
        }
        return null;
    }

    ArrayList<Folder> getOpenFolders() {
        final int screens = getChildCount();
        ArrayList<Folder> folders = new ArrayList<Folder>(screens);

        for (int screen = 0; screen < screens; screen++) {
            CellLayout currentScreen = (CellLayout) getChildAt(screen);
            int count = currentScreen.getChildCount();
            for (int i = 0; i < count; i++) {
                View child = currentScreen.getChildAt(i);
                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
                    folders.add((Folder) child);
                    break;
                }
            }
        }

        return folders;
    }

    boolean isDefaultScreenShowing() {
        return mCurrentScreen == mDefaultScreen;
    }

    /**
     * Returns the index of the currently displayed screen.
     *
     * @return The index of the currently displayed screen.
     */
    int getCurrentScreen() {
        return mCurrentScreen;
    }

    /**
     * Sets the current screen.
     *
     * @param currentScreen
     */
    void setCurrentScreen(int currentScreen) {
    Log.d(TAG,"setCurrentScreen------");
        if (!mScroller.isFinished()) mScroller.abortAnimation();
        clearVacantCache();
        mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
        mPreviousIndicator.setLevel(mCurrentScreen);
        mNextIndicator.setLevel(mCurrentScreen);
        scrollTo(mCurrentScreen * getWidth(), 0);
        updateWallpaperOffset();
        invalidate();
    }

    /**
     * Adds the specified child in the current screen. The position and dimension of
     * the child are defined by x, y, spanX and spanY.
     *
     * @param child The child to add in one of the workspace's screens.
     * @param x The X position of the child in the screen's grid.
     * @param y The Y position of the child in the screen's grid.
     * @param spanX The number of cells spanned horizontally by the child.
     * @param spanY The number of cells spanned vertically by the child.
     */
    void addInCurrentScreen(View child, int x, int y, int spanX, int spanY) {
        addInScreen(child, mCurrentScreen, x, y, spanX, spanY, false);
    }

    /**
     * Adds the specified child in the current screen. The position and dimension of
     * the child are defined by x, y, spanX and spanY.
     *
     * @param child The child to add in one of the workspace's screens.
     * @param x The X position of the child in the screen's grid.
     * @param y The Y position of the child in the screen's grid.
     * @param spanX The number of cells spanned horizontally by the child.
     * @param spanY The number of cells spanned vertically by the child.
     * @param insert When true, the child is inserted at the beginning of the children list.
     */
    void addInCurrentScreen(View child, int x, int y, int spanX, int spanY, boolean insert) {
        addInScreen(child, mCurrentScreen, x, y, spanX, spanY, insert);
    }

    /**
     * Adds the specified child in the specified screen. The position and dimension of
     * the child are defined by x, y, spanX and spanY.
     *
     * @param child The child to add in one of the workspace's screens.
     * @param screen The screen in which to add the child.
     * @param x The X position of the child in the screen's grid.
     * @param y The Y position of the child in the screen's grid.
     * @param spanX The number of cells spanned horizontally by the child.
     * @param spanY The number of cells spanned vertically by the child.
     */
    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
        addInScreen(child, screen, x, y, spanX, spanY, false);
    }

    /**
     * Adds the specified child in the specified screen. The position and dimension of
     * the child are defined by x, y, spanX and spanY.
     *
     * @param child The child to add in one of the workspace's screens.
     * @param screen The screen in which to add the child.
     * @param x The X position of the child in the screen's grid.
     * @param y The Y position of the child in the screen's grid.
     * @param spanX The number of cells spanned horizontally by the child.
     * @param spanY The number of cells spanned vertically by the child.
     * @param insert When true, the child is inserted at the beginning of the children list.
     */
    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
        if (screen < 0 || screen >= getChildCount()) {
            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
                + " (was " + screen + "); skipping child");
            return;
        }

        clearVacantCache();

        final CellLayout group = (CellLayout) getChildAt(screen);
        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
        if (lp == null) {
            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
        } else {
            lp.cellX = x;
            lp.cellY = y;
            lp.cellHSpan = spanX;
            lp.cellVSpan = spanY;
        }
        group.addView(child, insert ? 0 : -1, lp);
        if (!(child instanceof Folder)) {
            child.setHapticFeedbackEnabled(false);
            child.setOnLongClickListener(mLongClickListener);
        }
        if (child instanceof DropTarget) {
            mDragController.addDropTarget((DropTarget)child);
        }
    }

    CellLayout.CellInfo findAllVacantCells(boolean[] occupied) {
        CellLayout group = (CellLayout) getChildAt(mCurrentScreen);
        if (group != null) {
            return group.findAllVacantCells(occupied, null);
        }
        return null;
    }

    private void clearVacantCache() {
        if (mVacantCache != null) {
            mVacantCache.clearVacantCells();
            mVacantCache = null;
        }
    }

    /**
     * Registers the specified listener on each screen contained in this workspace.
     *
     * @param l The listener used to respond to long clicks.
     */
    @Override
    public void setOnLongClickListener(OnLongClickListener l) {
        mLongClickListener = l;
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            getChildAt(i).setOnLongClickListener(l);
        }
    }

    private void updateWallpaperOffset() {
        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
    }

    private void updateWallpaperOffset(int scrollRange) {
        IBinder token = getWindowToken();
        if (token != null) {
            mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
            mWallpaperManager.setWallpaperOffsets(getWindowToken(),
                    Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
        }
    }
   
    @Override
    public void scrollTo(int x, int y) {
        super.scrollTo(x, y);
        mTouchX = x;
        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
    }
   
    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            mTouchX = mScrollX = mScroller.getCurrX();
            mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
            mScrollY = mScroller.getCurrY();
            updateWallpaperOffset();
            postInvalidate();
        } else if (mNextScreen != INVALID_SCREEN) {
            mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
            mPreviousIndicator.setLevel(mCurrentScreen);
            mNextIndicator.setLevel(mCurrentScreen);
            Launcher.setScreen(mCurrentScreen);
            mNextScreen = INVALID_SCREEN;
            clearChildrenCache();
        } else if (mTouchState == TOUCH_STATE_SCROLLING) {
            final float now = System.nanoTime() / NANOTIME_DIV;
            final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT);
            final float dx = mTouchX - mScrollX;
            mScrollX += dx * e;
            mSmoothingTime = now;

            // Keep generating points as long as we're more than 1px away from the target
            if (dx > 1.f || dx < -1.f) {
                updateWallpaperOffset();
                postInvalidate();
            }
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
    Log.d(TAG,"dispatchDraw");
        boolean restore = false;
        int restoreCount = 0;
mCanvas = canvas;//add by yzh for 3D

        // 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.

        if (!mSensemode) { // add by yzh for HTCpreview
       
        boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN;
       
        //add by yzh for 3D
        final long drawingTime = getDrawingTime();
final int count = getChildCount();

//The following method will make the screen shot for the 5 screens
for (int i = 0; i < count; i++) {
getChildAt(i).buildDrawingCache();
s[i]=getChildAt(i).getDrawingCache();
}
//end by yzh for 3D

        // If we are not scrolling or flinging, draw only the current screen
        if (fastDraw) {
        //add by yzh for 3D
scrollTo(mCurrentScreen * getWidth(), 0);

mCanvas.save();
mCanvas.translate(mScrollX, 0);
        doDraw(mCanvas,s[mCurrentScreen],
new float[] {0,0,mCanvas.getWidth(),0,mCanvas.getWidth(),mCanvas.getHeight(),0,mCanvas.getHeight()},
new float[] {0,0,mCanvas.getWidth(),0,mCanvas.getWidth(),mCanvas.getHeight(),0,mCanvas.getHeight()}
        );
        mCanvas.restore();
        //end by yzh for 3D
       
/*
//new add for test
((CellLayout) getChildAt(mCurrentScreen)).setDockBg(mLauncher.getDockbarCache()); */

           // 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;
           
          //new add for test
//             ((CellLayout) getChildAt(mCurrentScreen)).setDockBg(mLauncher.getDockbarCache());
           
            if (leftScreen >= 0) {
                drawChild(canvas, getChildAt(leftScreen), drawingTime);
            }
            if (scrollPos != leftScreen && rightScreen < getChildCount()) {
                drawChild(canvas, getChildAt(rightScreen), drawingTime);
            }*/
        if (mNextScreen >= 0 && mNextScreen < getChildCount() &&
                    Math.abs(mCurrentScreen - mNextScreen) == 1) {
                drawChild(mCanvas, getChildAt(mCurrentScreen), drawingTime);
                drawChild(mCanvas, getChildAt(mNextScreen), drawingTime);
        }
        }
        } else { // add by yzh for HTCpreview
        long currentTime;
        if (startTime == 0) {
    startTime = SystemClock.uptimeMillis();
    currentTime = 0;
        } else {
        currentTime = SystemClock.uptimeMillis() - startTime;
        }
        if (currentTime >= mAnimationDuration) {
    isAnimating = false;
    if (mStatus == SENSE_OPENING) {
        mStatus = SENSE_OPEN;
    } else if (mStatus == SENSE_CLOSING) {
        mStatus = SENSE_CLOSED;
        mSensemode = false;
        clearChildrenCache();
        postInvalidate();
    }
        } else {
        postInvalidate();
        }
    final int count = getChildCount();
    for (int i = 0; i < count; i++) {
    drawChildForHTC(canvas, getChildAt(i), getDrawingTime());
    }
    }
    //end yzh add for HTCpreview
       
    /* if (restore) {
        canvas.restoreToCount(restoreCount);
    }*/
       
       
//add by yzh for 3D
if(mTouchState == TOUCH_STATE_SCROLLING){
startRotate(mCanvas,currentX,mCanvas.getWidth(),mCanvas.getHeight());
        }
//end by yzh for 3D
    }
   
   

    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        computeScroll();
        mDragController.setWindowToken(getWindowToken());
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        final int width = MeasureSpec.getSize(widthMeasureSpec);
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if (widthMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
        }

        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
        }

        // The children are given the same width and height as the workspace
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
        }


        if (mFirstLayout) {
        Log.d(TAG,"onMeasure_mFirstLayout------------");
            setHorizontalScrollBarEnabled(false);
            scrollTo(mCurrentScreen * width, 0);
            setHorizontalScrollBarEnabled(true);
            updateWallpaperOffset(width * (getChildCount() - 1));
            mFirstLayout = false;
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    Log.d(TAG,"onLayout");
        int childLeft = 0;

        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != View.GONE) {
                final int childWidth = child.getMeasuredWidth();
                child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
                childLeft += childWidth;
            }
        }
    }

    @Override
    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
        int screen = indexOfChild(child);
        if (screen != mCurrentScreen || !mScroller.isFinished()) {
            snapToScreen(screen);
            return true;
        }
        return false;
    }

    @Override
    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
        if (!mLauncher.isAllAppsVisible()) {
            final Folder openFolder = getOpenFolder();
            if (openFolder != null) {
                return openFolder.requestFocus(direction, previouslyFocusedRect);
            } else {
                int focusableScreen;
                if (mNextScreen != INVALID_SCREEN) {
                    focusableScreen = mNextScreen;
                } else {
                    focusableScreen = mCurrentScreen;
                }
                getChildAt(focusableScreen).requestFocus(direction, previouslyFocusedRect);
            }
        }
        return false;
    }

    @Override
    public boolean dispatchUnhandledMove(View focused, int direction) {
        if (direction == View.FOCUS_LEFT) {
            if (getCurrentScreen() > 0) {
                snapToScreen(getCurrentScreen() - 1);
                return true;
            }
        } else if (direction == View.FOCUS_RIGHT) {
            if (getCurrentScreen() < getChildCount() - 1) {
                snapToScreen(getCurrentScreen() + 1);
                return true;
            }
        }
        return super.dispatchUnhandledMove(focused, direction);
    }

    @Override
    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
        if (!mLauncher.isAllAppsVisible()) {
            final Folder openFolder = getOpenFolder();
            if (openFolder == null) {
                getChildAt(mCurrentScreen).addFocusables(views, direction);
                if (direction == View.FOCUS_LEFT) {
                    if (mCurrentScreen > 0) {
                        getChildAt(mCurrentScreen - 1).addFocusables(views, direction);
                    }
                } else if (direction == View.FOCUS_RIGHT){
                    if (mCurrentScreen < getChildCount() - 1) {
                        getChildAt(mCurrentScreen + 1).addFocusables(views, direction);
                    }
                }
            } else {
                openFolder.addFocusables(views, direction);
            }
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            if (mLauncher.isAllAppsVisible()) {
                return false;
            }
        }
        return super.dispatchTouchEvent(ev);
    }
   
//add by yzh for HTCpreview {
    private void findClickedPreview(float x, float y) {
for (int i = 0; i < getChildCount(); i++) {
    RectF tmp = getScaledChild(getChildAt(i));
    if (tmp.contains(x + getScrollX(), y + getScrollY())) {
if (mCurrentScreen != i) {
    mLauncher.dismissPreviews();
    snapToScreen(i);
    postInvalidate();
} else {
    mLauncher.dismissPreviews();
    postInvalidate();
}
    }
}
    }
//end by yzh for HTCpreview

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
    // add by yzh for HTCpreview
    if (mStatus == SENSE_OPEN) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        findClickedPreview(ev.getX(), ev.getY());
        }
        return true;
    }
    // add by yzh for HTCpreview
   
        final boolean allAppsVisible = mLauncher.isAllAppsVisible();
        if (allAppsVisible) {
            return false; // We don't want the events.  Let them fall through to the all apps view.
        }

        /*
         * This method JUST determines whether we want to intercept the motion.
         * If we return true, onTouchEvent will be called and we do the actual
         * scrolling there.
         */

        /*
         * Shortcut the most recurring case: the user is in the dragging
         * state and he is moving his finger.  We want to intercept this
         * motion.
         */
        final int action = ev.getAction();
        if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) {
            return true;
        }

        acquireVelocityTrackerAndAddMovement(ev);
       
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_MOVE: {
                /*
                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
                 * whether the user has moved far enough from his original down touch.
                 */

                /*
                 * Locally do absolute value. mLastMotionX is set to the y value
                 * of the down event.
                 */
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float x = ev.getX(pointerIndex);
                final float y = ev.getY(pointerIndex);
                final int xDiff = (int) Math.abs(x - mLastMotionX);
                final int yDiff = (int) Math.abs(y - mLastMotionY);

                final int touchSlop = mTouchSlop;
                boolean xMoved = xDiff > touchSlop;
                boolean yMoved = yDiff > touchSlop;
               
                if (xMoved || yMoved) {
                   
                    if (xMoved) {
                        // Scroll if the user moved far enough along the X axis
                        mTouchState = TOUCH_STATE_SCROLLING;
                        mLastMotionX = x;
                        mTouchX = mScrollX;
                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
                        enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1);
                    }
                    // Either way, cancel any pending longpress
                    if (mAllowLongPress) {
                        mAllowLongPress = false;
                        // Try canceling the long press. It could also have been scheduled
                        // by a distant descendant, so use the mAllowLongPress flag to block
                        // everything
                        final View currentScreen = getChildAt(mCurrentScreen);
                        currentScreen.cancelLongPress();
                    }
                }
                break;
            }

            case MotionEvent.ACTION_DOWN: {
                final float x = ev.getX();
                final float y = ev.getY();
                // Remember location of down touch
                mLastMotionX = x;

                mLastMotionY = y;
                mActivePointerId = ev.getPointerId(0);
                mAllowLongPress = true;

                /*
                 * If being flinged and user touches the screen, initiate drag;
                 * otherwise don't.  mScroller.isFinished should be false when
                 * being flinged.
                 */
                mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
                break;
            }

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
               
                if (mTouchState != TOUCH_STATE_SCROLLING) {
                    final CellLayout currentScreen = (CellLayout)getChildAt(mCurrentScreen);
                    if (!currentScreen.lastDownOnOccupiedCell()) {
                        getLocationOnScreen(mTempCell);
                        // Send a tap to the wallpaper if the last down was on empty space
                        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                        mWallpaperManager.sendWallpaperCommand(getWindowToken(),
                                "android.wallpaper.tap",
                                mTempCell[0] + (int) ev.getX(pointerIndex),
                                mTempCell[1] + (int) ev.getY(pointerIndex), 0, null);
                    }
                }
               
                // Release the drag
                clearChildrenCache();
                mTouchState = TOUCH_STATE_REST;
                mActivePointerId = INVALID_POINTER;
                mAllowLongPress = false;
                releaseVelocityTracker();
                break;
               
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
        }

        /*
         * The only time we want to intercept motion events is if we are in the
         * drag mode.
         */
        return mTouchState != TOUCH_STATE_REST;
    }
   
    private void onSecondaryPointerUp(MotionEvent ev) {
        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            // TODO: Make this decision more intelligent.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastMotionX = ev.getX(newPointerIndex);
            mLastMotionY = ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
            if (mVelocityTracker != null) {
                mVelocityTracker.clear();
            }
        }
    }

    /**
     * If one of our descendant views decides that it could be focused now, only
     * pass that along if it's on the current screen.
     *
     * This happens when live folders requery, and if they're off screen, they
     * end up calling requestFocus, which pulls it on screen.
     */
    @Override
    public void focusableViewAvailable(View focused) {
        View current = getChildAt(mCurrentScreen);
        View v = focused;
        while (true) {
            if (v == current) {
                super.focusableViewAvailable(focused);
                return;
            }
            if (v == this) {
                return;
            }
            ViewParent parent = v.getParent();
            if (parent instanceof View) {
                v = (View)v.getParent();
            } else {
                return;
            }
        }
    }

    void enableChildrenCache(int fromScreen, int toScreen) {
        if (fromScreen > toScreen) {
            final int temp = fromScreen;
            fromScreen = toScreen;
            toScreen = temp;
        }
       
        final int count = getChildCount();

        fromScreen = Math.max(fromScreen, 0);
        toScreen = Math.min(toScreen, count - 1);

        for (int i = fromScreen; i <= toScreen; i++) {
            final CellLayout layout = (CellLayout) getChildAt(i);
            layout.setChildrenDrawnWithCacheEnabled(true);
            layout.setChildrenDrawingCacheEnabled(true);
        }
    }

    void clearChildrenCache() {
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final CellLayout layout = (CellLayout) getChildAt(i);
            layout.setChildrenDrawnWithCacheEnabled(false);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        Log.d(TAG,"onTouchEvent");
        if (mLauncher.isAllAppsVisible() || mSensemode) {
            // Cancel any scrolling that is in progress.
           /* if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
            }
            snapToScreen(mCurrentScreen);*/
            //return false; // We don't want the events.  Let them fall through to the all apps view.
        return true;
        }

        acquireVelocityTrackerAndAddMovement(ev);

        final int action = ev.getAction();

        switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
        Log.d(TAG,"--onTouchEvent_ACTION_DOWN--");
            /*
             * If being flinged and user touches, stop the fling. isFinished
             * will be false if being flinged.
             */
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
            }

            // Remember where the motion event started
            mLastMotionX = ev.getX();
           
            mActivePointerId = ev.getPointerId(0);
            if (mTouchState == TOUCH_STATE_SCROLLING) {
                enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1);
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (mTouchState == TOUCH_STATE_SCROLLING) {

            Log.d(TAG,"--onTouchEvent_ACTION_MOVE--");
                // Scroll to follow the motion event
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float x = ev.getX(pointerIndex);
                final float deltaX = mLastMotionX - x;
                mLastMotionX = x;

                if (deltaX < 0) {
                   /* if (mTouchX > 0) {
                        mTouchX += Math.max(-mTouchX, deltaX);
                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
                        invalidate();
                    }*/
               //add by yzh for 3D
if (mScrollX > 0) {
                    mdirection = 1;// move to right
                    }
//end by yzh for 3D
                } else if (deltaX > 0) {
                mdirection = -1;// move to left // add by yzh for 3D
               
                    final float availableToScroll = getChildAt(getChildCount() - 1).getRight() -
                            mTouchX - getWidth();
                    if (availableToScroll > 0) {
                      /*  mTouchX += Math.min(availableToScroll, deltaX);
                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
                        invalidate()*/;
                    }
                }
                /*else {
                    awakenScrollBars();
                }*/
                //add by yzh for 3D
                currentX=x;
        calculateRotate();
        //end by yzh for 3D
            }
            break;
        case MotionEvent.ACTION_UP:
            if (mTouchState == TOUCH_STATE_SCROLLING) {
            Log.d(TAG,"--onTouchEvent_ACTION_UP--");
           
            makeTargetScreen();// add by yzh for 3D
           
                final VelocityTracker velocityTracker = mVelocityTracker;
                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                final int velocityX = (int) velocityTracker.getXVelocity(mActivePointerId);
               
                final int screenWidth = getWidth();
                final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
                final float scrolledPos = (float) mScrollX / screenWidth;
               
                if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
                    // Fling hard enough to move left.
                    // Don't fling across more than one screen at a time.
                  //  final int bound = scrolledPos < whichScreen ?
                   //         mCurrentScreen - 1 : mCurrentScreen;
                  //  snapToScreen(Math.min(whichScreen, bound), velocityX, true);
                } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
                    // Fling hard enough to move right
                    // Don't fling across more than one screen at a time.
                  //  final int bound = scrolledPos > whichScreen ?
                  //          mCurrentScreen + 1 : mCurrentScreen;
                  //  snapToScreen(Math.max(whichScreen, bound), velocityX, true);
                } else {
                   // snapToScreen(whichScreen, 0, true);
                }
            }
            mTouchState = TOUCH_STATE_REST;
            mActivePointerId = INVALID_POINTER;
            releaseVelocityTracker();
            break;
        case MotionEvent.ACTION_CANCEL:
            if (mTouchState == TOUCH_STATE_SCROLLING) {
                final int screenWidth = getWidth();
                final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
                snapToScreen(whichScreen, 0, true);
            }
            mTouchState = TOUCH_STATE_REST;
            mActivePointerId = INVALID_POINTER;
            releaseVelocityTracker();
            break;
        case MotionEvent.ACTION_POINTER_UP:
            onSecondaryPointerUp(ev);
            break;
        }

        return true;
    }
   
    private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(ev);
    }

    private void releaseVelocityTracker() {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }

    void snapToScreen(int whichScreen) {
        snapToScreen(whichScreen, 0, false);
    }

    private void snapToScreen(int whichScreen, int velocity, boolean settle) {
    Log.d(TAG, "snapToScreen--");
        //if (!mScroller.isFinished()) return;

        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
       
        clearVacantCache();
        enableChildrenCache(mCurrentScreen, whichScreen);

        mNextScreen = whichScreen;

        mPreviousIndicator.setLevel(mNextScreen);
        mNextIndicator.setLevel(mNextScreen);

        View focusedChild = getFocusedChild();
        if (focusedChild != null && whichScreen != mCurrentScreen &&
                focusedChild == getChildAt(mCurrentScreen)) {
            focusedChild.clearFocus();
        }
       
        final int screenDelta = Math.max(1, Math.abs(whichScreen - mCurrentScreen));
        final int newX = whichScreen * getWidth();
        final int delta = newX - mScrollX;
        int duration = (screenDelta + 1) * 100;

        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
        }
       
        if (settle) {
            mScrollInterpolator.setDistance(screenDelta);
        } else {
            mScrollInterpolator.disableSettle();
        }
       
        velocity = Math.abs(velocity);
        if (velocity > 0) {
            duration += (duration / (velocity / BASELINE_FLING_VELOCITY))
                    * FLING_VELOCITY_INFLUENCE;
        } else {
            duration += 100;
        }

        awakenScrollBars(duration);
        mScroller.startScroll(mScrollX, 0, delta, 0, duration);
        invalidate();
    }

    void startDrag(CellLayout.CellInfo cellInfo) {
    Log.d(TAG,"000000000000000000000");
        View child = cellInfo.cell;
       
        // Make sure the drag was started by a long press as opposed to a long click.
        if (!child.isInTouchMode()) {
            return;
        }
       
        mDragInfo = cellInfo;
        mDragInfo.screen = mCurrentScreen;
       
        CellLayout current = ((CellLayout) getChildAt(mCurrentScreen));

        current.onDragChild(child);
        mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
        invalidate();
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        final SavedState state = new SavedState(super.onSaveInstanceState());
        state.currentScreen = mCurrentScreen;
        return state;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        SavedState savedState = (SavedState) state;
        super.onRestoreInstanceState(savedState.getSuperState());
        if (savedState.currentScreen != -1) {
            mCurrentScreen = savedState.currentScreen;
            Launcher.setScreen(mCurrentScreen);
        }
    }

    void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) {
        addApplicationShortcut(info, cellInfo, false);
    }

    void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo,
            boolean insertAtFirst) {
        final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen);
        final int[] result = new int[2];

        layout.cellToPoint(cellInfo.cellX, cellInfo.cellY, result);
        onDropExternal(result[0], result[1], info, layout, insertAtFirst);
    }
   
//add by yzh for HTCpreview
    public void openSense(boolean open) {
//mScroller.abortAnimation();
int maxItemsPerRow = 0;
int distro_set = getChildCount() - 1;
int numRows = distro[distro_set].length;
for (int rows = 0; rows < distro[distro_set].length; rows++) {
    if (distro[distro_set][rows] > maxItemsPerRow) {
    maxItemsPerRow = distro[distro_set][rows];
    }
}
int maxPreviewHeight = (getMeasuredHeight() / numRows);
float w = getMeasuredWidth() / maxItemsPerRow;
int maxPreviewWidth = (int) w;
float scaleW = ((float) maxPreviewWidth / (float) getWidth());
float scaleH = ((float) maxPreviewHeight / (float) getHeight());
previewScale = (scaleW > scaleH) ? scaleH : scaleW;
if (previewScale >= 1)
    previewScale = .8f;

if (open) {
    mSensemode = true;
    isAnimating = true;
    mStatus = SENSE_OPENING;
    startTime = 0;
} else {
    mSensemode = true;
    isAnimating = true;
    mStatus = SENSE_CLOSING;
    startTime = 0;
}
    }

  //  @Override
    protected boolean drawChildForHTC(Canvas canvas, View child, long drawingTime) {
    int saveCount = canvas.save();
if (mSensemode) {
    if (isAnimating || mStatus == SENSE_OPEN) {
long currentTime = SystemClock.uptimeMillis() - startTime;
Rect r1 = new Rect(0, 0, child.getWidth(), child.getHeight());
RectF r2 = getScaledChild(child);
float x = 0;
float y = 0;
float width = 0;
float height = 0;
float alpha = 255;
if (mStatus == SENSE_OPENING) {
    alpha = easeOut(currentTime, 0, 100, mAnimationDuration);
    x = easeOut(currentTime, child.getLeft(), r2.left,
    mAnimationDuration);
    y = easeOut(currentTime, child.getTop(), r2.top,
    mAnimationDuration);
    width = easeOut(currentTime, child.getRight(), r2.right,
    mAnimationDuration);
    height = easeOut(currentTime, child.getBottom(), r2.bottom,
    mAnimationDuration);
} else if (mStatus == SENSE_CLOSING) {
    alpha = easeOut(currentTime, 100, 0, mAnimationDuration);
    x = easeOut(currentTime, r2.left, child.getLeft(),
    mAnimationDuration);
    y = easeOut(currentTime, r2.top, child.getTop(),
    mAnimationDuration);
    width = easeOut(currentTime, r2.right, child.getRight(),
    mAnimationDuration);
    height = easeOut(currentTime, r2.bottom, child.getBottom(),
    mAnimationDuration);
} else if (mStatus == SENSE_OPEN) {
    x = r2.left;
    y = r2.top;
    width = r2.right;
    height = r2.bottom;
    alpha = 100;
}
float scale = ((width - x) / r1.width());
canvas.save();
canvas.translate(x, y);
canvas.scale(scale, scale);
mPaint.setAlpha((int) alpha);
canvas.drawRoundRect(new RectF(r1.left + 5, r1.top + 5,
r1.right - 5, r1.bottom - 5), 15f, 15f, mPaint);
mPaint.setAlpha(255);
child.draw(canvas);
canvas.restore();
    } else {
child.draw(canvas);
    }
} else {
    super.drawChild(canvas, child, drawingTime);
}
canvas.restoreToCount(saveCount);
return true;
    }

    static float easeOut(float time, float begin, float end, float duration) {
float change = end - begin;
float value = change * ((time = time / duration - 1) * time * time + 1)
+ begin;
if (change > 0 && value > end)
    value = end;
if (change < 0 && value < end)
    value = end;
return value;
    }

    private RectF getScaledChild(View child) {
final int count = getChildCount();
final int width = getWidth();
final int height = getHeight();
int xpos = getScrollX();
int ypos = 0;

int distro_set = count - 1;
int childPos = 0;

int childWidth = (int) (width * previewScale);
int childHeight = (int) (height * previewScale);

final int topMargin = (height / 2)
- ((childHeight * distro[distro_set].length) / 2);
for (int rows = 0; rows < distro[distro_set].length; rows++) {
    final int leftMargin = (width / 2)
    - ((childWidth * distro[distro_set][rows]) / 2);
    for (int columns = 0; columns < distro[distro_set][rows]; columns++) {
if (childPos > getChildCount() - 1)
    break;
final View c = getChildAt(childPos);
if (child == c) {
    return new RectF(leftMargin + xpos, topMargin + ypos,
    leftMargin + xpos + childWidth, topMargin + ypos
    + childHeight);
} else {
    xpos += childWidth;
}
childPos++;
    }
    xpos = getScrollX();
    ypos += childHeight;
}
return new RectF();
    }
//end by yzh for HTCpreview

    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
            DragView dragView, Object dragInfo) {
        Log.d(TAG,"workspace_onDrop");
        final CellLayout cellLayout = getCurrentDropLayout();
       
        if (source != this) {
            onDropExternal(x - xOffset, y - yOffset, dragInfo, cellLayout);
        } else {
            // Move internally
            if (mDragInfo != null) {
                final View cell = mDragInfo.cell;
                int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen;               
                if (index != mDragInfo.screen) {
                    final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
                    originalCellLayout.removeView(cell);
                    cellLayout.addView(cell);
                }
               
                mTargetCell = estimateDropCell(x - xOffset, y - yOffset,
                        mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout, mTargetCell);
                cellLayout.onDropChild(cell, mTargetCell);

                final ItemInfo info = (ItemInfo) cell.getTag();
                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
                LauncherModel.moveItemInDatabase(mLauncher, info,
                        LauncherSettings.Favorites.CONTAINER_DESKTOP, index, lp.cellX, lp.cellY);
            }
        }
    }

    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
            DragView dragView, Object dragInfo) {
        clearVacantCache();
    }

    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
            DragView dragView, Object dragInfo) {
    }

    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
            DragView dragView, Object dragInfo) {
        clearVacantCache();
    }

    private void onDropExternal(int x, int y, Object dragInfo, CellLayout cellLayout) {
        onDropExternal(x, y, dragInfo, cellLayout, false);
    }
   
    private void onDropExternal(int x, int y, Object dragInfo, CellLayout cellLayout,
            boolean insertAtFirst) {
        // Drag from somewhere else
        ItemInfo info = (ItemInfo) dragInfo;

        View view;

        switch (info.itemType) {
        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
            if (info.container == NO_ID && info instanceof ApplicationInfo) {
                // Came from all apps -- make a copy
                info = new ShortcutInfo((ApplicationInfo)info);
            }
            view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo)info);
            break;
        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
                    (ViewGroup) getChildAt(mCurrentScreen), ((UserFolderInfo) info));
            break;
        default:
            throw new IllegalStateException("Unknown item type: " + info.itemType);
        }

        cellLayout.addView(view, insertAtFirst ? 0 : -1);
        view.setHapticFeedbackEnabled(false);
        view.setOnLongClickListener(mLongClickListener);
        if (view instanceof DropTarget) {
            mDragController.addDropTarget((DropTarget) view);
        }

        mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
        cellLayout.onDropChild(view, mTargetCell);
        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();

        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
                LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
    }
   
    /**
     * Return the current {@link CellLayout}, correctly picking the destination
     * screen while a scroll is in progress.
     */
    private CellLayout getCurrentDropLayout() {
        int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen;
        return (CellLayout) getChildAt(index);
    }

    /**
     * {@inheritDoc}
     */
    public boolean acceptDrop(DragSource source, int x, int y,
            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
        final CellLayout layout = getCurrentDropLayout();
        final CellLayout.CellInfo cellInfo = mDragInfo;
        final int spanX = cellInfo == null ? 1 : cellInfo.spanX;
        final int spanY = cellInfo == null ? 1 : cellInfo.spanY;

        if (mVacantCache == null) {
            final View ignoreView = cellInfo == null ? null : cellInfo.cell;
            mVacantCache = layout.findAllVacantCells(null, ignoreView);
        }

        return mVacantCache.findCellForSpan(mTempEstimate, spanX, spanY, false);
    }
   
    /**
     * {@inheritDoc}
     */
    public Rect estimateDropLocation(DragSource source, int x, int y,
            int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle) {
        final CellLayout layout = getCurrentDropLayout();
       
        final CellLayout.CellInfo cellInfo = mDragInfo;
        final int spanX = cellInfo == null ? 1 : cellInfo.spanX;
        final int spanY = cellInfo == null ? 1 : cellInfo.spanY;
        final View ignoreView = cellInfo == null ? null : cellInfo.cell;
       
        final Rect location = recycle != null ? recycle : new Rect();
       
        // Find drop cell and convert into rectangle
        int[] dropCell = estimateDropCell(x - xOffset, y - yOffset,
                spanX, spanY, ignoreView, layout, mTempCell);
       
        if (dropCell == null) {
            return null;
        }
       
        layout.cellToPoint(dropCell[0], dropCell[1], mTempEstimate);
        location.left = mTempEstimate[0];
        location.top = mTempEstimate[1];
       
        layout.cellToPoint(dropCell[0] + spanX, dropCell[1] + spanY, mTempEstimate);
        location.right = mTempEstimate[0];
        location.bottom = mTempEstimate[1];
       
        return location;
    }

    /**
     * Calculate the nearest cell where the given object would be dropped.
     */
    private int[] estimateDropCell(int pixelX, int pixelY,
            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
        // Create vacant cell cache if none exists
        if (mVacantCache == null) {
            mVacantCache = layout.findAllVacantCells(null, ignoreView);
        }

        // Find the best target drop location
        return layout.findNearestVacantArea(pixelX, pixelY,
                spanX, spanY, mVacantCache, recycle);
    }
   
    void setLauncher(Launcher launcher) {
        mLauncher = launcher;
    }

    public void setDragController(DragController dragController) {
        mDragController = dragController;
    }

    public void onDropCompleted(View target, boolean success) {
        clearVacantCache();

        if (success){
            if (target != this && mDragInfo != null) {
                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
                cellLayout.removeView(mDragInfo.cell);
                if (mDragInfo.cell instanceof DropTarget) {
                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
                }
                //final Object tag = mDragInfo.cell.getTag();
            }
        } else {
            if (mDragInfo != null) {
                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
                cellLayout.onDropAborted(mDragInfo.cell);
            }
        }

        mDragInfo = null;
    }

    public void scrollLeft() {
    Log.d(TAG,"scrollLeft");
        clearVacantCache();
        if (mScroller.isFinished()) {
            if (mCurrentScreen > 0) snapToScreen(mCurrentScreen - 1);
        } else {
            if (mNextScreen > 0) snapToScreen(mNextScreen - 1);           
        }
    }

    public void scrollRight() {
    Log.d(TAG,"scrollRight");
        clearVacantCache();
        if (mScroller.isFinished()) {
            if (mCurrentScreen < getChildCount() -1) snapToScreen(mCurrentScreen + 1);
        } else {
            if (mNextScreen < getChildCount() -1) snapToScreen(mNextScreen + 1);           
        }
    }

    public int getScreenForView(View v) {
        int result = -1;
        if (v != null) {
            ViewParent vp = v.getParent();
            int count = getChildCount();
            for (int i = 0; i < count; i++) {
                if (vp == getChildAt(i)) {
                    return i;
                }
            }
        }
        return result;
    }

    public Folder getFolderForTag(Object tag) {
        int screenCount = getChildCount();
        for (int screen = 0; screen < screenCount; screen++) {
            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
            int count = currentScreen.getChildCount();
            for (int i = 0; i < count; i++) {
                View child = currentScreen.getChildAt(i);
                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
                    Folder f = (Folder) child;
                    if (f.getInfo() == tag) {
                        return f;
                    }
                }
            }
        }
        return null;
    }

    public View getViewForTag(Object tag) {
        int screenCount = getChildCount();
        for (int screen = 0; screen < screenCount; screen++) {
            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
            int count = currentScreen.getChildCount();
            for (int i = 0; i < count; i++) {
                View child = currentScreen.getChildAt(i);
                if (child.getTag() == tag) {
                    return child;
                }
            }
        }
        return null;
    }

    /**
     * @return True is long presses are still allowed for the current touch
     */
    public boolean allowLongPress() {
        return mAllowLongPress;
    }
   
    /**
     * Set true to allow long-press events to be triggered, usually checked by
     * {@link Launcher} to accept or block dpad-initiated long-presses.
     */
    public void setAllowLongPress(boolean allowLongPress) {
        mAllowLongPress = allowLongPress;
    }

    void removeItems(final ArrayList<ApplicationInfo> apps) {
        final int count = getChildCount();
        final PackageManager manager = getContext().getPackageManager();
        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());

        final HashSet<String> packageNames = new HashSet<String>();
        final int appCount = apps.size();
        for (int i = 0; i < appCount; i++) {
            packageNames.add(apps.get(i).componentName.getPackageName());
        }

        for (int i = 0; i < count; i++) {
            final CellLayout layout = (CellLayout) getChildAt(i);

            // Avoid ANRs by treating each screen separately
            post(new Runnable() {
                public void run() {
                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
                    childrenToRemove.clear();
       
                    int childCount = layout.getChildCount();
                    for (int j = 0; j < childCount; j++) {
                        final View view = layout.getChildAt(j);
                        Object tag = view.getTag();
       
                        if (tag instanceof ShortcutInfo) {
                            final ShortcutInfo info = (ShortcutInfo) tag;
                            final Intent intent = info.intent;
                            final ComponentName name = intent.getComponent();
       
                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
                                for (String packageName: packageNames) {
                                    if (packageName.equals(name.getPackageName())) {
                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
                                        childrenToRemove.add(view);
                                    }
                                }
                            }
                        } else if (tag instanceof UserFolderInfo) {
                            final UserFolderInfo info = (UserFolderInfo) tag;
                            final ArrayList<ShortcutInfo> contents = info.contents;
                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
                            final int contentsCount = contents.size();
                            boolean removedFromFolder = false;
       
                            for (int k = 0; k < contentsCount; k++) {
                                final ShortcutInfo appInfo = contents.get(k);
                                final Intent intent = appInfo.intent;
                                final ComponentName name = intent.getComponent();
       
                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
                                    for (String packageName: packageNames) {
                                        if (packageName.equals(name.getPackageName())) {
                                            toRemove.add(appInfo);
                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
                                            removedFromFolder = true;
                                        }
                                    }
                                }
                            }
       
                            contents.removeAll(toRemove);
                            if (removedFromFolder) {
                                final Folder folder = getOpenFolder();
                                if (folder != null) folder.notifyDataSetChanged();
                            }
                        } else if (tag instanceof LiveFolderInfo) {
                            final LiveFolderInfo info = (LiveFolderInfo) tag;
                            final Uri uri = info.uri;
                            final ProviderInfo providerInfo = manager.resolveContentProvider(
                                    uri.getAuthority(), 0);

                            if (providerInfo != null) {
                                for (String packageName: packageNames) {
                                    if (packageName.equals(providerInfo.packageName)) {
                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
                                        childrenToRemove.add(view);                       
                                    }
                                }
                            }
                        } else if (tag instanceof LauncherAppWidgetInfo) {
                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
                            final AppWidgetProviderInfo provider =
                                    widgets.getAppWidgetInfo(info.appWidgetId);
                            if (provider != null) {
                                for (String packageName: packageNames) {
                                    if (packageName.equals(provider.provider.getPackageName())) {
                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
                                        childrenToRemove.add(view);                               
                                    }
                                }
                            }
                        }
                    }
       
                    childCount = childrenToRemove.size();
                    for (int j = 0; j < childCount; j++) {
                        View child = childrenToRemove.get(j);
                        layout.removeViewInLayout(child);
                        if (child instanceof DropTarget) {
                            mDragController.removeDropTarget((DropTarget)child);
                        }
                    }
       
                    if (childCount > 0) {
                        layout.requestLayout();
                        layout.invalidate();
                    }
                }
            });
        }
    }

    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
        final PackageManager pm = mLauncher.getPackageManager();

        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final CellLayout layout = (CellLayout) getChildAt(i);
            int childCount = layout.getChildCount();
            for (int j = 0; j < childCount; j++) {
                final View view = layout.getChildAt(j);
                Object tag = view.getTag();
                if (tag instanceof ShortcutInfo) {
                    ShortcutInfo info = (ShortcutInfo)tag;
                    // We need to check for ACTION_MAIN otherwise getComponent() might
                    // return null for some shortcuts (for instance, for shortcuts to
                    // web pages.)
                
7 楼 ishelf 2011-07-14  
CellLayout
yangzhihui_1171 写道
lz,这桌面3D效果能只在Workspace.java里改吗?不要在CellLayout.java里改

根据需要吧,其实都是正对canvas的一个变换
6 楼 yangzhihui_1171 2011-07-14  
lz,这桌面3D效果能只在Workspace.java里改吗?不要在CellLayout.java里改
5 楼 ishelf 2011-07-04  
yangzhihui_1171 写道
lz,能实现屏和屏的下方3个图标一起翻吗?就是其中一个屏和下方3个图标一起翻,或者是所有屏和下方3个图标一起翻。


这个翻转是针对workspace的,下方的三个图标是在另外一个布局中,需要单独做...
4 楼 yangzhihui_1171 2011-07-04  
lz,能实现屏和屏的下方3个图标一起翻吗?就是其中一个屏和下方3个图标一起翻,或者是所有屏和下方3个图标一起翻。
3 楼 ishelf 2011-04-19  
wensefu 写道
lz 可否发份完整代码压缩包给我研究研究 wensefu@foxmail.com 谢谢。你发的代码中一些变量的声明以及值的变化的地方 还有sepa方法木有。

源码包是没有了,呵呵, 基本重点的都写出来了, 交流用了.....
2 楼 wensefu 2011-04-07  
lz 可否发份完整代码压缩包给我研究研究 wensefu@foxmail.com 谢谢。你发的代码中一些变量的声明以及值的变化的地方 还有sepa方法木有。
1 楼 gqdy365 2010-12-10  
不错,谢谢分享!

相关推荐

    安卓Launcher桌面相关-使用ViewPager实现高仿launcher拖动效果.rar

    在实现Launcher桌面的滑动效果时,我们可以将每个主屏幕看作ViewPager的一个页面,通过滑动来切换不同的主屏幕。 1. **ViewPager的基本使用** - 首先,我们需要在布局文件中添加ViewPager,并为其指定适配器。...

    安卓Launcher桌面相关-实现类似桌面的单屏效果.rar

    本压缩包文件"安卓Launcher桌面相关-实现类似桌面的单屏效果.rar"提供的内容可能包含了创建一个自定义桌面样式的源代码,帮助开发者了解和学习如何构建具有类似桌面单屏效果的应用。 首先,我们要理解"单屏效果"。...

    launcher 3D旋转参考实例

    "launcher 3D旋转参考实例"是一个关于如何在Android上实现3D旋转效果的示例项目,它展示了如何通过Eclipse IDE来创建一个具有动态旋转效果的启动器界面。这种特效可以提升用户体验,为应用程序增添视觉吸引力。 ...

    安卓Launcher桌面相关-Android实现图标拖拽.rar

    "安卓Launcher桌面相关-Android实现图标拖拽"这个压缩包文件似乎包含了一些关于如何在Android Launcher中实现图标拖放功能的源代码或示例项目。下面将详细介绍Android Launcher桌面的原理以及实现图标拖拽的相关知识...

    开发工具 ant-launcher-1.9.6

    开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ...

    junit-platform-launcher-1.8.0-M1-API文档-中文版.zip

    赠送jar包:junit-platform-launcher-1.8.0-M1.jar; 赠送原API文档:junit-platform-launcher-1.8.0-M1-javadoc.jar; 赠送源代码:junit-platform-launcher-1.8.0-M1-sources.jar; 赠送Maven依赖信息文件:junit-...

    安卓Launcher桌面相关-android桌面拖拽效果.rar

    本压缩包“安卓Launcher桌面相关-android桌面拖拽效果.rar”可能包含了一些实现Android Launcher中拖拽效果的源代码和资源文件。由于描述中提到无法逐一验证所有内容,以下将详细解释Android Launcher中拖拽效果的...

    junit-platform-launcher-1.7.0.jar

    junit-platform-launcher-1.7.0.jarjunit-platform-launcher-1.7.0.jar

    安卓Launcher桌面相关-launcher3D旋转参考实例.rar

    launcher 3D旋转参考实例.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。

    junit-platform-launcher-1.6.2.jar

    junit-platform-launcher-1.6.2.jarjunit-platform-launcher-1.6.2.jarjunit-platform-launcher-1.6.2.jar

    Android Launcher 桌面分页滑动代码-IT计算机-毕业设计.zip

    在Android系统中,Launcher是用户与手机交互的入口,它是一个桌面应用程序,负责展示应用程序快捷方式、小部件以及管理屏幕工作区。这个压缩包提供的"Android Launcher 桌面分页滑动代码"是一个适用于学生毕业设计的...

    安卓Launcher桌面相关-BackgroundViewPager实现桌面launch移动.rar

    2. **BackgroundViewPager**:这个名词可能是指一个定制版的 ViewPager,专门用于处理桌面背景的滚动效果。常规的 ViewPager 只处理视图的切换,而 BackgroundViewPager 可能包含了对背景图像或者壁纸随着页面滑动的...

    安卓超酷 3D 桌面 Next Launcher 3D Shell 3.7.3.2 中文多语免费版.zip

    安卓超酷 3D 桌面 Next Launcher 3D Shell 中文版安卓超酷 3D 桌面 Next Launcher 3D Shell 中文版 告别平面背景、平面图标、平面体验,此刻开始,畅享全3D桌面旅程!加入百万用户,领先潮流,体验独特的操作和出色...

    安卓Launcher桌面相关-使用eclipse开发工具自己写的一个桌面小控件.rar

    【Android Launcher 桌面开发详解】 在 Android 系统中,Launcher 是用户与设备交互的重要入口,它作为系统的桌面,展示着应用快捷方式、小部件以及桌面图标等元素。本教程将基于 Eclipse 开发环境,讲解如何创建一...

    Android11.0 Launcher3 添加负一屏(谷歌Feed屏方案)

    包含客户端 Launcher3 修改 包含服务端 OverlayScreen(可替换成你自己客需定制负一屏View) 基于android11.0 绝对好用,网上目前最...实现效果图 &lt;img src="https://i.postimg.cc/g2phQy6y/Screen.gif" border="0" /&gt;

    Android应用源码之Android Launcher 桌面分页滑动代码-IT计算机-毕业设计.zip

    通过深入理解这份代码,你可以了解到Android桌面启动器的实现机制,尤其是分页滑动的效果。 1. **Android Launcher基本结构**: Android Launcher是基于Activity构建的,通常继承自`android.app.LauncherActivity`...

    Android项目源码-安卓Launcher原生桌面源码

    【Android项目源码-安卓Launcher原生桌面源码】是一个深入了解Android系统启动器(Launcher)工作原理的重要资源。源码提供了Android操作系统中的主屏幕和应用抽屉的实现细节,这对于Android开发者尤其是系统定制者...

    修改Launcher让图标不显示在桌面或者主菜单中

    ### 修改Launcher让图标不显示在桌面或主菜单中的方法 #### 概述 在Android 2.3系统中,可以通过自定义Launcher应用来控制应用程序图标是否显示在桌面或主菜单中。这一操作对于定制化系统界面、提升用户体验等方面...

    Android 6.0 Launcher3 增加屏幕切换动画

    在Android系统中,Launcher是用户与设备交互的主要入口,它负责显示桌面、应用程序快捷方式以及小部件。在Android 6.0(Marshmallow)版本中,开发者对Launcher3进行了重大改进,其中包括引入了新的屏幕切换动画,...

    安卓Launcher桌面相关-带注释的Launcher3.rar

    "安卓Launcher桌面相关-带注释的Launcher3.rar"是一个包含源码的压缩包,主要聚焦于Android系统中的Launcher应用开发。Launcher3是Android默认的主屏幕应用,它提供了用户与设备之间的交互界面,包括应用快捷方式、...

Global site tag (gtag.js) - Google Analytics