您的位置:首页 > 其它

通过Launcher里的WorkSpace完成桌面的3D转屏效果

2011-07-18 15:47 441 查看
大家复制起来研究太麻烦,要我上传附件,已经上传了,附件里面的改动比较大而且注释不那么详细了,
出于多效率的考虑,没有用多线程了。下面提到的问题也都已解决,有什么好的建议大家再提出来一起讨论。



/*
这个workspace可以看做一个整体,X坐标上的范围是0-960
它共有3页,每个页即为一个child,每个child里面都有很多单元格,单元格中可以放置shortcut,
active folder, widget,他们分别会横向纵向占用不同的单元格数。
通过使用ScrollTo(int,int)这个方法可以把workspace这个整体移动,来显示不同的页面
比如:
ScrollTo(0,0) 为第一页
ScrollTo(320,0) 为第二页
ScrollTo(640,0) 为第三页
如果有更多页
ScrollTo(640,0) 为第四页
ScrollTo(960,0) 为第五页
.
.
.
其实页面上的被添加了组件后,这些组件我们看不见,
但是你点击某些看不见的“空位置”也是可以进入。
比如我们在中间页的左上角添加了一个短信的shortcut,如果不调用
drawChild(canvas, getChildAt(1), drawingTime)或者绘制出来我们是
看不见这个icon的,但是点击屏幕左上角却可以进入短信。
流程:
1.得到3个页的bitmap,页面上一有变化就重新得到bitmap
2.拖动屏幕时让屏幕不滑动也不按原始方式换页,而进行相应
的两个bitmap的变换操作来达到3D效果(不用GL,这样可以更有效率)
3.通过拖动的起始和结束坐标判断是否换页,应该如何换页
4.由于使用drawChild()把icon画到页上的时候,在进行2个bitmap的变换达到3D效果时
图像会出现从叠,故没有使用它,而是使用Canvas.drawBitmap()把相应bitmap张贴到
相应的页上,这样可以我们就可以知道屏幕的何处有何应用图标了
背景还没做好,准备搞个全黑,转的时候的3个Bitmap的背景搞成桌面背景,这样用户
还可以更换,3D效果有了,但需要改善
希望大家把自己的研究成果都分享出来,大家共同学习,共同进步
下面修改过的代码基都加以注释
*/
package com.android.launcher;
import java.util.ArrayList;
import android.app.WallpaperManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.Scroller;
import android.widget.TextView;
public class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller,Runnable {
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 = 1000;
private int mDefaultScreen;
private final WallpaperManager mWallpaperManager;
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 DragController mDragger;

/**
* 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;
private boolean mLocked;
private int mTouchSlop;
private int mMaximumVelocity;
final Rect mDrawerBounds = new Rect();
final Rect mClipBounds = new Rect();
int mDrawerContentHeight;
int mDrawerContentWidth;
//有3页,因此定义三个Bitmap用作3次截屏
private Bitmap[] s=new Bitmap[3];
//定义图片的大小
private float width=280;
private float height=380;
//定义矩阵和矩阵被绘制的方式,矩阵被用来做变换来让2张图片达到3D效果
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Matrix mMatrix = new Matrix();
//用作绘制完成3D的参数
private float key=0.0f;
//当前手在屏幕上的X坐标值,通过它判断2张图片要如何绘制
private float currentX=0;
//判断拖动屏幕时的拖动方向,大于0为向右拖,小于0为向左拖
private float mdirection=0;
//当拖动屏幕时,手刚接触到屏幕时的坐标,可以用来计算方向和跨度
private float startDragCoor=0;
//用来得到startDragCoor时做判定
boolean flag=true;
public Workspace(Context context, AttributeSet attrs) {
this(context, attrs, 0);
//设为true,因为下面要截图操作
setDrawingCacheEnabled(true);
setDrawingCacheQuality(DRAWING_CACHE_QUALITY_HIGH);
}
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==1
mDefaultScreen = a.getInt(R.styleable.Workspace_defaultScreen, 1);
a.recycle();

//设为true,因为下面要截图操作
setDrawingCacheEnabled(true);

initWorkspace();

//新开一个线程,在拖动屏幕时更新 currentX 坐标并刷新屏幕,让2张图片变换达到3D效果
new Thread(this).start();
}
private void initWorkspace() {
mScroller = new Scroller(getContext());
mCurrentScreen = mDefaultScreen;
Launcher.setScreen(mCurrentScreen);
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) {
super.addView(child);
}
@Override
public void addView(View child, int index) {
super.addView(child, index);
}
@Override
public void addView(View child, int width, int height) {
super.addView(child, width, height);
}
@Override
public void addView(View child, LayoutParams params) {
super.addView(child, params);
}
Folder getOpenFolder() {
CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen);
int count = currentScreen.getChildCount();
for (int i = 0; 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 getOpenFolders() {
final int screens = getChildCount();
ArrayList folders = new ArrayList(screens);
for (int screen = 0; screen
CellLayout currentScreen = (CellLayout) getChildAt(screen);
int count = currentScreen.getChildCount();
for (int i = 0; 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;
}
//可查看当前是哪个页,0,1, 2
int getCurrentScreen() {
return mCurrentScreen;
}
//通过scrollTo(int,int)这个方法来移动动屏幕,让它到达某个页面
//第一个参数为X坐标,第二个参数为Y坐标,由于有3页,故X范围是0 - 320*3
//如果把参数设置成(0,0)则当前为第一页,(320,0)为第二页,(640,0)为第三页
void setCurrentScreen(int currentScreen) {
clearVacantCache();
mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
scrollTo(mCurrentScreen * getWidth(), 0);
Log.d("Launcer D","Here we go");
invalidate();
}
void addInCurrentScreen(View child, int x, int y, int spanX, int spanY) {
addInScreen(child, mCurrentScreen, x, y, spanX, spanY, false);
}
void addInCurrentScreen(View child, int x, int y, int spanX, int spanY, boolean insert) {
addInScreen(child, mCurrentScreen, x, y, spanX, spanY, insert);
}
void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
addInScreen(child, screen, x, y, spanX, spanY, false);
}
void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
if (screen = getChildCount()) {
throw new IllegalStateException("The screen must be >= 0 and
}
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.setOnLongClickListener(mLongClickListener);
}
}

void addWidget(View view, Widget widget, boolean insert) {
addInScreen(view, widget.screen, widget.cellX, widget.cellY, widget.spanX,
widget.spanY, insert);
}
CellLayout.CellInfo findAllVacantCells(boolean[] occupied) {
CellLayout group = (CellLayout) getChildAt(mCurrentScreen);
if (group != null) {
return group.findAllVacantCells(occupied, null);
}
return null;
}

CellLayout.CellInfo findAllVacantCellsFromModel() {
CellLayout group = (CellLayout) getChildAt(mCurrentScreen);
if (group != null) {
int countX = group.getCountX();
int countY = group.getCountY();
boolean occupied[][] = new boolean[countX][countY];
Launcher.getModel().findAllOccupiedCells(occupied, countX, countY, mCurrentScreen);
return group.findAllVacantCellsFromOccupied(occupied, countX, countY);
}
return null;
}

private void clearVacantCache() {
if (mVacantCache != null) {
mVacantCache.clearVacantCells();
mVacantCache = null;
}
}
@Override
public void setOnLongClickListener(OnLongClickListener l) {
mLongClickListener = l;
final int count = getChildCount();
for (int i = 0; i
getChildAt(i).setOnLongClickListener(l);
}
}
private void updateWallpaperOffset() {
updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
}
//当我们移动屏幕时,壁纸也会移动,但前提是壁纸一定要比页面大小大
private void updateWallpaperOffset(int scrollRange) {
mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );

//下面这个方法带两参数X Y, X should be 0.0-1.0,if there are 3 screens
// X can be 0.0 0.5 1.0, to represents the 3 screens
mWallpaperManager.setWallpaperOffsets(getWindowToken(), mScrollX / (float) scrollRange, 0);
}

本文转载至: http://www.eoeandroid.com/thread-27079-1-2.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: