CellInfo findAllVacantCells(boolean[] occupiedCells, View ignoreView) { final boolean portrait = mPortrait; final int xCount = portrait ? mShortAxisCells : mLongAxisCells; final int yCount = portrait ? mLongAxisCells : mShortAxisCells; boolean[][] occupied = mOccupied; if (occupiedCells != null) { for (int y = 0; y < yCount; y++) { for (int x = 0; x < xCount; x++) { occupied[x][y] = occupiedCells[y * xCount + x]; } } } else { findOccupiedCells(xCount, yCount, occupied, ignoreView); } CellInfo cellInfo = new CellInfo(); cellInfo.cellX = -1; cellInfo.cellY = -1; cellInfo.spanY = 0; cellInfo.spanX = 0; cellInfo.maxVacantSpanX = Integer.MIN_VALUE; cellInfo.maxVacantSpanXSpanY = Integer.MIN_VALUE; cellInfo.maxVacantSpanY = Integer.MIN_VALUE; cellInfo.maxVacantSpanYSpanX = Integer.MIN_VALUE; cellInfo.screen = mCellInfo.screen; Rect current = cellInfo.current; for (int x = 0; x < xCount; x++) { for (int y = 0; y < yCount; y++) { if (!occupied[x][y]) { current.set(x, y, x, y); findVacantCell(current, xCount, yCount, occupied, cellInfo); occupied[x][y] = true; } } } cellInfo.valid = cellInfo.vacantCells.size() > 0; // Assume the caller will perform their own cell searching, otherwise we // risk causing an unnecessary rebuild after findCellForSpan() return cellInfo; }
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getAction(); final CellInfo cellInfo = mCellInfo; if (action == MotionEvent.ACTION_DOWN) { final Rect frame = mRect; final int x = (int) ev.getX() + mScrollX; final int y = (int) ev.getY() + mScrollY; final int count = getChildCount(); boolean found = false; for (int i = count - 1; i >= 0; i--) { final View child = getChildAt(i); if ((child.getVisibility()) == VISIBLE || child.getAnimation() != null) { child.getHitRect(frame); if (frame.contains(x, y)) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); cellInfo.cell = child; cellInfo.cellX = lp.cellX; cellInfo.cellY = lp.cellY; cellInfo.spanX = lp.cellHSpan; cellInfo.spanY = lp.cellVSpan; cellInfo.valid = true; found = true; mDirtyTag = false; break; } } } mLastDownOnOccupiedCell = found; if (!found) { int cellXY[] = mCellXY; pointToCellExact(x, y, cellXY); final boolean portrait = mPortrait; final int xCount = portrait ? mShortAxisCells : mLongAxisCells; final int yCount = portrait ? mLongAxisCells : mShortAxisCells; final boolean[][] occupied = mOccupied; findOccupiedCells(xCount, yCount, occupied, null); cellInfo.cell = null; cellInfo.cellX = cellXY[0]; cellInfo.cellY = cellXY[1]; cellInfo.spanX = 1; cellInfo.spanY = 1; cellInfo.valid = cellXY[0] >= 0 && cellXY[1] >= 0 && cellXY[0] < xCount && cellXY[1] < yCount && !occupied[cellXY[0]][cellXY[1]]; // Instead of finding the interesting vacant cells here, wait until a // caller invokes getTag() to retrieve the result. Finding the vacant // cells is a bit expensive and can generate many new objects, it's // therefore better to defer it until we know we actually need it. mDirtyTag = true; } setTag(cellInfo); } else if (action == MotionEvent.ACTION_UP) { cellInfo.cell = null; cellInfo.cellX = -1; cellInfo.cellY = -1; cellInfo.spanX = 0; cellInfo.spanY = 0; cellInfo.valid = false; mDirtyTag = false; setTag(cellInfo); } return false; }