mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-01 00:06:47 +00:00
Allow for NxM layout and in-place rotation of items on homescreen.
Currently, rotation is disabled as designs are still in flux, but the NxM grid is enabled (8x4). Change-Id: I0026f88c674719e3d67de6d6d481d2d4cd606362
This commit is contained in:
@@ -16,36 +16,44 @@
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.app.WallpaperManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.LayoutAnimationController;
|
||||
|
||||
import com.android.launcher.R;
|
||||
|
||||
public class CellLayout extends ViewGroup {
|
||||
static final String TAG = "CellLayout";
|
||||
|
||||
private boolean mPortrait;
|
||||
|
||||
private int mCellWidth;
|
||||
private int mCellHeight;
|
||||
|
||||
|
||||
private int mLongAxisStartPadding;
|
||||
private int mLongAxisEndPadding;
|
||||
|
||||
private int mShortAxisStartPadding;
|
||||
private int mShortAxisEndPadding;
|
||||
|
||||
private int mLeftPadding;
|
||||
private int mRightPadding;
|
||||
private int mTopPadding;
|
||||
private int mBottomPadding;
|
||||
|
||||
private int mShortAxisCells;
|
||||
private int mLongAxisCells;
|
||||
|
||||
@@ -54,7 +62,7 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
private final Rect mRect = new Rect();
|
||||
private final CellInfo mCellInfo = new CellInfo();
|
||||
|
||||
|
||||
int[] mCellXY = new int[2];
|
||||
boolean[][] mOccupied;
|
||||
|
||||
@@ -62,8 +70,8 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
private boolean mDirtyTag;
|
||||
private boolean mLastDownOnOccupiedCell = false;
|
||||
|
||||
private final WallpaperManager mWallpaperManager;
|
||||
|
||||
private final WallpaperManager mWallpaperManager;
|
||||
|
||||
public CellLayout(Context context) {
|
||||
this(context, null);
|
||||
@@ -79,16 +87,16 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
mCellWidth = a.getDimensionPixelSize(R.styleable.CellLayout_cellWidth, 10);
|
||||
mCellHeight = a.getDimensionPixelSize(R.styleable.CellLayout_cellHeight, 10);
|
||||
|
||||
mLongAxisStartPadding =
|
||||
|
||||
mLongAxisStartPadding =
|
||||
a.getDimensionPixelSize(R.styleable.CellLayout_longAxisStartPadding, 10);
|
||||
mLongAxisEndPadding =
|
||||
mLongAxisEndPadding =
|
||||
a.getDimensionPixelSize(R.styleable.CellLayout_longAxisEndPadding, 10);
|
||||
mShortAxisStartPadding =
|
||||
a.getDimensionPixelSize(R.styleable.CellLayout_shortAxisStartPadding, 10);
|
||||
mShortAxisEndPadding =
|
||||
mShortAxisEndPadding =
|
||||
a.getDimensionPixelSize(R.styleable.CellLayout_shortAxisEndPadding, 10);
|
||||
|
||||
|
||||
mShortAxisCells = a.getInt(R.styleable.CellLayout_shortAxisCells, 4);
|
||||
mLongAxisCells = a.getInt(R.styleable.CellLayout_longAxisCells, 4);
|
||||
|
||||
@@ -96,14 +104,6 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
setAlwaysDrawnWithCacheEnabled(false);
|
||||
|
||||
if (mOccupied == null) {
|
||||
if (mPortrait) {
|
||||
mOccupied = new boolean[mShortAxisCells][mLongAxisCells];
|
||||
} else {
|
||||
mOccupied = new boolean[mLongAxisCells][mShortAxisCells];
|
||||
}
|
||||
}
|
||||
|
||||
mWallpaperManager = WallpaperManager.getInstance(getContext());
|
||||
}
|
||||
|
||||
@@ -132,14 +132,24 @@ public class CellLayout extends ViewGroup {
|
||||
return mPortrait ? mLongAxisCells : mShortAxisCells;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
// Takes canonical layout parameters
|
||||
public boolean addViewToCellLayout(View child, int index, int childId, LayoutParams params) {
|
||||
final LayoutParams lp = params;
|
||||
|
||||
// Generate an id for each view, this assumes we have at most 256x256 cells
|
||||
// per workspace screen
|
||||
final LayoutParams lp = (LayoutParams) params;
|
||||
child.setId(((getId() & 0xFF) << 16) | (lp.cellX & 0xFF) << 8 | (lp.cellY & 0xFF));
|
||||
if (lp.cellX >= 0 && lp.cellX <= getCountX() - 1 && lp.cellY >= 0 && lp.cellY <= getCountY() - 1) {
|
||||
// If the horizontal or vertical span is set to -1, it is taken to
|
||||
// mean that it spans the extent of the CellLayout
|
||||
if (lp.cellHSpan < 0) lp.cellHSpan = getCountX();
|
||||
if (lp.cellVSpan < 0) lp.cellVSpan = getCountY();
|
||||
|
||||
super.addView(child, index, params);
|
||||
child.setId(childId);
|
||||
|
||||
addView(child, index, lp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,7 +195,7 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mLastDownOnOccupiedCell = found;
|
||||
|
||||
if (!found) {
|
||||
@@ -217,6 +227,7 @@ public class CellLayout extends ViewGroup {
|
||||
setTag(cellInfo);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
final int action = ev.getAction();
|
||||
@@ -256,8 +267,8 @@ public class CellLayout extends ViewGroup {
|
||||
return info;
|
||||
}
|
||||
|
||||
private static void findIntersectingVacantCells(CellInfo cellInfo, int x, int y,
|
||||
int xCount, int yCount, boolean[][] occupied) {
|
||||
private static void findIntersectingVacantCells(CellInfo cellInfo, int x,
|
||||
int y, int xCount, int yCount, boolean[][] occupied) {
|
||||
|
||||
cellInfo.maxVacantSpanX = Integer.MIN_VALUE;
|
||||
cellInfo.maxVacantSpanXSpanY = Integer.MIN_VALUE;
|
||||
@@ -392,21 +403,21 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
// Assume the caller will perform their own cell searching, otherwise we
|
||||
// risk causing an unnecessary rebuild after findCellForSpan()
|
||||
|
||||
|
||||
return cellInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a point, return the cell that strictly encloses that point
|
||||
* Given a point, return the cell that strictly encloses that point
|
||||
* @param x X coordinate of the point
|
||||
* @param y Y coordinate of the point
|
||||
* @param result Array of 2 ints to hold the x and y coordinate of the cell
|
||||
*/
|
||||
void pointToCellExact(int x, int y, int[] result) {
|
||||
final boolean portrait = mPortrait;
|
||||
|
||||
final int hStartPadding = portrait ? mShortAxisStartPadding : mLongAxisStartPadding;
|
||||
final int vStartPadding = portrait ? mLongAxisStartPadding : mShortAxisStartPadding;
|
||||
|
||||
final int hStartPadding = getLeftPadding();
|
||||
final int vStartPadding = getTopPadding();
|
||||
|
||||
result[0] = (x - hStartPadding) / (mCellWidth + mWidthGap);
|
||||
result[1] = (y - vStartPadding) / (mCellHeight + mHeightGap);
|
||||
@@ -419,7 +430,7 @@ public class CellLayout extends ViewGroup {
|
||||
if (result[1] < 0) result[1] = 0;
|
||||
if (result[1] >= yAxis) result[1] = yAxis - 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a point, return the cell that most closely encloses that point
|
||||
* @param x X coordinate of the point
|
||||
@@ -432,18 +443,15 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Given a cell coordinate, return the point that represents the upper left corner of that cell
|
||||
*
|
||||
* @param cellX X coordinate of the cell
|
||||
*
|
||||
* @param cellX X coordinate of the cell
|
||||
* @param cellY Y coordinate of the cell
|
||||
*
|
||||
*
|
||||
* @param result Array of 2 ints to hold the x and y coordinate of the point
|
||||
*/
|
||||
void cellToPoint(int cellX, int cellY, int[] result) {
|
||||
final boolean portrait = mPortrait;
|
||||
|
||||
final int hStartPadding = portrait ? mShortAxisStartPadding : mLongAxisStartPadding;
|
||||
final int vStartPadding = portrait ? mLongAxisStartPadding : mShortAxisStartPadding;
|
||||
|
||||
final int hStartPadding = getLeftPadding();
|
||||
final int vStartPadding = getTopPadding();
|
||||
|
||||
result[0] = hStartPadding + cellX * (mCellWidth + mWidthGap);
|
||||
result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap);
|
||||
@@ -458,92 +466,117 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
|
||||
int getLeftPadding() {
|
||||
return mPortrait ? mShortAxisStartPadding : mLongAxisStartPadding;
|
||||
return mLeftPadding;
|
||||
}
|
||||
|
||||
int getTopPadding() {
|
||||
return mPortrait ? mLongAxisStartPadding : mShortAxisStartPadding;
|
||||
return mTopPadding;
|
||||
}
|
||||
|
||||
int getRightPadding() {
|
||||
return mPortrait ? mShortAxisEndPadding : mLongAxisEndPadding;
|
||||
return mRightPadding;
|
||||
}
|
||||
|
||||
int getBottomPadding() {
|
||||
return mPortrait ? mLongAxisEndPadding : mShortAxisEndPadding;
|
||||
return mBottomPadding;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// TODO: currently ignoring padding
|
||||
|
||||
|
||||
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
|
||||
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
|
||||
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
|
||||
if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
|
||||
throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
|
||||
}
|
||||
|
||||
final int shortAxisCells = mShortAxisCells;
|
||||
final int longAxisCells = mLongAxisCells;
|
||||
final int longAxisStartPadding = mLongAxisStartPadding;
|
||||
final int longAxisEndPadding = mLongAxisEndPadding;
|
||||
final int shortAxisStartPadding = mShortAxisStartPadding;
|
||||
final int shortAxisEndPadding = mShortAxisEndPadding;
|
||||
final int cellWidth = mCellWidth;
|
||||
final int cellHeight = mCellHeight;
|
||||
|
||||
mPortrait = heightSpecSize > widthSpecSize;
|
||||
boolean portrait = heightSpecSize > widthSpecSize;
|
||||
if (portrait != mPortrait || mOccupied == null) {
|
||||
if (portrait) {
|
||||
mOccupied = new boolean[mShortAxisCells][mLongAxisCells];
|
||||
} else {
|
||||
mOccupied = new boolean[mLongAxisCells][mShortAxisCells];
|
||||
}
|
||||
}
|
||||
mPortrait = portrait;
|
||||
|
||||
int numShortGaps = shortAxisCells - 1;
|
||||
int numLongGaps = longAxisCells - 1;
|
||||
|
||||
if (mPortrait) {
|
||||
int vSpaceLeft = heightSpecSize - longAxisStartPadding - longAxisEndPadding
|
||||
- (cellHeight * longAxisCells);
|
||||
int vSpaceLeft = heightSpecSize - mLongAxisStartPadding
|
||||
- mLongAxisEndPadding - (cellHeight * longAxisCells);
|
||||
mHeightGap = vSpaceLeft / numLongGaps;
|
||||
|
||||
int hSpaceLeft = widthSpecSize - shortAxisStartPadding - shortAxisEndPadding
|
||||
- (cellWidth * shortAxisCells);
|
||||
int hSpaceLeft = widthSpecSize - mShortAxisStartPadding
|
||||
- mShortAxisEndPadding - (cellWidth * shortAxisCells);
|
||||
if (numShortGaps > 0) {
|
||||
mWidthGap = hSpaceLeft / numShortGaps;
|
||||
} else {
|
||||
mWidthGap = 0;
|
||||
}
|
||||
|
||||
if (LauncherApplication.isInPlaceRotationEnabled()) {
|
||||
mWidthGap = mHeightGap = Math.min(mHeightGap, mWidthGap);
|
||||
mLeftPadding = mRightPadding = (widthSpecSize - cellWidth
|
||||
* shortAxisCells - (shortAxisCells - 1) * mWidthGap) / 2;
|
||||
mTopPadding = mBottomPadding = (heightSpecSize - cellHeight
|
||||
* longAxisCells - (longAxisCells - 1) * mHeightGap) / 2;
|
||||
} else {
|
||||
mLeftPadding = mShortAxisStartPadding;
|
||||
mRightPadding = mShortAxisEndPadding;
|
||||
mTopPadding = mLongAxisStartPadding;
|
||||
mBottomPadding = mLongAxisEndPadding;
|
||||
}
|
||||
} else {
|
||||
int hSpaceLeft = widthSpecSize - longAxisStartPadding - longAxisEndPadding
|
||||
- (cellWidth * longAxisCells);
|
||||
int hSpaceLeft = widthSpecSize - mLongAxisStartPadding
|
||||
- mLongAxisEndPadding - (cellWidth * longAxisCells);
|
||||
mWidthGap = hSpaceLeft / numLongGaps;
|
||||
|
||||
int vSpaceLeft = heightSpecSize - shortAxisStartPadding - shortAxisEndPadding
|
||||
- (cellHeight * shortAxisCells);
|
||||
int vSpaceLeft = heightSpecSize - mShortAxisStartPadding
|
||||
- mShortAxisEndPadding - (cellHeight * shortAxisCells);
|
||||
if (numShortGaps > 0) {
|
||||
mHeightGap = vSpaceLeft / numShortGaps;
|
||||
} else {
|
||||
mHeightGap = 0;
|
||||
}
|
||||
|
||||
if (LauncherApplication.isScreenXLarge()) {
|
||||
mWidthGap = mHeightGap = Math.min(mHeightGap, mWidthGap);
|
||||
mLeftPadding = mRightPadding = (widthSpecSize - cellWidth
|
||||
* longAxisCells - (longAxisCells - 1) * mWidthGap) / 2 ;
|
||||
mTopPadding = mBottomPadding = (heightSpecSize - cellHeight
|
||||
* shortAxisCells - (shortAxisCells - 1) * mHeightGap) / 2;
|
||||
} else {
|
||||
mLeftPadding = mLongAxisStartPadding;
|
||||
mRightPadding = mLongAxisEndPadding;
|
||||
mTopPadding = mShortAxisStartPadding;
|
||||
mBottomPadding = mShortAxisEndPadding;
|
||||
}
|
||||
}
|
||||
|
||||
int count = getChildCount();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap,
|
||||
mLeftPadding, mTopPadding);
|
||||
|
||||
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width,
|
||||
MeasureSpec.EXACTLY);
|
||||
int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
|
||||
MeasureSpec.EXACTLY);
|
||||
|
||||
if (mPortrait) {
|
||||
lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap, shortAxisStartPadding,
|
||||
longAxisStartPadding);
|
||||
} else {
|
||||
lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap, longAxisStartPadding,
|
||||
shortAxisStartPadding);
|
||||
}
|
||||
|
||||
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
|
||||
int childheightMeasureSpec =
|
||||
MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
|
||||
child.measure(childWidthMeasureSpec, childheightMeasureSpec);
|
||||
}
|
||||
|
||||
@@ -596,7 +629,7 @@ public class CellLayout extends ViewGroup {
|
||||
/**
|
||||
* Find a vacant area that will fit the given bounds nearest the requested
|
||||
* cell location. Uses Euclidean distance to score multiple vacant areas.
|
||||
*
|
||||
*
|
||||
* @param pixelX The X location at which you want to search for a vacant area.
|
||||
* @param pixelY The Y location at which you want to search for a vacant area.
|
||||
* @param spanX Horizontal span of the object.
|
||||
@@ -608,12 +641,12 @@ public class CellLayout extends ViewGroup {
|
||||
*/
|
||||
int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY,
|
||||
CellInfo vacantCells, int[] recycle) {
|
||||
|
||||
|
||||
// Keep track of best-scoring drop area
|
||||
final int[] bestXY = recycle != null ? recycle : new int[2];
|
||||
final int[] cellXY = mCellXY;
|
||||
double bestDistance = Double.MAX_VALUE;
|
||||
|
||||
|
||||
// Bail early if vacant cells aren't valid
|
||||
if (!vacantCells.valid) {
|
||||
return null;
|
||||
@@ -623,17 +656,17 @@ public class CellLayout extends ViewGroup {
|
||||
final int size = vacantCells.vacantCells.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final CellInfo.VacantCell cell = vacantCells.vacantCells.get(i);
|
||||
|
||||
|
||||
// Reject if vacant cell isn't our exact size
|
||||
if (cell.spanX != spanX || cell.spanY != spanY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Score is center distance from requested pixel
|
||||
cellToPoint(cell.cellX, cell.cellY, cellXY);
|
||||
|
||||
double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2) +
|
||||
Math.pow(cellXY[1] - pixelY, 2));
|
||||
|
||||
double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
|
||||
+ Math.pow(cellXY[1] - pixelY, 2));
|
||||
if (distance <= bestDistance) {
|
||||
bestDistance = distance;
|
||||
bestXY[0] = cell.cellX;
|
||||
@@ -641,25 +674,22 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
// Return null if no suitable location found
|
||||
// Return null if no suitable location found
|
||||
if (bestDistance < Double.MAX_VALUE) {
|
||||
return bestXY;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drop a child at the specified position
|
||||
* Mark a child as having been dropped.
|
||||
*
|
||||
* @param child The child that is being dropped
|
||||
* @param targetXY Destination area to move to
|
||||
*/
|
||||
void onDropChild(View child, int[] targetXY) {
|
||||
void onDropChild(View child) {
|
||||
if (child != null) {
|
||||
LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
lp.cellX = targetXY[0];
|
||||
lp.cellY = targetXY[1];
|
||||
lp.isDragging = false;
|
||||
lp.dropped = true;
|
||||
mDragRect.setEmpty();
|
||||
@@ -678,7 +708,7 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Start dragging the specified child
|
||||
*
|
||||
*
|
||||
* @param child The child that is being dragged
|
||||
*/
|
||||
void onDragChild(View child) {
|
||||
@@ -686,13 +716,13 @@ public class CellLayout extends ViewGroup {
|
||||
lp.isDragging = true;
|
||||
mDragRect.setEmpty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drag a child over the specified position
|
||||
*
|
||||
*
|
||||
* @param child The child that is being dropped
|
||||
* @param cellX The child's new x cell location
|
||||
* @param cellY The child's new y cell location
|
||||
* @param cellY The child's new y cell location
|
||||
*/
|
||||
void onDragOverChild(View child, int cellX, int cellY) {
|
||||
int[] cellXY = mCellXY;
|
||||
@@ -701,39 +731,38 @@ public class CellLayout extends ViewGroup {
|
||||
cellToRect(cellXY[0], cellXY[1], lp.cellHSpan, lp.cellVSpan, mDragRect);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes a bounding rectangle for a range of cells
|
||||
*
|
||||
*
|
||||
* @param cellX X coordinate of upper left corner expressed as a cell position
|
||||
* @param cellY Y coordinate of upper left corner expressed as a cell position
|
||||
* @param cellHSpan Width in cells
|
||||
* @param cellHSpan Width in cells
|
||||
* @param cellVSpan Height in cells
|
||||
* @param dragRect Rectnagle into which to put the results
|
||||
*/
|
||||
public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF dragRect) {
|
||||
final boolean portrait = mPortrait;
|
||||
final int cellWidth = mCellWidth;
|
||||
final int cellHeight = mCellHeight;
|
||||
final int widthGap = mWidthGap;
|
||||
final int heightGap = mHeightGap;
|
||||
|
||||
final int hStartPadding = portrait ? mShortAxisStartPadding : mLongAxisStartPadding;
|
||||
final int vStartPadding = portrait ? mLongAxisStartPadding : mShortAxisStartPadding;
|
||||
|
||||
|
||||
final int hStartPadding = getLeftPadding();
|
||||
final int vStartPadding = getTopPadding();
|
||||
|
||||
int width = cellHSpan * cellWidth + ((cellHSpan - 1) * widthGap);
|
||||
int height = cellVSpan * cellHeight + ((cellVSpan - 1) * heightGap);
|
||||
|
||||
int x = hStartPadding + cellX * (cellWidth + widthGap);
|
||||
int y = vStartPadding + cellY * (cellHeight + heightGap);
|
||||
|
||||
|
||||
dragRect.set(x, y, x + width, y + height);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the required horizontal and vertical cell spans to always
|
||||
* Computes the required horizontal and vertical cell spans to always
|
||||
* fit the given rectangle.
|
||||
*
|
||||
*
|
||||
* @param width Width in pixels
|
||||
* @param height Height in pixels
|
||||
*/
|
||||
@@ -758,7 +787,7 @@ public class CellLayout extends ViewGroup {
|
||||
* @param vacant Holds the x and y coordinate of the vacant cell
|
||||
* @param spanX Horizontal cell span.
|
||||
* @param spanY Vertical cell span.
|
||||
*
|
||||
*
|
||||
* @return True if a vacant cell was found
|
||||
*/
|
||||
public boolean getVacantCell(int[] vacant, int spanX, int spanY) {
|
||||
@@ -852,6 +881,17 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
return new CellLayout.LayoutParams(p);
|
||||
}
|
||||
|
||||
public static class CellLayoutAnimationController extends LayoutAnimationController {
|
||||
public CellLayoutAnimationController(Animation animation, float delay) {
|
||||
super(animation, delay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getDelayForView(View view) {
|
||||
return (int) (Math.random() * 150);
|
||||
}
|
||||
}
|
||||
|
||||
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
|
||||
/**
|
||||
* Horizontal location of the item in the grid.
|
||||
@@ -876,7 +916,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
*/
|
||||
@ViewDebug.ExportedProperty
|
||||
public int cellVSpan;
|
||||
|
||||
|
||||
/**
|
||||
* Is this item currently being dragged
|
||||
*/
|
||||
@@ -902,7 +942,15 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
cellHSpan = 1;
|
||||
cellVSpan = 1;
|
||||
}
|
||||
|
||||
|
||||
public LayoutParams(LayoutParams source) {
|
||||
super(source);
|
||||
this.cellX = source.cellX;
|
||||
this.cellY = source.cellY;
|
||||
this.cellHSpan = source.cellHSpan;
|
||||
this.cellVSpan = source.cellVSpan;
|
||||
}
|
||||
|
||||
public LayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
|
||||
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
this.cellX = cellX;
|
||||
@@ -913,12 +961,12 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
|
||||
public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap,
|
||||
int hStartPadding, int vStartPadding) {
|
||||
|
||||
|
||||
final int myCellHSpan = cellHSpan;
|
||||
final int myCellVSpan = cellVSpan;
|
||||
final int myCellX = cellX;
|
||||
final int myCellY = cellY;
|
||||
|
||||
|
||||
width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
|
||||
leftMargin - rightMargin;
|
||||
height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
|
||||
@@ -927,14 +975,18 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
|
||||
y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "(" + this.cellX + ", " + this.cellY + ")";
|
||||
}
|
||||
}
|
||||
|
||||
static final class CellInfo implements ContextMenu.ContextMenuInfo {
|
||||
/**
|
||||
* See View.AttachInfo.InvalidateInfo for futher explanations about
|
||||
* the recycling mechanism. In this case, we recycle the vacant cells
|
||||
* instances because up to several hundreds can be instanciated when
|
||||
* the user long presses an empty cell.
|
||||
* See View.AttachInfo.InvalidateInfo for futher explanations about the
|
||||
* recycling mechanism. In this case, we recycle the vacant cells
|
||||
* instances because up to several hundreds can be instanciated when the
|
||||
* user long presses an empty cell.
|
||||
*/
|
||||
static final class VacantCell {
|
||||
int cellX;
|
||||
@@ -945,7 +997,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
// We can create up to 523 vacant cells on a 4x4 grid, 100 seems
|
||||
// like a reasonable compromise given the size of a VacantCell and
|
||||
// the fact that the user is not likely to touch an empty 4x4 grid
|
||||
// very often
|
||||
// very often
|
||||
private static final int POOL_LIMIT = 100;
|
||||
private static final Object sLock = new Object();
|
||||
|
||||
@@ -980,8 +1032,8 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VacantCell[x=" + cellX + ", y=" + cellY + ", spanX=" + spanX +
|
||||
", spanY=" + spanY + "]";
|
||||
return "VacantCell[x=" + cellX + ", y=" + cellY + ", spanX="
|
||||
+ spanX + ", spanY=" + spanY + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,7 +1056,9 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
final ArrayList<VacantCell> list = vacantCells;
|
||||
final int count = list.size();
|
||||
|
||||
for (int i = 0; i < count; i++) list.get(i).release();
|
||||
for (int i = 0; i < count; i++) {
|
||||
list.get(i).release();
|
||||
}
|
||||
|
||||
list.clear();
|
||||
}
|
||||
@@ -1078,15 +1132,17 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
if (clear) clearVacantCells();
|
||||
if (clear) {
|
||||
clearVacantCells();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Cell[view=" + (cell == null ? "null" : cell.getClass()) + ", x=" + cellX +
|
||||
", y=" + cellY + "]";
|
||||
return "Cell[view=" + (cell == null ? "null" : cell.getClass())
|
||||
+ ", x=" + cellX + ", y=" + cellY + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1094,5 +1150,3 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
return mLastDownOnOccupiedCell;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user