private void setupContentDimensions(int count) { ArrayList<View> list = getItemsInReadingOrder(); int countX = mContent.getCountX(); int countY = mContent.getCountY(); boolean done = false; while (!done) { int oldCountX = countX; int oldCountY = countY; if (countX * countY < count) { // Current grid is too small, expand it if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) { countX++; } else if (countY < mMaxCountY) { countY++; } if (countY == 0) countY++; } else if ((countY - 1) * countX >= count && countY >= countX) { countY = Math.max(0, countY - 1); } else if ((countX - 1) * countY >= count) { countX = Math.max(0, countX - 1); } done = countX == oldCountX && countY == oldCountY; } mContent.setGridSize(countX, countY); arrangeChildren(list); }
protected boolean createAndAddShortcut(ShortcutInfo item) { final StyledTextFoo textView = (StyledTextFoo) mInflater.inflate(R.layout.application, this, false); textView.setCompoundDrawablesWithIntrinsicBounds( null, new FastBitmapDrawable(item.getIcon(mIconCache)), null, null); textView.setText(item.title); textView.setTag(item); textView.setOnClickListener(this); textView.setOnLongClickListener(this); // We need to check here to verify that the given item's location isn't already occupied // by another item. If it is, we need to find the next available slot and assign // it that position. This is an issue when upgrading from the old Folders implementation // which could contain an unlimited number of items. if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0 || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) { if (!findAndSetEmptyCells(item)) { return false; } } CellLayout.LayoutParams lp = new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY); boolean insert = false; textView.setOnKeyListener(new FolderKeyEventListener()); mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int) item.id, lp, true); return true; }
/** 向Folder添加ShortcutInfo */ protected boolean createAndAddShortcut(ShortcutInfo item) { final TextView textView = (TextView) mInflater.inflate(R.layout.application, this, false); textView.setCompoundDrawablesWithIntrinsicBounds( null, new FastBitmapDrawable(item.getIcon(mIconCache)), null, null); textView.setText(item.title); textView.setTag(item); textView.setOnClickListener(this); textView.setOnLongClickListener(this); // 检查这个地方是否被其他item占据 if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0 || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) { // 其实不应该发生 Log.e(TAG, "Folder order not properly persisted during bind"); if (!findAndSetEmptyCells(item)) { return false; } } CellLayout.LayoutParams lp = new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY); boolean insert = false; textView.setOnKeyListener(new FolderKeyEventListener()); mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int) item.id, lp, true); return true; }
private View getViewForInfo(ShortcutInfo item) { for (int j = 0; j < mContent.getCountY(); j++) { for (int i = 0; i < mContent.getCountX(); i++) { View v = mContent.getChildAt(i, j); if (v.getTag() == item) { return v; } } } return null; }
public ArrayList<View> getItemsInReadingOrder() { if (mItemsInvalidated) { mItemsInReadingOrder.clear(); for (int j = 0; j < mContent.getCountY(); j++) { for (int i = 0; i < mContent.getCountX(); i++) { View v = mContent.getChildAt(i, j); if (v != null) { mItemsInReadingOrder.add(v); } } } mItemsInvalidated = false; } return mItemsInReadingOrder; }
/** 左到右,上到下,为阅读顺序 */ public ArrayList<View> getItemsInReadingOrder(boolean includeCurrentDragItem) { if (mItemsInvalidated) { mItemsInReadingOrder.clear(); for (int j = 0; j < mContent.getCountY(); j++) { for (int i = 0; i < mContent.getCountX(); i++) { View v = mContent.getChildAt(i, j); if (v != null) { ShortcutInfo info = (ShortcutInfo) v.getTag(); if (info != mCurrentDragInfo || includeCurrentDragItem) { mItemsInReadingOrder.add(v); } } } } mItemsInvalidated = false; } return mItemsInReadingOrder; }
/** * Private helper method to find the next closest BubbleTextView or FolderIcon in the direction * delta on the next line. * * @param delta either -1 or 1 depending on the line and direction we want to search */ private static View getClosestIconOnLine( CellLayout layout, ViewGroup parent, View v, int lineDelta) { final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent); final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams(); final int cellCountY = layout.getCountY(); final int row = lp.cellY; final int newRow = row + lineDelta; if (0 <= newRow && newRow < cellCountY) { float closestDistance = Float.MAX_VALUE; int closestIndex = -1; int index = views.indexOf(v); int endIndex = (lineDelta < 0) ? -1 : views.size(); while (index != endIndex) { View newV = views.get(index); CellLayout.LayoutParams tmpLp = (CellLayout.LayoutParams) newV.getLayoutParams(); boolean satisfiesRow = (lineDelta < 0) ? (tmpLp.cellY < row) : (tmpLp.cellY > row); if (satisfiesRow && (newV instanceof BubbleTextView || newV instanceof FolderIcon)) { float tmpDistance = (float) Math.sqrt( Math.pow(tmpLp.cellX - lp.cellX, 2) + Math.pow(tmpLp.cellY - lp.cellY, 2)); if (tmpDistance < closestDistance) { closestIndex = index; closestDistance = tmpDistance; } } if (index <= endIndex) { ++index; } else { --index; } } if (closestIndex > -1) { return views.get(closestIndex); } } return null; }
protected View createAndAddShortcut(ShortcutInfo item) { final BubbleTextView textView = (BubbleTextView) mInflater.inflate(R.layout.folder_application, this, false); textView.applyFromShortcutInfo(item, mIconCache, false); int color = SettingsProvider.getInt( getContext(), SettingsProvider.FOLDER_ICON_TEXT_COLOR, getResources().getColor(R.color.folder_items_text_color)); textView.setTextColor(color); textView.setOnClickListener(this); textView.setOnLongClickListener(this); textView.setOnFocusChangeListener(mFocusIndicatorHandler); // We need to check here to verify that the given item's location isn't already occupied // by another item. if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0 || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) { // This shouldn't happen, log it. Log.e(TAG, "Folder order not properly persisted during bind"); if (!findAndSetEmptyCells(item)) { return null; } } CellLayout.LayoutParams lp = new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY); boolean insert = false; textView.setOnKeyListener(new FolderKeyEventListener()); mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int) item.id, lp, true); return textView; }
int getCellYFromOrder(int rank) { return hasVerticalHotseat() ? (mContent.getCountY() - (rank + 1)) : 0; }
/* Get the orientation invariant order of the item in the hotseat for persistence. */ int getOrderInHotseat(int x, int y) { return hasVerticalHotseat() ? (mContent.getCountY() - y - 1) : x; }
int getCellYFromOrder(int rank) { return mIsLandscape ? (mContent.getCountY() - (rank + 1)) : 0; }
/* Get the orientation invariant order of the item in the hotseat for persistence. */ int getOrderInHotseat(int x, int y) { return mIsLandscape ? (mContent.getCountY() - y - 1) : x; }
/** Based on the current deltas, we determine if and how to resize the widget. */ private void resizeWidgetIfNeeded(boolean onDismiss) { int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap(); int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap(); int deltaX = mDeltaX + mDeltaXAddOn; int deltaY = mDeltaY + mDeltaYAddOn; float hSpanIncF = 1.0f * deltaX / xThreshold - mRunningHInc; float vSpanIncF = 1.0f * deltaY / yThreshold - mRunningVInc; int hSpanInc = 0; int vSpanInc = 0; int cellXInc = 0; int cellYInc = 0; int countX = mCellLayout.getCountX(); int countY = mCellLayout.getCountY(); if (Math.abs(hSpanIncF) > RESIZE_THRESHOLD) { hSpanInc = Math.round(hSpanIncF); } if (Math.abs(vSpanIncF) > RESIZE_THRESHOLD) { vSpanInc = Math.round(vSpanIncF); } if (!onDismiss && (hSpanInc == 0 && vSpanInc == 0)) return; CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams(); int spanX = lp.cellHSpan; int spanY = lp.cellVSpan; int cellX = lp.useTmpCoords ? lp.tmpCellX : lp.cellX; int cellY = lp.useTmpCoords ? lp.tmpCellY : lp.cellY; int hSpanDelta = 0; int vSpanDelta = 0; // For each border, we bound the resizing based on the minimum width, and the maximum // expandability. if (mLeftBorderActive) { cellXInc = Math.max(-cellX, hSpanInc); cellXInc = Math.min(lp.cellHSpan - mMinHSpan, cellXInc); hSpanInc *= -1; hSpanInc = Math.min(cellX, hSpanInc); hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc); hSpanDelta = -hSpanInc; } else if (mRightBorderActive) { hSpanInc = Math.min(countX - (cellX + spanX), hSpanInc); hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc); hSpanDelta = hSpanInc; } if (mTopBorderActive) { cellYInc = Math.max(-cellY, vSpanInc); cellYInc = Math.min(lp.cellVSpan - mMinVSpan, cellYInc); vSpanInc *= -1; vSpanInc = Math.min(cellY, vSpanInc); vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc); vSpanDelta = -vSpanInc; } else if (mBottomBorderActive) { vSpanInc = Math.min(countY - (cellY + spanY), vSpanInc); vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc); vSpanDelta = vSpanInc; } mDirectionVector[0] = 0; mDirectionVector[1] = 0; // Update the widget's dimensions and position according to the deltas computed above if (mLeftBorderActive || mRightBorderActive) { spanX += hSpanInc; cellX += cellXInc; if (hSpanDelta != 0) { mDirectionVector[0] = mLeftBorderActive ? -1 : 1; } } if (mTopBorderActive || mBottomBorderActive) { spanY += vSpanInc; cellY += cellYInc; if (vSpanDelta != 0) { mDirectionVector[1] = mTopBorderActive ? -1 : 1; } } if (!onDismiss && vSpanDelta == 0 && hSpanDelta == 0) return; // We always want the final commit to match the feedback, so we make sure to use the // last used direction vector when committing the resize / reorder. if (onDismiss) { mDirectionVector[0] = mLastDirectionVector[0]; mDirectionVector[1] = mLastDirectionVector[1]; } else { mLastDirectionVector[0] = mDirectionVector[0]; mLastDirectionVector[1] = mDirectionVector[1]; } if (mCellLayout.createAreaForResize( cellX, cellY, spanX, spanY, mWidgetView, mDirectionVector, onDismiss)) { lp.tmpCellX = cellX; lp.tmpCellY = cellY; lp.cellHSpan = spanX; lp.cellVSpan = spanY; mRunningVInc += vSpanDelta; mRunningHInc += hSpanDelta; if (!onDismiss) { updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY); } } mWidgetView.requestLayout(); }