- 浏览: 106339 次
- 性别:
- 来自: 深圳
最新评论
-
ysc123shift:
给的东西,稍微欠完整。对于初学者,参考意义不大。
music player:一(歌词显示,LyricView,Canvas)---自动滚动 -
sunny09290:
楼主,请问当歌词太长,需要换行该怎么处理呢
music player:一(歌词显示,LyricView,Canvas)---自动滚动 -
zhongyuanceshi:
博主,GraphicsActivity这个类是你自己写的吧,T ...
music player:一(歌词显示,LyricView,Canvas)---自动滚动 -
huxinli:
汉语词典开发-assets,raw的InputStream数据流操作(文件分割合并) -
w1048499078:
能给我源代码 学习么 我邮箱是274633305@qq.c ...
android播放器(music player)源码分析5(在线播放功能)
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,供以学习和讨论。欢迎大家给以指正
评论
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;
}
}
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.)
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
根据需要吧,其实都是正对canvas的一个变换
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的一个页面,通过滑动来切换不同的主屏幕。 1. **ViewPager的基本使用** - 首先,我们需要在布局文件中添加ViewPager,并为其指定适配器。...
本压缩包文件"安卓Launcher桌面相关-实现类似桌面的单屏效果.rar"提供的内容可能包含了创建一个自定义桌面样式的源代码,帮助开发者了解和学习如何构建具有类似桌面单屏效果的应用。 首先,我们要理解"单屏效果"。...
"launcher 3D旋转参考实例"是一个关于如何在Android上实现3D旋转效果的示例项目,它展示了如何通过Eclipse IDE来创建一个具有动态旋转效果的启动器界面。这种特效可以提升用户体验,为应用程序增添视觉吸引力。 ...
"安卓Launcher桌面相关-Android实现图标拖拽"这个压缩包文件似乎包含了一些关于如何在Android Launcher中实现图标拖放功能的源代码或示例项目。下面将详细介绍Android Launcher桌面的原理以及实现图标拖拽的相关知识...
赠送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”可能包含了一些实现Android Launcher中拖拽效果的源代码和资源文件。由于描述中提到无法逐一验证所有内容,以下将详细解释Android Launcher中拖拽效果的...
junit-platform-launcher-1.7.0.jarjunit-platform-launcher-1.7.0.jar
launcher 3D旋转参考实例.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
junit-platform-launcher-1.6.2.jarjunit-platform-launcher-1.6.2.jarjunit-platform-launcher-1.6.2.jar
在Android系统中,Launcher是用户与手机交互的入口,它是一个桌面应用程序,负责展示应用程序快捷方式、小部件以及管理屏幕工作区。这个压缩包提供的"Android Launcher 桌面分页滑动代码"是一个适用于学生毕业设计的...
2. **BackgroundViewPager**:这个名词可能是指一个定制版的 ViewPager,专门用于处理桌面背景的滚动效果。常规的 ViewPager 只处理视图的切换,而 BackgroundViewPager 可能包含了对背景图像或者壁纸随着页面滑动的...
【Android Launcher 桌面开发详解】 在 Android 系统中,Launcher 是用户与设备交互的重要入口,它作为系统的桌面,展示着应用快捷方式、小部件以及桌面图标等元素。本教程将基于 Eclipse 开发环境,讲解如何创建一...
包含客户端 Launcher3 修改 包含服务端 OverlayScreen(可替换成你自己客需定制负一屏View) 基于android11.0 绝对好用,网上目前最...实现效果图 <img src="https://i.postimg.cc/g2phQy6y/Screen.gif" border="0" />
通过深入理解这份代码,你可以了解到Android桌面启动器的实现机制,尤其是分页滑动的效果。 1. **Android Launcher基本结构**: Android Launcher是基于Activity构建的,通常继承自`android.app.LauncherActivity`...
安卓超酷 3D 桌面 Next Launcher 3D Shell 中文版安卓超酷 3D 桌面 Next Launcher 3D Shell 中文版 告别平面背景、平面图标、平面体验,此刻开始,畅享全3D桌面旅程!加入百万用户,领先潮流,体验独特的操作和出色...
【Android项目源码-安卓Launcher原生桌面源码】是一个深入了解Android系统启动器(Launcher)工作原理的重要资源。源码提供了Android操作系统中的主屏幕和应用抽屉的实现细节,这对于Android开发者尤其是系统定制者...
开发工具 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开发工具 ...
### 修改Launcher让图标不显示在桌面或主菜单中的方法 #### 概述 在Android 2.3系统中,可以通过自定义Launcher应用来控制应用程序图标是否显示在桌面或主菜单中。这一操作对于定制化系统界面、提升用户体验等方面...
在Android系统中,Launcher是用户与设备交互的主要入口,它负责显示桌面、应用程序快捷方式以及小部件。在Android 6.0(Marshmallow)版本中,开发者对Launcher3进行了重大改进,其中包括引入了新的屏幕切换动画,...
本篇文章将深入探讨Launcher3的源码,特别是其循环翻页的实现原理,帮助开发者更好地理解和优化Android桌面应用。 首先,我们需要理解Launcher3的基本架构。Launcher3是一个Activity,它继承自PhoneWindowManager,...