Merge branch 'master' into honeycomb-release
diff --git a/res/anim/paged_view_click_feedback.xml b/res/anim/paged_view_click_feedback.xml
index 786d974..d1e6e23 100644
--- a/res/anim/paged_view_click_feedback.xml
+++ b/res/anim/paged_view_click_feedback.xml
@@ -16,8 +16,8 @@
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
- android:toAlpha="0.65"
- android:duration="100"
+ android:toAlpha="0.5"
+ android:duration="75"
android:fillAfter="true"
android:repeatCount="1"
android:repeatMode="reverse" />
diff --git a/res/values-xlarge/config.xml b/res/values-xlarge/config.xml
index 6a56679..a54528e 100644
--- a/res/values-xlarge/config.xml
+++ b/res/values-xlarge/config.xml
@@ -5,6 +5,10 @@
<!-- NB: This should be less than the workspaceShrinkTime as they happen together. -->
<integer name="config_allAppsZoomInTime">350</integer>
+ <!-- Duration in milliseconds of the transition between tabs in the all apps/customize
+ tray -->
+ <integer name="config_tabTransitionTime">100</integer>
+
<!-- Duration in milliseconds of the all apps zoom-out animation -->
<!-- NB: This should be less than the workspaceUnshrinkTime as they happen together. -->
<integer name="config_allAppsZoomOutTime">350</integer>
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java
index e0ff1a8..a6e21b9 100644
--- a/src/com/android/launcher2/AllAppsTabbed.java
+++ b/src/com/android/launcher2/AllAppsTabbed.java
@@ -76,7 +76,8 @@
setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
// animate the changing of the tab content by fading pages in and out
- final int duration = 150;
+ final Resources res = getResources();
+ final int duration = res.getInteger(R.integer.config_tabTransitionTime);
final float alpha = mAllApps.getAlpha();
ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mAllApps, "alpha", alpha, 0.0f).
setDuration(duration);
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 11c0c18..e340101 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -839,6 +839,10 @@
mBackgroundAlphaMultiplier = multiplier;
}
+ public float getBackgroundAlphaMultiplier() {
+ return mBackgroundAlphaMultiplier;
+ }
+
public void setBackgroundAlpha(float alpha) {
mBackgroundAlpha = alpha;
invalidate();
@@ -1034,15 +1038,15 @@
final int countY = mCountY;
final boolean[][] occupied = mOccupied;
- for (int x = 0; x < countX - (spanX - 1); x++) {
+ for (int y = 0; y < countY - (spanY - 1); y++) {
inner:
- for (int y = 0; y < countY - (spanY - 1); y++) {
+ for (int x = 0; x < countX - (spanX - 1); x++) {
for (int i = 0; i < spanX; i++) {
for (int j = 0; j < spanY; j++) {
if (occupied[x + i][y + j]) {
- // small optimization: we can skip to below the row we just found
+ // small optimization: we can skip to after the column we just found
// an occupied cell
- y += j;
+ x += i;
continue inner;
}
}
@@ -1150,15 +1154,15 @@
endY = Math.min(endY, intersectY + (spanY - 1) + (spanY == 1 ? 1 : 0));
}
- for (int x = startX; x < endX; x++) {
+ for (int y = startY; y < endY && !foundCell; y++) {
inner:
- for (int y = startY; y < endY; y++) {
+ for (int x = startX; x < endX; x++) {
for (int i = 0; i < spanX; i++) {
for (int j = 0; j < spanY; j++) {
if (mOccupied[x + i][y + j]) {
- // small optimization: we can skip to below the row we just found
+ // small optimization: we can skip to after the column we just found
// an occupied cell
- y += j;
+ x += i;
continue inner;
}
}
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 14b2429..1763a00 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -289,6 +289,7 @@
public void setCustomizationFilter(CustomizationType filterType) {
mCustomizationType = filterType;
setCurrentPage(0);
+ updateCurrentPageScroll();
invalidatePageData();
// End the current choice mode so that we don't carry selections across tabs
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 81e1847..37c2b41 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -316,7 +316,8 @@
mHomeCustomizationDrawer.setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
// animate the changing of the tab content by fading pages in and out
- final int duration = 150;
+ final Resources res = getResources();
+ final int duration = res.getInteger(R.integer.config_tabTransitionTime);
final float alpha = mCustomizePagedView.getAlpha();
ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mCustomizePagedView,
"alpha", alpha, 0.0f);
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 70746b3..109696c 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -245,6 +245,17 @@
}
/**
+ * Updates the scroll of the current page immediately to its final scroll position. We use this
+ * in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of
+ * the previous tab page.
+ */
+ protected void updateCurrentPageScroll() {
+ int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage);
+ scrollTo(newX, 0);
+ mScroller.setFinalX(newX);
+ }
+
+ /**
* Sets the current page.
*/
void setCurrentPage(int currentPage) {
@@ -256,9 +267,7 @@
}
mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
- int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage);
- scrollTo(newX, 0);
- mScroller.setFinalX(newX);
+ updateCurrentPageScroll();
invalidate();
notifyPageSwitchListener();
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index e068a76..3823cc1 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -20,9 +20,9 @@
import java.util.HashSet;
import java.util.List;
+import android.R.integer;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
@@ -55,6 +55,7 @@
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Pair;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -558,12 +559,11 @@
int delta = screenCenter - (getChildOffset(i) -
getRelativeChildOffset(i) + halfScreenSize);
- float scrollProgress = delta/(totalDistance*1.0f);
+ float scrollProgress = delta / (totalDistance * 1.0f);
scrollProgress = Math.min(scrollProgress, 1.0f);
scrollProgress = Math.max(scrollProgress, -1.0f);
- float mult = mInDragMode ? 1.0f : Math.abs(scrollProgress);
- cl.setBackgroundAlphaMultiplier(mult);
+ cl.setBackgroundAlphaMultiplier(Math.abs(scrollProgress));
float rotation = WORKSPACE_ROTATION * scrollProgress;
cl.setRotationY(rotation);
@@ -779,6 +779,9 @@
mActivePointerId = INVALID_POINTER;
CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
+ if (currentPage.getBackgroundAlphaMultiplier() < 1.0f) {
+ currentPage.setBackgroundAlpha(0.0f);
+ }
currentPage.setBackgroundAlphaMultiplier(1.0f);
final Resources res = getResources();
@@ -1043,8 +1046,8 @@
// For a TextView, adjust the clip rect so that we don't include the text label
if (v instanceof TextView) {
- final int iconHeight = ((TextView)v).getCompoundPaddingTop() - v.getPaddingTop();
- clipRect.bottom = clipRect.top + iconHeight;
+ final TextView tv = (TextView) v;
+ clipRect.bottom = clipRect.top + tv.getCompoundPaddingTop() - 1;
}
// Draw the View into the bitmap.
@@ -1351,8 +1354,6 @@
mDragTargetLayout.onDragEnter();
showOutlines();
mInDragMode = true;
- CellLayout cl = (CellLayout) getChildAt(mCurrentPage);
- cl.setBackgroundAlphaMultiplier(1.0f);
}
}
@@ -1398,6 +1399,30 @@
}
/**
+ * Tests to see if the drop will be accepted by Launcher, and if so, includes additional data
+ * in the returned structure related to the widgets that match the drop (or a null list if it is
+ * a shortcut drop). If the drop is not accepted then a null structure is returned.
+ */
+ private Pair<Integer, List<WidgetMimeTypeHandlerData>> validateDrag(DragEvent event) {
+ final LauncherModel model = mLauncher.getModel();
+ final ClipDescription desc = event.getClipDescription();
+ final int mimeTypeCount = desc.getMimeTypeCount();
+ for (int i = 0; i < mimeTypeCount; ++i) {
+ final String mimeType = desc.getMimeType(i);
+ if (mimeType.equals(InstallShortcutReceiver.SHORTCUT_MIMETYPE)) {
+ return new Pair<Integer, List<WidgetMimeTypeHandlerData>>(i, null);
+ } else {
+ final List<WidgetMimeTypeHandlerData> widgets =
+ model.resolveWidgetsForMimeType(mContext, mimeType);
+ if (widgets.size() > 0) {
+ return new Pair<Integer, List<WidgetMimeTypeHandlerData>>(i, widgets);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
* Global drag and drop handler
*/
@Override
@@ -1411,10 +1436,22 @@
final int y = (int) event.getY() - pos[1];
switch (event.getAction()) {
- case DragEvent.ACTION_DRAG_STARTED:
- // Check if we have enough space on this screen to add a new shortcut
- if (!layout.findCellForSpan(pos, 1, 1)) {
- Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
+ case DragEvent.ACTION_DRAG_STARTED: {
+ // Validate this drag
+ Pair<Integer, List<WidgetMimeTypeHandlerData>> test = validateDrag(event);
+ if (test != null) {
+ boolean isShortcut = (test.second == null);
+ if (isShortcut) {
+ // Check if we have enough space on this screen to add a new shortcut
+ if (!layout.findCellForSpan(pos, 1, 1)) {
+ Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+ } else {
+ // Show error message if we couldn't accept any of the items
+ Toast.makeText(mContext, mContext.getString(R.string.external_drop_widget_error),
Toast.LENGTH_SHORT).show();
return false;
}
@@ -1432,18 +1469,12 @@
layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
return true;
+ }
case DragEvent.ACTION_DRAG_LOCATION:
// Visualize the drop location
layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
return true;
- case DragEvent.ACTION_DROP:
- // Check if we have enough space on this screen to add a new shortcut
- if (!layout.findCellForSpan(pos, 1, 1)) {
- Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
- Toast.LENGTH_SHORT).show();
- return false;
- }
-
+ case DragEvent.ACTION_DROP: {
// Try and add any shortcuts
int newDropCount = 0;
final LauncherModel model = mLauncher.getModel();
@@ -1455,29 +1486,25 @@
// representation will be handled.
pos[0] = x;
pos[1] = y;
- final int mimeTypeCount = desc.getMimeTypeCount();
- for (int j = 0; j < mimeTypeCount; ++j) {
- final String mimeType = desc.getMimeType(j);
-
- if (mimeType.equals(InstallShortcutReceiver.SHORTCUT_MIMETYPE)) {
- final Intent intent = data.getItem(j).getIntent();
+ Pair<Integer, List<WidgetMimeTypeHandlerData>> test = validateDrag(event);
+ if (test != null) {
+ final int index = test.first;
+ final List<WidgetMimeTypeHandlerData> widgets = test.second;
+ final boolean isShortcut = (widgets == null);
+ final String mimeType = desc.getMimeType(index);
+ if (isShortcut) {
+ final Intent intent = data.getItem(index).getIntent();
Object info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
onDropExternal(x, y, info, layout);
} else {
- final List<WidgetMimeTypeHandlerData> widgets =
- model.resolveWidgetsForMimeType(mContext, mimeType);
- final int numWidgets = widgets.size();
-
- if (numWidgets == 0) {
- continue;
- } else if (numWidgets == 1) {
+ if (widgets.size() == 1) {
// If there is only one item, then go ahead and add and configure
// that widget
final AppWidgetProviderInfo widgetInfo = widgets.get(0).widgetInfo;
final PendingAddWidgetInfo createInfo =
new PendingAddWidgetInfo(widgetInfo, mimeType, data);
mLauncher.addAppWidgetFromDrop(createInfo, mCurrentPage, pos);
- } else if (numWidgets > 1) {
+ } else {
// Show the widget picker dialog if there is more than one widget
// that can handle this data type
final InstallWidgetReceiver.WidgetListAdapter adapter =
@@ -1493,17 +1520,9 @@
builder.show();
}
}
- newDropCount++;
- break;
}
-
- // Show error message if we couldn't accept any of the items
- if (newDropCount <= 0) {
- Toast.makeText(mContext, mContext.getString(R.string.external_drop_widget_error),
- Toast.LENGTH_SHORT).show();
- }
-
return true;
+ }
case DragEvent.ACTION_DRAG_ENDED:
// Hide the page outlines after the drop
layout.setHover(false);
@@ -1825,7 +1844,8 @@
if (view == null) {
cellLayout.onDragExit();
} else {
- mTargetCell = findNearestVacantArea(x, y, 1, 1, null, cellLayout, mTargetCell);
+ mTargetCell = new int[]{x, y};
+ cellLayout.findCellForSpan(mTargetCell, 1, 1);
addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
cellLayout.onDropChild(view);