summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r--src/com/android/launcher3/AppsCustomizePagedView.java10
-rw-r--r--src/com/android/launcher3/BubbleTextView.java27
-rw-r--r--src/com/android/launcher3/CellLayout.java185
-rw-r--r--src/com/android/launcher3/Cling.java8
-rw-r--r--src/com/android/launcher3/DragLayer.java7
-rw-r--r--src/com/android/launcher3/DynamicGrid.java478
-rw-r--r--src/com/android/launcher3/Folder.java50
-rw-r--r--src/com/android/launcher3/FolderIcon.java28
-rw-r--r--src/com/android/launcher3/Hotseat.java19
-rw-r--r--src/com/android/launcher3/Launcher.java62
-rw-r--r--src/com/android/launcher3/LauncherAppState.java28
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHostView.java1
-rw-r--r--src/com/android/launcher3/LauncherModel.java35
-rw-r--r--src/com/android/launcher3/LauncherProvider.java10
-rw-r--r--src/com/android/launcher3/PagedViewCellLayout.java8
-rw-r--r--src/com/android/launcher3/SearchDropTargetBar.java4
-rw-r--r--src/com/android/launcher3/ShortcutAndWidgetContainer.java25
-rw-r--r--src/com/android/launcher3/Utilities.java87
-rw-r--r--src/com/android/launcher3/WidgetPreviewLoader.java6
-rw-r--r--src/com/android/launcher3/Workspace.java95
20 files changed, 773 insertions, 400 deletions
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index dafa9b490..245d7eaf9 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -360,12 +360,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
Configuration.ORIENTATION_LANDSCAPE;
int maxCellCountX = Integer.MAX_VALUE;
int maxCellCountY = Integer.MAX_VALUE;
- if (LauncherAppState.getInstance().isScreenLarge()) {
- maxCellCountX = (isLandscape ? LauncherModel.getCellCountX() :
- LauncherModel.getCellCountY());
- maxCellCountY = (isLandscape ? LauncherModel.getCellCountY() :
- LauncherModel.getCellCountX());
- }
if (mMaxAppCellCountX > -1) {
maxCellCountX = Math.min(maxCellCountX, mMaxAppCellCountX);
}
@@ -1162,7 +1156,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// Note: We force a measure here to get around the fact that when we do layout calculations
// immediately after syncing, we don't have a proper width.
- int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+ int workspaceWidth = mLauncher.getWorkspace().getMeasuredWidth();
+ int widthSpec = MeasureSpec.makeMeasureSpec(Math.min(getMeasuredWidth(), workspaceWidth),
+ MeasureSpec.AT_MOST);
int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
layout.setMinimumWidth(getPageContentWidth());
layout.measure(widthSpec, heightSpec);
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 868e3acad..bb6903d43 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -25,6 +25,7 @@ import android.graphics.Region;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.MotionEvent;
import android.widget.TextView;
@@ -34,7 +35,6 @@ import android.widget.TextView;
* too aggressive.
*/
public class BubbleTextView extends TextView {
- static final float CORNER_RADIUS = 4.0f;
static final float SHADOW_LARGE_RADIUS = 4.0f;
static final float SHADOW_SMALL_RADIUS = 1.75f;
static final float SHADOW_Y_OFFSET = 2.0f;
@@ -55,6 +55,8 @@ public class BubbleTextView extends TextView {
private int mPressedOutlineColor;
private int mPressedGlowColor;
+ private boolean mIsTextVisible;
+
private boolean mBackgroundSizeChanged;
private Drawable mBackground;
@@ -76,6 +78,15 @@ public class BubbleTextView extends TextView {
init();
}
+ public void onFinishInflate() {
+ super.onFinishInflate();
+
+ // Ensure we are using the right text size
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize);
+ }
+
private void init() {
mLongPressHelper = new CheckLongPressHelper(this);
mBackground = getBackground();
@@ -326,6 +337,20 @@ public class BubbleTextView extends TextView {
if (mBackground != null) mBackground.setCallback(null);
}
+ public void setTextVisibility(boolean visible) {
+ Resources res = getResources();
+ if (visible) {
+ setTextColor(res.getColor(R.color.workspace_icon_text_color));
+ } else {
+ setTextColor(res.getColor(android.R.color.transparent));
+ }
+ mIsTextVisible = visible;
+ }
+
+ public boolean isTextVisible() {
+ return mIsTextVisible;
+ }
+
@Override
protected boolean onSetAlpha(int alpha) {
if (mPrevAlpha != alpha) {
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 86bc1b047..abc057c8d 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -191,11 +191,11 @@ public class CellLayout extends ViewGroup {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0);
- mCellWidth = a.getDimensionPixelSize(R.styleable.CellLayout_cellWidth, 10);
- mCellHeight = a.getDimensionPixelSize(R.styleable.CellLayout_cellHeight, 10);
- mWidthGap = mOriginalWidthGap = a.getDimensionPixelSize(R.styleable.CellLayout_widthGap, 0);
- mHeightGap = mOriginalHeightGap = a.getDimensionPixelSize(R.styleable.CellLayout_heightGap, 0);
- mMaxGap = a.getDimensionPixelSize(R.styleable.CellLayout_maxGap, 0);
+ mCellWidth = -1;
+ mCellHeight = -1;
+ mWidthGap = mOriginalWidthGap = 0;
+ mHeightGap = mOriginalHeightGap = 0;
+ mMaxGap = Integer.MAX_VALUE;
mCountX = LauncherModel.getCellCountX();
mCountY = LauncherModel.getCellCountY();
mOccupied = new boolean[mCountX][mCountY];
@@ -208,7 +208,9 @@ public class CellLayout extends ViewGroup {
setAlwaysDrawnWithCacheEnabled(false);
final Resources res = getResources();
- mHotseatScale = (res.getInteger(R.integer.hotseat_item_scale_percentage) / 100f);
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ mHotseatScale = (float) grid.hotseatIconSize / grid.iconSize;
mNormalBackground = res.getDrawable(R.drawable.homescreen_blue_normal_holo);
mActiveGlowBackground = res.getDrawable(R.drawable.homescreen_blue_strong_holo);
@@ -219,16 +221,13 @@ public class CellLayout extends ViewGroup {
res.getDimensionPixelSize(R.dimen.workspace_overscroll_drawable_padding);
mReorderHintAnimationMagnitude = (REORDER_HINT_MAGNITUDE *
- res.getDimensionPixelSize(R.dimen.app_icon_size));
+ grid.iconSizePx);
mNormalBackground.setFilterBitmap(true);
mActiveGlowBackground.setFilterBitmap(true);
// Initialize the data structures used for the drag visualization.
-
mEaseOutInterpolator = new DecelerateInterpolator(2.5f); // Quint ease out
-
-
mDragCell[0] = mDragCell[1] = -1;
for (int i = 0; i < mDragOutlines.length; i++) {
mDragOutlines[i] = new Rect(-1, -1, -1, -1);
@@ -289,33 +288,11 @@ public class CellLayout extends ViewGroup {
mShortcutsAndWidgets = new ShortcutAndWidgetContainer(context);
mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap,
- mCountX);
+ mCountX, mCountY);
addView(mShortcutsAndWidgets);
}
- static int widthInPortrait(Resources r, int numCells) {
- // We use this method from Workspace to figure out how many rows/columns Launcher should
- // have. We ignore the left/right padding on CellLayout because it turns out in our design
- // the padding extends outside the visible screen size, but it looked fine anyway.
- int cellWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
- int minGap = Math.min(r.getDimensionPixelSize(R.dimen.workspace_width_gap),
- r.getDimensionPixelSize(R.dimen.workspace_height_gap));
-
- return minGap * (numCells - 1) + cellWidth * numCells;
- }
-
- static int heightInLandscape(Resources r, int numCells) {
- // We use this method from Workspace to figure out how many rows/columns Launcher should
- // have. We ignore the left/right padding on CellLayout because it turns out in our design
- // the padding extends outside the visible screen size, but it looked fine anyway.
- int cellHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height);
- int minGap = Math.min(r.getDimensionPixelSize(R.dimen.workspace_width_gap),
- r.getDimensionPixelSize(R.dimen.workspace_height_gap));
-
- return minGap * (numCells - 1) + cellHeight * numCells;
- }
-
public void enableHardwareLayers() {
mShortcutsAndWidgets.setLayerType(LAYER_TYPE_HARDWARE, sPaint);
}
@@ -332,6 +309,13 @@ public class CellLayout extends ViewGroup {
return mIsHotseat ? mHotseatScale : 1.0f;
}
+ public void setCellDimensions(int width, int height) {
+ mCellWidth = width;
+ mCellHeight = height;
+ mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap,
+ mCountX, mCountY);
+ }
+
public void setGridSize(int x, int y) {
mCountX = x;
mCountY = y;
@@ -339,7 +323,7 @@ public class CellLayout extends ViewGroup {
mTmpOccupied = new boolean[mCountX][mCountY];
mTempRectStack.clear();
mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap,
- mCountX);
+ mCountX, mCountY);
requestLayout();
}
@@ -500,17 +484,21 @@ public class CellLayout extends ViewGroup {
int previewOffset = FolderRingAnimator.sPreviewSize;
// The folder outer / inner ring image(s)
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
for (int i = 0; i < mFolderOuterRings.size(); i++) {
FolderRingAnimator fra = mFolderOuterRings.get(i);
// Draw outer ring
Drawable d = FolderRingAnimator.sSharedOuterRingDrawable;
- int width = (int) fra.getOuterRingSize();
+ int width = (int) (fra.getOuterRingSize() * getChildrenScale());
int height = width;
cellToPoint(fra.mCellX, fra.mCellY, mTempLocation);
+ View child = getChildAt(fra.mCellX, fra.mCellY);
int centerX = mTempLocation[0] + mCellWidth / 2;
- int centerY = mTempLocation[1] + previewOffset / 2;
+ int centerY = mTempLocation[1] + previewOffset / 2 +
+ child.getPaddingTop() + grid.folderBackgroundOffset;
canvas.save();
canvas.translate(centerX - width / 2, centerY - height / 2);
@@ -520,12 +508,14 @@ public class CellLayout extends ViewGroup {
// Draw inner ring
d = FolderRingAnimator.sSharedInnerRingDrawable;
- width = (int) fra.getInnerRingSize();
+ width = (int) (fra.getInnerRingSize() * getChildrenScale());
height = width;
cellToPoint(fra.mCellX, fra.mCellY, mTempLocation);
+ child = getChildAt(fra.mCellX, fra.mCellY);
centerX = mTempLocation[0] + mCellWidth / 2;
- centerY = mTempLocation[1] + previewOffset / 2;
+ centerY = mTempLocation[1] + previewOffset / 2 +
+ child.getPaddingTop() + grid.folderBackgroundOffset;
canvas.save();
canvas.translate(centerX - width / 2, centerY - width / 2);
d.setBounds(0, 0, width, height);
@@ -539,8 +529,10 @@ public class CellLayout extends ViewGroup {
int height = d.getIntrinsicHeight();
cellToPoint(mFolderLeaveBehindCell[0], mFolderLeaveBehindCell[1], mTempLocation);
+ View child = getChildAt(mFolderLeaveBehindCell[0], mFolderLeaveBehindCell[1]);
int centerX = mTempLocation[0] + mCellWidth / 2;
- int centerY = mTempLocation[1] + previewOffset / 2;
+ int centerY = mTempLocation[1] + previewOffset / 2 +
+ child.getPaddingTop() + grid.folderBackgroundOffset;
canvas.save();
canvas.translate(centerX - width / 2, centerY - width / 2);
@@ -620,6 +612,7 @@ public class CellLayout extends ViewGroup {
public void setIsHotseat(boolean isHotseat) {
mIsHotseat = isHotseat;
+ mShortcutsAndWidgets.setIsHotseat(isHotseat);
}
public boolean addViewToCellLayout(View child, int index, int childId, LayoutParams params,
@@ -631,11 +624,7 @@ public class CellLayout extends ViewGroup {
BubbleTextView bubbleChild = (BubbleTextView) child;
Resources res = getResources();
- if (mIsHotseat) {
- bubbleChild.setTextColor(res.getColor(android.R.color.transparent));
- } else {
- bubbleChild.setTextColor(res.getColor(R.color.workspace_icon_text_color));
- }
+ bubbleChild.setTextVisibility(!mIsHotseat);
}
child.setScaleX(getChildrenScale());
@@ -940,49 +929,10 @@ public class CellLayout extends ViewGroup {
static void getMetrics(Rect metrics, Resources res, int measureWidth, int measureHeight,
int countX, int countY, int orientation) {
- int numWidthGaps = countX - 1;
- int numHeightGaps = countY - 1;
-
- int widthGap;
- int heightGap;
- int cellWidth;
- int cellHeight;
- int paddingLeft;
- int paddingRight;
- int paddingTop;
- int paddingBottom;
-
- int maxGap = res.getDimensionPixelSize(R.dimen.workspace_max_gap);
- if (orientation == LANDSCAPE) {
- cellWidth = res.getDimensionPixelSize(R.dimen.workspace_cell_width_land);
- cellHeight = res.getDimensionPixelSize(R.dimen.workspace_cell_height_land);
- widthGap = res.getDimensionPixelSize(R.dimen.workspace_width_gap_land);
- heightGap = res.getDimensionPixelSize(R.dimen.workspace_height_gap_land);
- paddingLeft = res.getDimensionPixelSize(R.dimen.cell_layout_left_padding_land);
- paddingRight = res.getDimensionPixelSize(R.dimen.cell_layout_right_padding_land);
- paddingTop = res.getDimensionPixelSize(R.dimen.cell_layout_top_padding_land);
- paddingBottom = res.getDimensionPixelSize(R.dimen.cell_layout_bottom_padding_land);
- } else {
- // PORTRAIT
- cellWidth = res.getDimensionPixelSize(R.dimen.workspace_cell_width_port);
- cellHeight = res.getDimensionPixelSize(R.dimen.workspace_cell_height_port);
- widthGap = res.getDimensionPixelSize(R.dimen.workspace_width_gap_port);
- heightGap = res.getDimensionPixelSize(R.dimen.workspace_height_gap_port);
- paddingLeft = res.getDimensionPixelSize(R.dimen.cell_layout_left_padding_port);
- paddingRight = res.getDimensionPixelSize(R.dimen.cell_layout_right_padding_port);
- paddingTop = res.getDimensionPixelSize(R.dimen.cell_layout_top_padding_port);
- paddingBottom = res.getDimensionPixelSize(R.dimen.cell_layout_bottom_padding_port);
- }
-
- if (widthGap < 0 || heightGap < 0) {
- int hSpace = measureWidth - paddingLeft - paddingRight;
- int vSpace = measureHeight - paddingTop - paddingBottom;
- int hFreeSpace = hSpace - (countX * cellWidth);
- int vFreeSpace = vSpace - (countY * cellHeight);
- widthGap = Math.min(maxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
- heightGap = Math.min(maxGap, numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
- }
- metrics.set(cellWidth, cellHeight, widthGap, heightGap);
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ metrics.set(grid.calculateCellWidth(measureWidth, countX),
+ grid.calculateCellHeight(measureHeight, countY), 0, 0);
}
public void setFixedSize(int width, int height) {
@@ -992,14 +942,22 @@ public class CellLayout extends ViewGroup {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
+ int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+ if (mCellWidth < 0 || mCellHeight < 0) {
+ mCellWidth = grid.calculateCellWidth(widthSize, mCountX);
+ mCellHeight = grid.calculateCellHeight(heightSize, mCountY);
+ mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap,
+ mHeightGap, mCountX, mCountY);
+ }
- int newWidth = widthSpecSize;
- int newHeight = heightSpecSize;
+ int newWidth = widthSize;
+ int newHeight = heightSize;
if (mFixedWidth > 0 && mFixedHeight > 0) {
newWidth = mFixedWidth;
newHeight = mFixedHeight;
@@ -1011,29 +969,21 @@ public class CellLayout extends ViewGroup {
int numHeightGaps = mCountY - 1;
if (mOriginalWidthGap < 0 || mOriginalHeightGap < 0) {
- int hSpace = widthSpecSize - getPaddingLeft() - getPaddingRight();
- int vSpace = heightSpecSize - getPaddingTop() - getPaddingBottom();
+ int hSpace = widthSize - getPaddingLeft() - getPaddingRight();
+ int vSpace = heightSize - getPaddingTop() - getPaddingBottom();
int hFreeSpace = hSpace - (mCountX * mCellWidth);
int vFreeSpace = vSpace - (mCountY * mCellHeight);
mWidthGap = Math.min(mMaxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
mHeightGap = Math.min(mMaxGap,numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
- mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap,
- mCountX);
+ mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap,
+ mHeightGap, mCountX, mCountY);
} else {
mWidthGap = mOriginalWidthGap;
mHeightGap = mOriginalHeightGap;
}
-
- // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY
- if (widthSpecMode == MeasureSpec.AT_MOST) {
- newWidth = getPaddingLeft() + getPaddingRight() + (mCountX * mCellWidth) +
- ((mCountX - 1) * mWidthGap);
- newHeight = getPaddingTop() + getPaddingBottom() + (mCountY * mCellHeight) +
- ((mCountY - 1) * mHeightGap);
- setMeasuredDimension(newWidth, newHeight);
- }
-
int count = getChildCount();
+ int maxWidth = 0;
+ int maxHeight = 0;
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth - getPaddingLeft() -
@@ -1041,8 +991,10 @@ public class CellLayout extends ViewGroup {
int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight - getPaddingTop() -
getPaddingBottom(), MeasureSpec.EXACTLY);
child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+ maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
+ maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
}
- setMeasuredDimension(newWidth, newHeight);
+ setMeasuredDimension(maxWidth, maxHeight);
}
@Override
@@ -1530,7 +1482,7 @@ public class CellLayout extends ViewGroup {
* matches exactly. Otherwise we find the best matching direction.
* @param occoupied The array which represents which cells in the CellLayout are occupied
* @param blockOccupied The array which represents which cells in the specified block (cellX,
- * cellY, spanX, spanY) are occupied. This is used when try to move a group of views.
+ * cellY, spanX, spanY) are occupied. This is used when try to move a group of views.
* @param result Array in which to place the result, or null (in which case a new array will
* be allocated)
* @return The X, Y cell of a vacant area that can contain this object,
@@ -2003,7 +1955,7 @@ public class CellLayout extends ViewGroup {
private boolean attemptPushInDirection(ArrayList<View> intersectingViews, Rect occupied,
int[] direction, View ignoreView, ItemConfiguration solution) {
if ((Math.abs(direction[0]) + Math.abs(direction[1])) > 1) {
- // If the direction vector has two non-zero components, we try pushing
+ // If the direction vector has two non-zero components, we try pushing
// separately in each of the components.
int temp = direction[1];
direction[1] = 0;
@@ -2044,7 +1996,7 @@ public class CellLayout extends ViewGroup {
direction[0] = temp;
direction[0] *= -1;
direction[1] *= -1;
-
+
} else {
// If the direction vector has a single non-zero component, we push first in the
// direction of the vector
@@ -2062,8 +2014,8 @@ public class CellLayout extends ViewGroup {
// Switch the direction back
direction[0] *= -1;
direction[1] *= -1;
-
- // If we have failed to find a push solution with the above, then we try
+
+ // If we have failed to find a push solution with the above, then we try
// to find a solution by pushing along the perpendicular axis.
// Swap the components
@@ -2125,7 +2077,7 @@ public class CellLayout extends ViewGroup {
}
}
- // First we try to find a solution which respects the push mechanic. That is,
+ // First we try to find a solution which respects the push mechanic. That is,
// we try to find a solution such that no displaced item travels through another item
// without also displacing that item.
if (attemptPushInDirection(mIntersectingViews, mOccupiedRect, direction, ignoreView,
@@ -3013,10 +2965,13 @@ public class CellLayout extends ViewGroup {
}
public static int[] rectToCell(Resources resources, int width, int height, int[] result) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
// Always assume we're working with the smallest span to make sure we
// reserve enough space in both orientations.
- int actualWidth = resources.getDimensionPixelSize(R.dimen.workspace_cell_width);
- int actualHeight = resources.getDimensionPixelSize(R.dimen.workspace_cell_height);
+ int actualWidth = grid.cellWidthPx;
+ int actualHeight = grid.cellHeightPx;
int smallerSize = Math.min(actualWidth, actualHeight);
// Always round up to next largest cell
diff --git a/src/com/android/launcher3/Cling.java b/src/com/android/launcher3/Cling.java
index 77c41b799..add6da51d 100644
--- a/src/com/android/launcher3/Cling.java
+++ b/src/com/android/launcher3/Cling.java
@@ -90,13 +90,15 @@ public class Cling extends FrameLayout {
mPositionData = positionData;
Resources r = getContext().getResources();
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
mPunchThroughGraphic = r.getDrawable(R.drawable.cling);
mPunchThroughGraphicCenterRadius =
r.getDimensionPixelSize(R.dimen.clingPunchThroughGraphicCenterRadius);
- mAppIconSize = r.getDimensionPixelSize(R.dimen.app_icon_size);
- mRevealRadius = r.getDimensionPixelSize(R.dimen.reveal_radius) * 1f;
- mButtonBarHeight = r.getDimensionPixelSize(R.dimen.button_bar_height);
+ mAppIconSize = grid.iconSizePx;
+ mRevealRadius = grid.iconSizePx * 1f;
+ mButtonBarHeight = grid.hotseatBarHeightPx;
mErasePaint = new Paint();
mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index 94316df9f..be0d47b68 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -28,11 +28,7 @@ import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
+import android.view.*;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.DecelerateInterpolator;
@@ -503,6 +499,7 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
} else if (child instanceof FolderIcon) {
// Account for holographic blur padding on the drag view
+ toY += Math.round(scale * (child.getPaddingTop() - dragView.getDragRegionTop()));
toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2;
toY -= (1 - scale) * dragView.getMeasuredHeight() / 2;
// Center in the x coordinate about the target's drawable
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
new file mode 100644
index 000000000..37cccfbd3
--- /dev/null
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.Paint.FontMetrics;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+
+class DeviceProfileQuery {
+ float widthDps;
+ float heightDps;
+ float value;
+ PointF dimens;
+
+ DeviceProfileQuery(float w, float h, float v) {
+ widthDps = w;
+ heightDps = h;
+ value = v;
+ dimens = new PointF(w, h);
+ }
+}
+
+class DeviceProfile {
+ String name;
+ float minWidthDps;
+ float minHeightDps;
+ float numRows;
+ float numColumns;
+ float iconSize;
+ float iconTextSize;
+ float numHotseatIcons;
+ float hotseatIconSize;
+
+ boolean isLandscape;
+ boolean isTablet;
+ boolean isLargeTablet;
+ boolean transposeLayoutWithOrientation;
+
+ int edgeMarginPx;
+
+ int widthPx;
+ int heightPx;
+ int iconSizePx;
+ int iconTextSizePx;
+ int cellWidthPx;
+ int cellHeightPx;
+ int folderBackgroundOffset;
+ int folderIconSizePx;
+ int folderCellWidthPx;
+ int folderCellHeightPx;
+ int hotseatCellWidthPx;
+ int hotseatCellHeightPx;
+ int hotseatIconSizePx;
+ int hotseatBarHeightPx;
+ int searchBarSpaceWidthPx;
+ int searchBarSpaceMaxWidthPx;
+ int searchBarSpaceHeightPx;
+ int searchBarHeightPx;
+ int pageIndicatorHeightPx;
+
+ DeviceProfile(String n, float w, float h, float r, float c,
+ float is, float its, float hs, float his) {
+ name = n;
+ minWidthDps = w;
+ minHeightDps = h;
+ numRows = r;
+ numColumns = c;
+ iconSize = is;
+ iconTextSize = its;
+ numHotseatIcons = hs;
+ hotseatIconSize = his;
+ }
+
+ DeviceProfile(ArrayList<DeviceProfile> profiles,
+ float minWidth, int minWidthPx,
+ float minHeight, int minHeightPx,
+ int wPx, int hPx,
+ Resources resources) {
+ DisplayMetrics dm = resources.getDisplayMetrics();
+ ArrayList<DeviceProfileQuery> points =
+ new ArrayList<DeviceProfileQuery>();
+ transposeLayoutWithOrientation =
+ resources.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
+ updateFromConfiguration(resources, wPx, hPx);
+ minWidthDps = minWidth;
+ minHeightDps = minHeight;
+
+ edgeMarginPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
+ pageIndicatorHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
+
+ // Interpolate the rows
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numRows));
+ }
+ numRows = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
+ // Interpolate the columns
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numColumns));
+ }
+ numColumns = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
+ // Interpolate the icon size
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconSize));
+ }
+ iconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
+ iconSizePx = (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ iconSize, dm));
+ // Interpolate the icon text size
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconTextSize));
+ }
+ iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points);
+ iconTextSizePx = (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
+ iconTextSize, dm));
+ // Interpolate the hotseat size
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numHotseatIcons));
+ }
+ numHotseatIcons = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
+ // Interpolate the hotseat icon size
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.hotseatIconSize));
+ }
+
+ // Hotseat
+ hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
+ hotseatIconSizePx = (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ hotseatIconSize, dm));
+ hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
+ hotseatCellWidthPx = iconSizePx;
+ hotseatCellHeightPx = iconSizePx;
+
+ // Search Bar
+ searchBarSpaceMaxWidthPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width);
+ searchBarHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
+ searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx);
+ searchBarSpaceHeightPx = searchBarHeightPx + 2 * edgeMarginPx;
+
+ // Calculate the actual text height
+ Paint textPaint = new Paint();
+ textPaint.setTextSize(iconTextSizePx);
+ FontMetrics fm = textPaint.getFontMetrics();
+ cellWidthPx = iconSizePx;
+ cellHeightPx = iconSizePx + (int) Math.ceil(fm.bottom - fm.top);
+
+ // Folder
+ folderCellWidthPx = cellWidthPx + 3 * edgeMarginPx;
+ folderCellHeightPx = cellHeightPx + edgeMarginPx;
+ folderBackgroundOffset = -edgeMarginPx;
+ folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset;
+ }
+
+ void updateFromConfiguration(Resources resources, int wPx, int hPx) {
+ isLandscape = (resources.getConfiguration().orientation ==
+ Configuration.ORIENTATION_LANDSCAPE);
+ isTablet = resources.getBoolean(R.bool.is_tablet);
+ isLargeTablet = resources.getBoolean(R.bool.is_large_tablet);
+ widthPx = wPx;
+ heightPx = hPx;
+ }
+
+ private float dist(PointF p0, PointF p1) {
+ return (float) Math.sqrt((p1.x - p0.x)*(p1.x-p0.x) +
+ (p1.y-p0.y)*(p1.y-p0.y));
+ }
+
+ private float weight(PointF a, PointF b,
+ float pow) {
+ float d = dist(a, b);
+ if (d == 0f) {
+ return Float.POSITIVE_INFINITY;
+ }
+ return (float) (1f / Math.pow(d, pow));
+ }
+
+ private float invDistWeightedInterpolate(float width, float height,
+ ArrayList<DeviceProfileQuery> points) {
+ float sum = 0;
+ float weights = 0;
+ float pow = 5;
+ float kNearestNeighbors = 3;
+ final PointF xy = new PointF(width, height);
+
+ ArrayList<DeviceProfileQuery> pointsByNearness = points;
+ Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() {
+ public int compare(DeviceProfileQuery a, DeviceProfileQuery b) {
+ return (int) (dist(xy, a.dimens) - dist(xy, b.dimens));
+ }
+ });
+
+ for (int i = 0; i < pointsByNearness.size(); ++i) {
+ DeviceProfileQuery p = pointsByNearness.get(i);
+ if (i < kNearestNeighbors) {
+ float w = weight(xy, p.dimens, pow);
+ if (w == Float.POSITIVE_INFINITY) {
+ return p.value;
+ }
+ weights += w;
+ }
+ }
+
+ for (int i = 0; i < pointsByNearness.size(); ++i) {
+ DeviceProfileQuery p = pointsByNearness.get(i);
+ if (i < kNearestNeighbors) {
+ float w = weight(xy, p.dimens, pow);
+ sum += w * p.value / weights;
+ }
+ }
+
+ return sum;
+ }
+
+ Rect getWorkspacePadding(int orientation) {
+ Rect padding = new Rect();
+ if (orientation == CellLayout.LANDSCAPE &&
+ transposeLayoutWithOrientation) {
+ // Pad the left and right of the workspace with search/hotseat bar sizes
+ padding.set(searchBarSpaceHeightPx, edgeMarginPx,
+ hotseatBarHeightPx, edgeMarginPx);
+ } else {
+ if (isTablet()) {
+ // Pad the left and right of the workspace to ensure consistent spacing
+ // between all icons
+ int width = (orientation == CellLayout.LANDSCAPE)
+ ? Math.max(widthPx, heightPx)
+ : Math.min(widthPx, heightPx);
+ // XXX: If the icon size changes across orientations, we will have to take
+ // that into account here too.
+ int gap = (int) ((width - 2 * edgeMarginPx -
+ (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
+ padding.set(edgeMarginPx + gap,
+ searchBarSpaceHeightPx,
+ edgeMarginPx + gap,
+ hotseatBarHeightPx + pageIndicatorHeightPx);
+ } else {
+ // Pad the top and bottom of the workspace with search/hotseat bar sizes
+ padding.set(edgeMarginPx,
+ searchBarSpaceHeightPx,
+ edgeMarginPx,
+ hotseatBarHeightPx + pageIndicatorHeightPx);
+ }
+ }
+ return padding;
+ }
+
+ int calculateCellWidth(int width, int countX) {
+ return width / countX;
+ }
+ int calculateCellHeight(int height, int countY) {
+ return height / countY;
+ }
+
+ boolean isTablet() {
+ return isTablet;
+ }
+
+ boolean isLargeTablet() {
+ return isLargeTablet;
+ }
+
+ public void layout(Launcher launcher) {
+ FrameLayout.LayoutParams lp;
+ Resources res = launcher.getResources();
+ boolean hasVerticalBarLayout = isLandscape &&
+ res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
+
+ // Layout the search bar space
+ View searchBarSpace = launcher.findViewById(R.id.qsb_bar);
+ lp = (FrameLayout.LayoutParams) searchBarSpace.getLayoutParams();
+ if (hasVerticalBarLayout) {
+ // Vertical search bar
+ lp.gravity = Gravity.TOP | Gravity.LEFT;
+ lp.width = searchBarSpaceHeightPx;
+ lp.height = LayoutParams.MATCH_PARENT;
+ searchBarSpace.setPadding(
+ 0, 2 * edgeMarginPx, 0,
+ 2 * edgeMarginPx);
+ } else {
+ // Horizontal search bar
+ lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+ lp.width = searchBarSpaceWidthPx;
+ lp.height = searchBarSpaceHeightPx;
+ searchBarSpace.setPadding(
+ 2 * edgeMarginPx,
+ 2 * edgeMarginPx,
+ 2 * edgeMarginPx, 0);
+ }
+ searchBarSpace.setLayoutParams(lp);
+
+ // Layout the search bar
+ View searchBar = searchBarSpace.findViewById(R.id.qsb_search_bar);
+ lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
+ lp.width = LayoutParams.MATCH_PARENT;
+ lp.height = LayoutParams.MATCH_PARENT;
+ searchBar.setLayoutParams(lp);
+
+ // Layout the voice proxy
+ View voiceButtonProxy = launcher.findViewById(R.id.voice_button_proxy);
+ if (voiceButtonProxy != null) {
+ if (hasVerticalBarLayout) {
+ // TODO: MOVE THIS INTO SEARCH BAR MEASURE
+ } else {
+ lp = (FrameLayout.LayoutParams) voiceButtonProxy.getLayoutParams();
+ lp.gravity = Gravity.TOP | Gravity.END;
+ lp.width = (widthPx - searchBarSpaceWidthPx) / 2 +
+ 2 * iconSizePx;
+ lp.height = searchBarSpaceHeightPx;
+ }
+ }
+
+ // Layout the workspace
+ View workspace = launcher.findViewById(R.id.workspace);
+ lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
+ lp.gravity = Gravity.CENTER;
+ Rect padding = getWorkspacePadding(isLandscape
+ ? CellLayout.LANDSCAPE
+ : CellLayout.PORTRAIT);
+ workspace.setPadding(padding.left, padding.top,
+ padding.right, padding.bottom);
+ workspace.setLayoutParams(lp);
+
+ // Layout the hotseat
+ View hotseat = launcher.findViewById(R.id.hotseat);
+ lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams();
+ if (hasVerticalBarLayout) {
+ // Vertical hotseat
+ lp.gravity = Gravity.RIGHT;
+ lp.width = hotseatBarHeightPx;
+ lp.height = LayoutParams.MATCH_PARENT;
+ hotseat.setPadding(0, 2 * edgeMarginPx,
+ 2 * edgeMarginPx, 2 * edgeMarginPx);
+ } else if (isTablet()) {
+ // Pad the hotseat with the grid gap calculated above
+ int gridGap = (int) ((widthPx - 2 * edgeMarginPx -
+ (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
+ int gridWidth = (int) ((numColumns * cellWidthPx) +
+ ((numColumns - 1) * gridGap));
+ int hotseatGap = (int) Math.max(0,
+ (gridWidth - (numHotseatIcons * hotseatCellWidthPx))
+ / (numHotseatIcons - 1));
+ lp.gravity = Gravity.BOTTOM;
+ lp.width = LayoutParams.MATCH_PARENT;
+ lp.height = hotseatBarHeightPx;
+ hotseat.setPadding(2 * edgeMarginPx + gridGap + hotseatGap, 0,
+ 2 * edgeMarginPx + gridGap + hotseatGap,
+ 2 * edgeMarginPx);
+ } else {
+ // For phones, layout the hotseat without any bottom margin
+ // to ensure that we have space for the folders
+ lp.gravity = Gravity.BOTTOM;
+ lp.width = LayoutParams.MATCH_PARENT;
+ lp.height = hotseatBarHeightPx;
+ hotseat.setPadding(2 * edgeMarginPx, 0,
+ 2 * edgeMarginPx, 0);
+ }
+ hotseat.setLayoutParams(lp);
+
+ // Layout the page indicators
+ View pageIndicator = launcher.findViewById(R.id.page_indicator);
+ if (pageIndicator != null) {
+ if (hasVerticalBarLayout) {
+ // Hide the page indicators when we have vertical search/hotseat
+ pageIndicator.setVisibility(View.GONE);
+ } else {
+ // Put the page indicators above the hotseat
+ lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams();
+ lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+ lp.width = LayoutParams.WRAP_CONTENT;
+ lp.height = pageIndicatorHeightPx;
+ lp.bottomMargin = hotseatBarHeightPx;
+ pageIndicator.setLayoutParams(lp);
+ }
+ }
+ }
+}
+
+public class DynamicGrid {
+ @SuppressWarnings("unused")
+ private static final String TAG = "DynamicGrid";
+
+ private DeviceProfile mProfile;
+ private float mMinWidth;
+ private float mMinHeight;
+
+ public static int dpiFromPx(int size, DisplayMetrics metrics){
+ float densityRatio = (float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
+ return (int) Math.round(size / densityRatio);
+ }
+
+ public DynamicGrid(Resources resources, int minWidthPx, int minHeightPx,
+ int widthPx, int heightPx) {
+ DisplayMetrics dm = resources.getDisplayMetrics();
+ ArrayList<DeviceProfile> deviceProfiles =
+ new ArrayList<DeviceProfile>();
+ // Our phone profiles include the bar sizes in each orientation
+ deviceProfiles.add(new DeviceProfile("Super Short Stubby",
+ 255, 300, 2, 3, 48, 12, 4, 48));
+ deviceProfiles.add(new DeviceProfile("Shorter Stubby",
+ 255, 400, 3, 3, 48, 12, 4, 48));
+ deviceProfiles.add(new DeviceProfile("Short Stubby",
+ 275, 420, 3, 4, 48, 12, 4, 48));
+ deviceProfiles.add(new DeviceProfile("Stubby",
+ 255, 450, 3, 4, 48, 12, 4, 48));
+ deviceProfiles.add(new DeviceProfile("Nexus S",
+ 296, 491.33f, 4, 4, 48, 12, 4, 48));
+ deviceProfiles.add(new DeviceProfile("Nexus 4",
+ 359, 518, 4, 4, 60, 12, 5, 56));
+ // The tablet profile is odd in that the landscape orientation
+ // also includes the nav bar on the side
+ deviceProfiles.add(new DeviceProfile("Nexus 7",
+ 575, 904, 6, 6, 72, 14.4f, 7, 60));
+ // Larger tablet profiles always have system bars on the top & bottom
+ deviceProfiles.add(new DeviceProfile("Nexus 10",
+ 727, 1207, 5, 8, 80, 14.4f, 9, 64));
+ /*
+ deviceProfiles.add(new DeviceProfile("Nexus 7",
+ 600, 960, 5, 5, 72, 14.4f, 5, 60));
+ deviceProfiles.add(new DeviceProfile("Nexus 10",
+ 800, 1280, 5, 5, 80, 14.4f, 6, 64));
+ */
+ deviceProfiles.add(new DeviceProfile("20-inch Tablet",
+ 1527, 2527, 7, 7, 100, 20, 7, 72));
+ mMinWidth = dpiFromPx(minWidthPx, dm);
+ mMinHeight = dpiFromPx(minHeightPx, dm);
+ mProfile = new DeviceProfile(deviceProfiles,
+ mMinWidth, minWidthPx,
+ mMinHeight, minHeightPx,
+ widthPx, heightPx,
+ resources);
+ }
+
+ DeviceProfile getDeviceProfile() {
+ return mProfile;
+ }
+
+ public String toString() {
+ return "-------- DYNAMIC GRID ------- \n" +
+ "Wd: " + mProfile.minWidthDps + ", Hd: " + mProfile.minHeightDps +
+ ", W: " + mProfile.widthPx + ", H: " + mProfile.heightPx +
+ " [r: " + mProfile.numRows + ", c: " + mProfile.numColumns +
+ ", is: " + mProfile.iconSizePx + ", its: " + mProfile.iconTextSize +
+ ", cw: " + mProfile.cellWidthPx + ", ch: " + mProfile.cellHeightPx +
+ ", hc: " + mProfile.numHotseatIcons + ", his: " + mProfile.hotseatIconSizePx + "]";
+ }
+}
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 3ff4fa323..f23e1bb39 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -138,39 +138,16 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
*/
public Folder(Context context, AttributeSet attrs) {
super(context, attrs);
+
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
setAlwaysDrawnWithCacheEnabled(false);
mInflater = LayoutInflater.from(context);
- mIconCache = (LauncherAppState.getInstance()).getIconCache();
+ mIconCache = app.getIconCache();
Resources res = getResources();
- mMaxCountX = mMaxVisibleX = res.getInteger(R.integer.folder_max_count_x);
- mMaxCountY = mMaxVisibleY = res.getInteger(R.integer.folder_max_count_y);
- mMaxNumItems = res.getInteger(R.integer.folder_max_num_items);
-
- if (mMaxCountY == -1) {
- // -2 indicates unlimited
- mMaxCountY = Integer.MAX_VALUE;
- mMaxVisibleX = LauncherModel.getCellCountX() + 1;
- }
- if (mMaxNumItems == -1) {
- // -2 indicates unlimited
- mMaxNumItems = Integer.MAX_VALUE;
- mMaxVisibleY = LauncherModel.getCellCountY() + 1;
- }
- if (mMaxCountX == 0) {
- mMaxCountX = mMaxVisibleX = LauncherModel.getCellCountX();
- mMaxVisibleX++;
- }
- if (mMaxCountY == 0) {
- mMaxCountY = mMaxVisibleY = LauncherModel.getCellCountY();
- mMaxVisibleY++;
- }
- if (mMaxNumItems == 0) {
- mMaxNumItems = mMaxCountX * mMaxCountY;
- if (mMaxNumItems < 0) {
- mMaxNumItems = Integer.MAX_VALUE;
- }
- }
+ mMaxCountX = mMaxVisibleX = mMaxVisibleY = (int) (grid.numColumns);
+ mMaxCountY = mMaxNumItems = Integer.MAX_VALUE;
mInputMethodManager = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -196,10 +173,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mScrollView = (ScrollView) findViewById(R.id.scroll_view);
mContent = (CellLayout) findViewById(R.id.folder_content);
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
// Beyond this height, the area scrolls
+ mContent.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
mContent.setGridSize(mMaxVisibleX, mMaxVisibleY);
mMaxContentAreaHeight = mContent.getDesiredHeight() - SCROLL_CUT_OFF_AMOUNT;
-
mContent.setGridSize(0, 0);
mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
mContent.setInvertIfRtl(true);
@@ -535,13 +515,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
oa.start();
}
- void notifyDataSetChanged() {
- // recreate all the children if the data set changes under us. We may want to do this more
- // intelligently (ie just removing the views that should no longer exist)
- mContent.removeAllViewsInLayout();
- bind(mInfo);
- }
-
public boolean acceptDrop(DragObject d) {
final ItemInfo item = (ItemInfo) d.dragInfo;
final int itemType = item.itemType;
@@ -764,6 +737,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
boolean beingCalledAfterUninstall = mDeferredAction != null;
boolean successfulDrop =
success && (!beingCalledAfterUninstall || mUninstallSuccessful);
+
if (successfulDrop) {
if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) {
replaceFolderWithFinalItem();
@@ -783,6 +757,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
completeDragExit();
}
}
+
mDeleteFolderOnDropCompleted = false;
mDragInProgress = false;
mItemAddedBackToSelfViaIcon = false;
@@ -981,7 +956,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-
int contentAreaHeight = mContent.getDesiredHeight();
if (contentAreaHeight >= mMaxContentAreaHeight) {
// Subtract a bit so the user can see that it's scrollable.
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index fa713a41a..fd8337021 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -132,10 +132,18 @@ public class FolderIcon extends LinearLayout implements FolderListener {
}
FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
-
+ icon.setClipToPadding(false);
icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_icon_name);
icon.mFolderName.setText(folderInfo.title);
icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background);
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ // Offset the preview background to center this view accordingly
+ LinearLayout.LayoutParams lp =
+ (LinearLayout.LayoutParams) icon.mPreviewBackground.getLayoutParams();
+ lp.topMargin = grid.folderBackgroundOffset;
+ lp.width = grid.folderIconSizePx;
+ lp.height = grid.folderIconSizePx;
icon.setTag(folderInfo);
icon.setOnClickListener(launcher);
@@ -187,7 +195,10 @@ public class FolderIcon extends LinearLayout implements FolderListener {
throw new RuntimeException("FolderRingAnimator loading drawables on non-UI thread "
+ Thread.currentThread());
}
- sPreviewSize = res.getDimensionPixelSize(R.dimen.folder_preview_size);
+
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ sPreviewSize = grid.folderIconSizePx;
sPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding);
sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo);
sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_holo);
@@ -392,7 +403,7 @@ public class FolderIcon extends LinearLayout implements FolderListener {
center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]);
to.offset(center[0] - animateView.getMeasuredWidth() / 2,
- center[1] - animateView.getMeasuredHeight() / 2);
+ center[1] - animateView.getMeasuredHeight() / 2);
float finalAlpha = index < NUM_ITEMS_IN_PREVIEW ? 0.5f : 0f;
@@ -430,10 +441,13 @@ public class FolderIcon extends LinearLayout implements FolderListener {
private void computePreviewDrawingParams(int drawableSize, int totalSize) {
if (mIntrinsicIconSize != drawableSize || mTotalWidth != totalSize) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
mIntrinsicIconSize = drawableSize;
mTotalWidth = totalSize;
- final int previewSize = FolderRingAnimator.sPreviewSize;
+ final int previewSize = mPreviewBackground.getLayoutParams().height;
final int previewPadding = FolderRingAnimator.sPreviewPadding;
mAvailableSpaceInPreview = (previewSize - 2 * previewPadding);
@@ -447,7 +461,7 @@ public class FolderIcon extends LinearLayout implements FolderListener {
mMaxPerspectiveShift = mBaselineIconSize * PERSPECTIVE_SHIFT_FACTOR;
mPreviewOffsetX = (mTotalWidth - mAvailableSpaceInPreview) / 2;
- mPreviewOffsetY = previewPadding;
+ mPreviewOffsetY = previewPadding + grid.folderBackgroundOffset;
}
}
@@ -494,7 +508,7 @@ public class FolderIcon extends LinearLayout implements FolderListener {
// We want to imagine our coordinates from the bottom left, growing up and to the
// right. This is natural for the x-axis, but for the y-axis, we have to invert things.
- float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection);
+ float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection) + getPaddingTop();
float transX = offset + scaleOffsetCorrection;
float totalScale = mBaselineIconScale * scale;
final int overlayAlpha = (int) (80 * (1 - r));
@@ -569,7 +583,7 @@ public class FolderIcon extends LinearLayout implements FolderListener {
final float scale0 = 1.0f;
final float transX0 = (mAvailableSpaceInPreview - d.getIntrinsicWidth()) / 2;
- final float transY0 = (mAvailableSpaceInPreview - d.getIntrinsicHeight()) / 2;
+ final float transY0 = (mAvailableSpaceInPreview - d.getIntrinsicHeight()) / 2 + getPaddingTop();
mAnimParams.drawable = d;
ValueAnimator va = LauncherAnimUtils.ofFloat(this, 0f, 1.0f);
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index f94ed7829..d28e96f2d 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -37,11 +37,8 @@ public class Hotseat extends FrameLayout {
@SuppressWarnings("unused")
private static final String TAG = "Hotseat";
- private Launcher mLauncher;
private CellLayout mContent;
- private int mCellCountX;
- private int mCellCountY;
private int mAllAppsButtonRank;
private boolean mTransposeLayoutWithOrientation;
@@ -61,9 +58,6 @@ public class Hotseat extends FrameLayout {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Hotseat, defStyle, 0);
Resources r = context.getResources();
- mCellCountX = a.getInt(R.styleable.Hotseat_cellCountX, -1);
- mCellCountY = a.getInt(R.styleable.Hotseat_cellCountY, -1);
- mAllAppsButtonRank = r.getInteger(R.integer.hotseat_all_apps_index);
mTransposeLayoutWithOrientation =
r.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
mIsLandscape = context.getResources().getConfiguration().orientation ==
@@ -71,7 +65,6 @@ public class Hotseat extends FrameLayout {
}
public void setup(Launcher launcher) {
- mLauncher = launcher;
setOnKeyListener(new HotseatIconKeyEventListener());
}
@@ -101,10 +94,16 @@ public class Hotseat extends FrameLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- if (mCellCountX < 0) mCellCountX = LauncherModel.getCellCountX();
- if (mCellCountY < 0) mCellCountY = LauncherModel.getCellCountY();
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
+ mAllAppsButtonRank = (int) (grid.numHotseatIcons / 2);
mContent = (CellLayout) findViewById(R.id.layout);
- mContent.setGridSize(mCellCountX, mCellCountY);
+ if (grid.isLandscape && !grid.isLargeTablet()) {
+ mContent.setGridSize(1, (int) grid.numHotseatIcons);
+ } else {
+ mContent.setGridSize((int) grid.numHotseatIcons, 1);
+ }
mContent.setIsHotseat(true);
resetLayout();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ab2bc67d6..c29e74f5e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -51,6 +51,7 @@ import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -199,7 +200,6 @@ public class Launcher extends Activity
private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED };
private State mState = State.WORKSPACE;
private AnimatorSet mStateAnimation;
- private AnimatorSet mDividerAnimator;
static final int APPWIDGET_HOST_ID = 1024;
private static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
@@ -221,7 +221,6 @@ public class Launcher extends Activity
private LayoutInflater mInflater;
private Workspace mWorkspace;
- private View mQsbDivider;
private View mLauncherView;
private DragLayer mDragLayer;
private DragController mDragController;
@@ -372,9 +371,23 @@ public class Launcher extends Activity
super.onCreate(savedInstanceState);
- // the LauncherApplication should call this, but in case of Instrumentation it might not be present yet
LauncherAppState.setApplicationContext(getApplicationContext());
LauncherAppState app = LauncherAppState.getInstance();
+
+ // Determine the dynamic grid properties
+ Point smallestSize = new Point();
+ Point largestSize = new Point();
+ Point realSize = new Point();
+ Display display = getWindowManager().getDefaultDisplay();
+ display.getCurrentSizeRange(smallestSize, largestSize);
+ display.getRealSize(realSize);
+ // Lazy-initialize the dynamic grid
+ DeviceProfile grid = app.initDynamicGrid(this,
+ Math.min(smallestSize.x, smallestSize.y),
+ Math.min(largestSize.x, largestSize.y),
+ realSize.x, realSize.y);
+
+ // the LauncherApplication should call this, but in case of Instrumentation it might not be present yet
mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
Context.MODE_PRIVATE);
mModel = app.setLauncher(this);
@@ -400,6 +413,7 @@ public class Launcher extends Activity
checkForLocaleChange();
setContentView(R.layout.launcher);
+ grid.layout(this);
setupViews();
showFirstRunWorkspaceCling();
@@ -1061,7 +1075,6 @@ public class Launcher extends Activity
mLauncherView = findViewById(R.id.launcher);
mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
- mQsbDivider = findViewById(R.id.qsb_divider);
mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
mWorkspaceBackgroundDrawable = getResources().getDrawable(R.drawable.workspace_bg);
@@ -2014,6 +2027,9 @@ public class Launcher extends Activity
FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo, mIconCache);
mWorkspace.addInScreen(newFolder, container, screenId, cellX, cellY, 1, 1,
isWorkspaceLocked());
+ // Force measure the new folder icon
+ CellLayout parent = mWorkspace.getParentCellLayoutForView(newFolder);
+ parent.getShortcutsAndWidgets().measureChild(newFolder);
return newFolder;
}
@@ -2784,11 +2800,6 @@ public class Launcher extends Activity
dispatchOnLauncherTransitionEnd(fromView, animated, false);
dispatchOnLauncherTransitionEnd(toView, animated, false);
- if (mWorkspace != null
- && !springLoaded
- && !LauncherAppState.getInstance().isScreenLarge()) {
- hideDockDivider();
- }
if (!animationCancelled) {
updateWallpaperVisibility(false);
}
@@ -2855,8 +2866,6 @@ public class Launcher extends Activity
toView.bringToFront();
if (!springLoaded && !LauncherAppState.getInstance().isScreenLarge()) {
- hideDockDivider();
-
// Hide the search bar
if (mSearchDropTargetBar != null) {
mSearchDropTargetBar.hideSearchBar(false);
@@ -3008,9 +3017,6 @@ public class Launcher extends Activity
mSearchDropTargetBar.showSearchBar(wasInSpringLoadedMode);
}
- // We only need to animate in the dock divider if we're going from spring loaded mode
- showDockDivider(animated && wasInSpringLoadedMode);
-
// Set focus to the AppsCustomize button
if (mAllAppsButton != null) {
mAllAppsButton.requestFocus();
@@ -3056,7 +3062,6 @@ public class Launcher extends Activity
void enterSpringLoadedDragMode() {
if (isAllAppsVisible()) {
hideAppsCustomizeHelper(State.APPS_CUSTOMIZE_SPRING_LOADED, true, true, null);
- hideDockDivider();
mState = State.APPS_CUSTOMIZE_SPRING_LOADED;
}
}
@@ -3093,33 +3098,6 @@ public class Launcher extends Activity
// Otherwise, we are not in spring loaded mode, so don't do anything.
}
- void hideDockDivider() {
- if (mQsbDivider != null) {
- mQsbDivider.setVisibility(View.INVISIBLE);
- }
- }
-
- void showDockDivider(boolean animated) {
- if (mQsbDivider != null) {
- mQsbDivider.setVisibility(View.VISIBLE);
- if (mDividerAnimator != null) {
- mDividerAnimator.cancel();
- mQsbDivider.setAlpha(1f);
- mDividerAnimator = null;
- }
- if (animated) {
- mDividerAnimator = LauncherAnimUtils.createAnimatorSet();
- mDividerAnimator.playTogether(LauncherAnimUtils.ofFloat(mQsbDivider, "alpha", 1f));
- int duration = 0;
- if (mSearchDropTargetBar != null) {
- duration = mSearchDropTargetBar.getTransitionInDuration();
- }
- mDividerAnimator.setDuration(duration);
- mDividerAnimator.start();
- }
- }
- }
-
void lockAllApps() {
// TODO
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 03d2d3395..0c577e548 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -21,11 +21,14 @@ import android.content.*;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.os.Handler;
+import android.provider.Settings;
import android.util.Log;
+import android.view.Display;
import java.lang.ref.WeakReference;
public class LauncherAppState {
+ private static final String TAG = "LauncherAppState";
private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
private LauncherModel mModel;
@@ -41,6 +44,8 @@ public class LauncherAppState {
private static Object mLock = new Object();
private static LauncherAppState INSTANCE;
+ private DynamicGrid mDynamicGrid;
+
public static LauncherAppState getInstance() {
if (INSTANCE == null) {
INSTANCE = new LauncherAppState();
@@ -71,7 +76,7 @@ public class LauncherAppState {
}
// set sIsScreenXLarge and mScreenDensity *before* creating icon cache
- mIsScreenLarge = sContext.getResources().getBoolean(R.bool.is_large_screen);
+ mIsScreenLarge = sContext.getResources().getBoolean(R.bool.is_large_tablet);
mScreenDensity = sContext.getResources().getDisplayMetrics().density;
mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
@@ -158,6 +163,27 @@ public class LauncherAppState {
return SHARED_PREFERENCES_KEY;
}
+ DeviceProfile initDynamicGrid(Context context, int minWidth, int minHeight, int width, int height) {
+ boolean created = false;
+ if (mDynamicGrid == null) {
+ mDynamicGrid = new DynamicGrid(context.getResources(),
+ minWidth, minHeight, width, height);
+ created = true;
+ }
+
+ DeviceProfile grid = mDynamicGrid.getDeviceProfile();
+ if (created) {
+ LauncherModel.updateWorkspaceLayoutCells((int) grid.numColumns, (int) grid.numRows);
+ }
+ // Update the icon size
+ Utilities.setIconSize(grid.iconSizePx);
+ grid.updateFromConfiguration(context.getResources(), width, height);
+ return grid;
+ }
+ DynamicGrid getDynamicGrid() {
+ return mDynamicGrid;
+ }
+
public boolean isScreenLarge() {
return mIsScreenLarge;
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index faec8b6c1..90587f9c5 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -18,6 +18,7 @@ package com.android.launcher3;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
+import android.graphics.Canvas;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 2ac9b1b6c..cd37a167c 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1556,6 +1556,11 @@ public class LauncherModel extends BroadcastReceiver {
}
}
+ private boolean checkItemDimensions(ItemInfo info) {
+ return (info.cellX + info.spanX) > mCellCountX ||
+ (info.cellY + info.spanY) > mCellCountY;
+ }
+
// check & update map of what's occupied; used to discard overlapping/invalid items
private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item) {
long containerIndex = item.screenId;
@@ -1743,6 +1748,16 @@ public class LauncherModel extends BroadcastReceiver {
info.screenId = c.getInt(screenIndex);
info.cellX = c.getInt(cellXIndex);
info.cellY = c.getInt(cellYIndex);
+ info.spanX = 1;
+ info.spanY = 1;
+ // Skip loading items that are out of bounds
+ if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ if (checkItemDimensions(info)) {
+ Log.d(TAG, "Skipped loading out of bounds shortcut: "
+ + info.intent);
+ continue;
+ }
+ }
// check & update map of what's occupied
if (!checkItemPlacement(occupied, info)) {
break;
@@ -1781,11 +1796,22 @@ public class LauncherModel extends BroadcastReceiver {
folderInfo.screenId = c.getInt(screenIndex);
folderInfo.cellX = c.getInt(cellXIndex);
folderInfo.cellY = c.getInt(cellYIndex);
-
+ folderInfo.spanX = 1;
+ folderInfo.spanY = 1;
+
+ // Skip loading items that are out of bounds
+ if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ int iconSpan = 1;
+ if (checkItemDimensions(folderInfo)) {
+ Log.d(TAG, "Skipped loading out of bounds folder");
+ continue;
+ }
+ }
// check & update map of what's occupied
if (!checkItemPlacement(occupied, folderInfo)) {
break;
}
+
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
@@ -1834,6 +1860,13 @@ public class LauncherModel extends BroadcastReceiver {
}
appWidgetInfo.container = c.getInt(containerIndex);
+ // Skip loading items that are out of bounds
+ if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ if (checkItemDimensions(appWidgetInfo)) {
+ Log.d(TAG, "Skipped loading out of bounds app widget");
+ continue;
+ }
+ }
// check & update map of what's occupied
if (!checkItemPlacement(occupied, appWidgetInfo)) {
break;
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 7d090e1fd..5e8a619cf 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -963,8 +963,6 @@ public class LauncherProvider extends ContentProvider {
ContentValues values = new ContentValues();
PackageManager packageManager = mContext.getPackageManager();
- int allAppsButtonRank =
- mContext.getResources().getInteger(R.integer.hotseat_all_apps_index);
int i = 0;
try {
XmlResourceParser parser = mContext.getResources().getXml(workspaceResourceId);
@@ -995,14 +993,6 @@ public class LauncherProvider extends ContentProvider {
String x = a.getString(R.styleable.Favorite_x);
String y = a.getString(R.styleable.Favorite_y);
- // If we are adding to the hotseat, the screen is used as the position in the
- // hotseat. This screen can't be at position 0 because AllApps is in the
- // zeroth position.
- if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
- && Integer.valueOf(screen) == allAppsButtonRank) {
- throw new RuntimeException("Invalid screen position for hotseat item");
- }
-
values.clear();
values.put(LauncherSettings.Favorites.CONTAINER, container);
values.put(LauncherSettings.Favorites.SCREEN, screen);
diff --git a/src/com/android/launcher3/PagedViewCellLayout.java b/src/com/android/launcher3/PagedViewCellLayout.java
index 9aa246793..38fd1ed00 100644
--- a/src/com/android/launcher3/PagedViewCellLayout.java
+++ b/src/com/android/launcher3/PagedViewCellLayout.java
@@ -59,11 +59,11 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
setAlwaysDrawnWithCacheEnabled(false);
// setup default cell parameters
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
Resources resources = context.getResources();
- mOriginalCellWidth = mCellWidth =
- resources.getDimensionPixelSize(R.dimen.apps_customize_cell_width);
- mOriginalCellHeight = mCellHeight =
- resources.getDimensionPixelSize(R.dimen.apps_customize_cell_height);
+ mOriginalCellWidth = mCellWidth = grid.cellWidthPx;
+ mOriginalCellHeight = mCellHeight = grid.cellHeightPx;
mCellCountX = LauncherModel.getCellCountX();
mCellCountY = LauncherModel.getCellCountY();
mOriginalWidthGap = mOriginalHeightGap = mWidthGap = mHeightGap = -1;
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
index 32d094b05..8f1b5d2d2 100644
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ b/src/com/android/launcher3/SearchDropTargetBar.java
@@ -99,7 +99,6 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
mDropTargetBar = findViewById(R.id.drag_target_bar);
mInfoDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.info_target_text);
mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target_text);
- mBarHeight = getResources().getDimensionPixelSize(R.dimen.qsb_bar_height);
mInfoDropTarget.setSearchDropTargetBar(this);
mDeleteDropTarget.setSearchDropTargetBar(this);
@@ -109,6 +108,9 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
// Create the various fade animations
if (mEnableDropDownDropTargets) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ mBarHeight = grid.searchBarSpaceHeightPx;
mDropTargetBar.setTranslationY(-mBarHeight);
mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "translationY",
-mBarHeight, 0f);
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index 64a87ef07..6c3360126 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -33,6 +33,8 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
private final WallpaperManager mWallpaperManager;
+ private boolean mIsHotseatLayout;
+
private int mCellWidth;
private int mCellHeight;
@@ -40,6 +42,7 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
private int mHeightGap;
private int mCountX;
+ private int mCountY;
private boolean mInvertIfRtl = false;
@@ -49,12 +52,13 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
}
public void setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap,
- int countX) {
+ int countX, int countY) {
mCellWidth = cellWidth;
mCellHeight = cellHeight;
mWidthGap = widthGap;
mHeightGap = heightGap;
mCountX = countX;
+ mCountY = countY;
}
public View getChildAt(int x, int y) {
@@ -113,13 +117,28 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
mInvertIfRtl = invert;
}
+ public void setIsHotseat(boolean isHotseat) {
+ mIsHotseatLayout = isHotseat;
+ }
+
public void measureChild(View child) {
+ final LauncherAppState app = LauncherAppState.getInstance();
+ final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
final int cellWidth = mCellWidth;
final int cellHeight = mCellHeight;
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
if (!lp.isFullscreen) {
lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap, invertLayoutHorizontally(),
mCountX);
+
+ if (child instanceof LauncherAppWidgetHostView) {
+ // Widgets have their own padding, so skip
+ } else {
+ // Otherwise, center the icon
+ int cHeight = mIsHotseatLayout ? grid.hotseatCellHeightPx : Math.min(getMeasuredHeight(), grid.cellHeightPx);
+ int cellPaddingY = (int) Math.max(0, ((lp.height - cHeight) / 2f));
+ child.setPadding(0, cellPaddingY, 0, 0);
+ }
} else {
lp.x = 0;
lp.y = 0;
@@ -142,12 +161,14 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
-
int childLeft = lp.x;
int childTop = lp.y;
child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height);
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index cc22bb5db..0529cfb74 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -120,19 +120,12 @@ final class Utilities {
int sourceWidth = icon.getIntrinsicWidth();
int sourceHeight = icon.getIntrinsicHeight();
if (sourceWidth > 0 && sourceHeight > 0) {
- // There are intrinsic sizes.
- if (width < sourceWidth || height < sourceHeight) {
- // It's too big, scale it down.
- final float ratio = (float) sourceWidth / sourceHeight;
- if (sourceWidth > sourceHeight) {
- height = (int) (width / ratio);
- } else if (sourceHeight > sourceWidth) {
- width = (int) (height * ratio);
- }
- } else if (sourceWidth < width && sourceHeight < height) {
- // Don't scale up the icon
- width = sourceWidth;
- height = sourceHeight;
+ // Scale the icon proportionally to the icon dimensions
+ final float ratio = (float) sourceWidth / sourceHeight;
+ if (sourceWidth > sourceHeight) {
+ height = (int) (width / ratio);
+ } else if (sourceHeight > sourceWidth) {
+ width = (int) (height * ratio);
}
}
@@ -169,34 +162,8 @@ final class Utilities {
}
}
- static void drawSelectedAllAppsBitmap(Canvas dest, int destWidth, int destHeight,
- boolean pressed, Bitmap src) {
- synchronized (sCanvas) { // we share the statics :-(
- if (sIconWidth == -1) {
- // We can't have gotten to here without src being initialized, which
- // comes from this file already. So just assert.
- //initStatics(context);
- throw new RuntimeException("Assertion failed: Utilities not initialized");
- }
-
- dest.drawColor(0, PorterDuff.Mode.CLEAR);
-
- int[] xy = new int[2];
- Bitmap mask = src.extractAlpha(sBlurPaint, xy);
-
- float px = (destWidth - src.getWidth()) / 2;
- float py = (destHeight - src.getHeight()) / 2;
- dest.drawBitmap(mask, px + xy[0], py + xy[1],
- pressed ? sGlowColorPressedPaint : sGlowColorFocusedPaint);
-
- mask.recycle();
- }
- }
-
/**
* Returns a Bitmap representing the thumbnail of the specified Bitmap.
- * The size of the thumbnail is defined by the dimension
- * android.R.dimen.launcher_application_icon_size.
*
* @param bitmap The bitmap to get a thumbnail of.
* @param context The application's context.
@@ -219,24 +186,6 @@ final class Utilities {
}
}
- static Bitmap drawDisabledBitmap(Bitmap bitmap, Context context) {
- synchronized (sCanvas) { // we share the statics :-(
- if (sIconWidth == -1) {
- initStatics(context);
- }
- final Bitmap disabled = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
- Bitmap.Config.ARGB_8888);
- final Canvas canvas = sCanvas;
- canvas.setBitmap(disabled);
-
- canvas.drawBitmap(bitmap, 0.0f, 0.0f, sDisabledPaint);
-
- canvas.setBitmap(null);
-
- return disabled;
- }
- }
-
/**
* Given a coordinate relative to the descendant, find the coordinate in a parent view's
* coordinates.
@@ -345,26 +294,8 @@ final class Utilities {
sDisabledPaint.setAlpha(0x88);
}
- /** Only works for positive numbers. */
- static int roundToPow2(int n) {
- int orig = n;
- n >>= 1;
- int mask = 0x8000000;
- while (mask != 0 && (n & mask) == 0) {
- mask >>= 1;
- }
- while (mask != 0) {
- n |= mask;
- mask >>= 1;
- }
- n += 1;
- if (n != orig) {
- n <<= 1;
- }
- return n;
- }
-
- static int generateRandomId() {
- return new Random(System.currentTimeMillis()).nextInt(1 << 24);
+ public static void setIconSize(int widthPx) {
+ sIconWidth = sIconHeight = widthPx;
+ sIconTextureWidth = sIconTextureHeight = widthPx;
}
}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index e96981a30..11c12f875 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -138,10 +138,12 @@ public class WidgetPreviewLoader {
}
public WidgetPreviewLoader(Launcher launcher) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
mContext = mLauncher = launcher;
mPackageManager = mContext.getPackageManager();
- mAppIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
- LauncherAppState app = LauncherAppState.getInstance();
+ mAppIconSize = grid.iconSizePx;
mIconCache = app.getIconCache();
mDb = app.getWidgetPreviewCacheDb();
mLoadedPreviews = new HashMap<String, WeakReference<Bitmap>>();
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 44eeae41e..77f726a44 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -164,9 +164,6 @@ public class Workspace extends SmoothPagedView
private float mSpringLoadedShrinkFactor;
private float mOverviewModeShrinkFactor;
- private static final int DEFAULT_CELL_COUNT_X = 4;
- private static final int DEFAULT_CELL_COUNT_Y = 4;
-
// State variable that indicates whether the pages are small (ie when you're
// in all apps or customize mode)
@@ -188,7 +185,6 @@ public class Workspace extends SmoothPagedView
private final Rect mTempRect = new Rect();
private final int[] mTempXY = new int[2];
private int[] mTempVisiblePagesRange = new int[2];
- private float mOverscrollFade = 0;
private boolean mOverscrollTransformsSet;
public static final int DRAG_BITMAP_PADDING = 2;
private boolean mWorkspaceFadeInAdjacentScreens;
@@ -301,52 +297,17 @@ public class Workspace extends SmoothPagedView
mFadeInAdjacentScreens = false;
mWallpaperManager = WallpaperManager.getInstance(context);
- int cellCountX = DEFAULT_CELL_COUNT_X;
- int cellCountY = DEFAULT_CELL_COUNT_Y;
-
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Workspace, defStyle, 0);
-
- if (LauncherAppState.getInstance().isScreenLarge()) {
- // Determine number of rows/columns dynamically
- // TODO: This code currently fails on tablets with an aspect ratio < 1.3.
- // Around that ratio we should make cells the same size in portrait and
- // landscape
- TypedArray actionBarSizeTypedArray =
- context.obtainStyledAttributes(new int[] { android.R.attr.actionBarSize });
- final float actionBarHeight = actionBarSizeTypedArray.getDimension(0, 0f);
-
- Point minDims = new Point();
- Point maxDims = new Point();
- mLauncher.getWindowManager().getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
-
- cellCountX = 1;
- while (CellLayout.widthInPortrait(res, cellCountX + 1) <= minDims.x) {
- cellCountX++;
- }
-
- cellCountY = 1;
- while (actionBarHeight + CellLayout.heightInLandscape(res, cellCountY + 1)
- <= minDims.y) {
- cellCountY++;
- }
- }
-
mSpringLoadedShrinkFactor =
res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
mOverviewModeShrinkFactor =
res.getInteger(R.integer.config_workspaceOverviewShrinkPercentage) / 100.0f;
mCameraDistance = res.getInteger(R.integer.config_cameraDistance);
-
- // if the value is manually specified, use that instead
- cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);
- cellCountY = a.getInt(R.styleable.Workspace_cellCountY, cellCountY);
mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
a.recycle();
setOnHierarchyChangeListener(this);
-
- LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
setHapticFeedbackEnabled(false);
initWorkspace();
@@ -417,6 +378,7 @@ public class Workspace extends SmoothPagedView
mCurrentPage = mDefaultPage;
Launcher.setScreen(mCurrentPage);
LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
mIconCache = app.getIconCache();
setWillNotDraw(false);
setClipChildren(false);
@@ -438,7 +400,7 @@ public class Workspace extends SmoothPagedView
mWallpaperTravelWidth = (int) (mDisplaySize.x *
wallpaperTravelToScreenWidthRatio(mDisplaySize.x, mDisplaySize.y));
- mMaxDistanceForFolderCreation = (0.55f * res.getDimensionPixelSize(R.dimen.app_icon_size));
+ mMaxDistanceForFolderCreation = (0.55f * grid.iconSizePx);
mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
}
@@ -615,7 +577,10 @@ public class Workspace extends SmoothPagedView
}
public long getScreenIdForPageIndex(int index) {
- return mScreenOrder.get(index);
+ if (0 <= index && index < mScreenOrder.size()) {
+ return mScreenOrder.get(index);
+ }
+ return -1;
}
ArrayList<Long> getScreenOrder() {
@@ -1401,7 +1366,6 @@ public class Workspace extends SmoothPagedView
cl.setOverScrollAmount(Math.abs(scrollProgress), isLeftPage);
float rotation = -WORKSPACE_OVERSCROLL_ROTATION * scrollProgress;
cl.setRotationY(rotation);
- setFadeForOverScroll(Math.abs(scrollProgress));
if (!mOverscrollTransformsSet) {
mOverscrollTransformsSet = true;
cl.setCameraDistance(mDensity * mCameraDistance);
@@ -1410,9 +1374,6 @@ public class Workspace extends SmoothPagedView
cl.setOverscrollTransformsDirty(true);
}
} else {
- if (mOverscrollFade != 0) {
- setFadeForOverScroll(0);
- }
if (mOverscrollTransformsSet) {
mOverscrollTransformsSet = false;
((CellLayout) getChildAt(0)).resetOverscrollTransforms();
@@ -2165,11 +2126,12 @@ public class Workspace extends SmoothPagedView
Math.round(mTempXY[1] - (bmpHeight - scale * bmpHeight) / 2
- DRAG_BITMAP_PADDING / 2);
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
Point dragVisualizeOffset = null;
Rect dragRect = null;
if (child instanceof BubbleTextView || child instanceof PagedViewIcon) {
- int iconSize = r.getDimensionPixelSize(R.dimen.app_icon_size);
- int iconPaddingTop = r.getDimensionPixelSize(R.dimen.app_icon_padding_top);
+ int iconSize = grid.iconSizePx;
int top = child.getPaddingTop();
int left = (bmpWidth - iconSize) / 2;
int right = left + iconSize;
@@ -2177,12 +2139,11 @@ public class Workspace extends SmoothPagedView
dragLayerY += top;
// Note: The drag region is used to calculate drag layer offsets, but the
// dragVisualizeOffset in addition to the dragRect (the size) to position the outline.
- dragVisualizeOffset = new Point(-DRAG_BITMAP_PADDING / 2,
- iconPaddingTop - DRAG_BITMAP_PADDING / 2);
+ dragVisualizeOffset = new Point(-DRAG_BITMAP_PADDING / 2, DRAG_BITMAP_PADDING / 2);
dragRect = new Rect(left, top, right, bottom);
} else if (child instanceof FolderIcon) {
- int previewSize = r.getDimensionPixelSize(R.dimen.folder_preview_size);
- dragRect = new Rect(0, 0, child.getWidth(), previewSize);
+ int previewSize = grid.folderIconSizePx;
+ dragRect = new Rect(0, child.getPaddingTop(), child.getWidth(), previewSize);
}
// Clear the pressed state if necessary
@@ -2665,6 +2626,9 @@ public class Workspace extends SmoothPagedView
}
static Rect getCellLayoutMetrics(Launcher launcher, int orientation) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
Resources res = launcher.getResources();
Display display = launcher.getWindowManager().getDefaultDisplay();
Point smallestSize = new Point();
@@ -2672,12 +2636,9 @@ public class Workspace extends SmoothPagedView
display.getCurrentSizeRange(smallestSize, largestSize);
if (orientation == CellLayout.LANDSCAPE) {
if (mLandscapeCellLayoutMetrics == null) {
- int paddingLeft = res.getDimensionPixelSize(R.dimen.workspace_left_padding_land);
- int paddingRight = res.getDimensionPixelSize(R.dimen.workspace_right_padding_land);
- int paddingTop = res.getDimensionPixelSize(R.dimen.workspace_top_padding_land);
- int paddingBottom = res.getDimensionPixelSize(R.dimen.workspace_bottom_padding_land);
- int width = largestSize.x - paddingLeft - paddingRight;
- int height = smallestSize.y - paddingTop - paddingBottom;
+ Rect padding = grid.getWorkspacePadding(CellLayout.LANDSCAPE);
+ int width = largestSize.x - padding.left - padding.right;
+ int height = smallestSize.y - padding.top - padding.bottom;
mLandscapeCellLayoutMetrics = new Rect();
CellLayout.getMetrics(mLandscapeCellLayoutMetrics, res,
width, height, LauncherModel.getCellCountX(), LauncherModel.getCellCountY(),
@@ -2686,12 +2647,9 @@ public class Workspace extends SmoothPagedView
return mLandscapeCellLayoutMetrics;
} else if (orientation == CellLayout.PORTRAIT) {
if (mPortraitCellLayoutMetrics == null) {
- int paddingLeft = res.getDimensionPixelSize(R.dimen.workspace_left_padding_land);
- int paddingRight = res.getDimensionPixelSize(R.dimen.workspace_right_padding_land);
- int paddingTop = res.getDimensionPixelSize(R.dimen.workspace_top_padding_land);
- int paddingBottom = res.getDimensionPixelSize(R.dimen.workspace_bottom_padding_land);
- int width = smallestSize.x - paddingLeft - paddingRight;
- int height = largestSize.y - paddingTop - paddingBottom;
+ Rect padding = grid.getWorkspacePadding(CellLayout.PORTRAIT);
+ int width = smallestSize.x - padding.left - padding.right;
+ int height = largestSize.y - padding.top - padding.bottom;
mPortraitCellLayoutMetrics = new Rect();
CellLayout.getMetrics(mPortraitCellLayoutMetrics, res,
width, height, LauncherModel.getCellCountX(), LauncherModel.getCellCountY(),
@@ -4129,7 +4087,7 @@ public class Workspace extends SmoothPagedView
@Override
protected int getPageIndicatorMarker(int pageIndex) {
if (getScreenIdForPageIndex(pageIndex) == CUSTOM_CONTENT_SCREEN_ID) {
- return R.layout.now_page_indicator_marker;
+ return R.layout.custom_content_page_indicator_marker;
}
return super.getPageIndicatorMarker(pageIndex);
}
@@ -4151,13 +4109,4 @@ public class Workspace extends SmoothPagedView
public void getLocationInDragLayer(int[] loc) {
mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
}
-
- void setFadeForOverScroll(float fade) {
- mOverscrollFade = fade;
- float reducedFade = 0.5f + 0.5f * (1 - fade);
- final ViewGroup parent = (ViewGroup) getParent();
- final ImageView qsbDivider = (ImageView) (parent.findViewById(R.id.qsb_divider));
-
- if (qsbDivider != null) qsbDivider.setAlpha(reducedFade);
- }
}