Merge branch 'master' into honeycomb-release
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4aa5d68..247f5b7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -75,7 +75,7 @@
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:theme="@style/Theme"
- android:windowSoftInputMode="stateUnspecified|adjustPan">
+ android:windowSoftInputMode="stateUnspecified|adjustNothing">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
@@ -88,6 +88,7 @@
android:name="com.android.launcher2.WallpaperChooser"
android:label="@string/pick_wallpaper"
android:icon="@drawable/ic_launcher_wallpaper"
+ android:theme="@style/Theme.WallpaperPicker"
android:screenOrientation="nosensor"
android:finishOnCloseSystemDialogs="true">
<intent-filter>
diff --git a/res/drawable-xlarge-hdpi/textfield_end.9.png b/res/drawable-xlarge-hdpi/textfield_end.9.png
deleted file mode 100644
index be1b2b6..0000000
--- a/res/drawable-xlarge-hdpi/textfield_end.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/textfield_end.9.png b/res/drawable-xlarge-hdpi/textfield_home_end.9.png
similarity index 92%
rename from res/drawable-xlarge-mdpi/textfield_end.9.png
rename to res/drawable-xlarge-hdpi/textfield_home_end.9.png
index 94706b4..4e79920 100644
--- a/res/drawable-xlarge-mdpi/textfield_end.9.png
+++ b/res/drawable-xlarge-hdpi/textfield_home_end.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/textfield_home_start.9.png b/res/drawable-xlarge-hdpi/textfield_home_start.9.png
new file mode 100644
index 0000000..a338c69
--- /dev/null
+++ b/res/drawable-xlarge-hdpi/textfield_home_start.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/textfield_start.9.png b/res/drawable-xlarge-hdpi/textfield_start.9.png
deleted file mode 100644
index 6b5ebe2..0000000
--- a/res/drawable-xlarge-hdpi/textfield_start.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/textfield_end.9.png b/res/drawable-xlarge-mdpi/textfield_home_end.9.png
similarity index 92%
copy from res/drawable-xlarge-mdpi/textfield_end.9.png
copy to res/drawable-xlarge-mdpi/textfield_home_end.9.png
index 94706b4..753514f 100644
--- a/res/drawable-xlarge-mdpi/textfield_end.9.png
+++ b/res/drawable-xlarge-mdpi/textfield_home_end.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/textfield_start.9.png b/res/drawable-xlarge-mdpi/textfield_home_start.9.png
similarity index 90%
rename from res/drawable-xlarge-mdpi/textfield_start.9.png
rename to res/drawable-xlarge-mdpi/textfield_home_start.9.png
index 8cddc34..11ee7ca 100644
--- a/res/drawable-xlarge-mdpi/textfield_start.9.png
+++ b/res/drawable-xlarge-mdpi/textfield_home_start.9.png
Binary files differ
diff --git a/res/layout-xlarge-land/launcher.xml b/res/layout-xlarge-land/launcher.xml
index 7516796..f93506e 100644
--- a/res/layout-xlarge-land/launcher.xml
+++ b/res/layout-xlarge-land/launcher.xml
@@ -63,7 +63,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
- android:background="@drawable/textfield_start"
+ android:background="@drawable/textfield_home_start"
android:orientation="horizontal">
<!-- Global search icon -->
<ImageView
@@ -84,7 +84,7 @@
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:background="@drawable/textfield_end"
+ android:background="@drawable/textfield_home_end"
android:orientation="horizontal">
<!-- Voice search icon -->
<ImageView
diff --git a/res/layout-xlarge-port/launcher.xml b/res/layout-xlarge-port/launcher.xml
index c2ca467..088f081 100644
--- a/res/layout-xlarge-port/launcher.xml
+++ b/res/layout-xlarge-port/launcher.xml
@@ -63,7 +63,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
- android:background="@drawable/textfield_start"
+ android:background="@drawable/textfield_home_start"
android:orientation="horizontal">
<!-- Global search icon -->
<ImageView
@@ -84,7 +84,7 @@
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:background="@drawable/textfield_end"
+ android:background="@drawable/textfield_home_end"
android:orientation="horizontal">
<!-- Voice search icon -->
<ImageView
diff --git a/res/layout-xlarge/wallpaper_chooser.xml b/res/layout-xlarge/wallpaper_chooser.xml
new file mode 100644
index 0000000..9649e88
--- /dev/null
+++ b/res/layout-xlarge/wallpaper_chooser.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/gallery"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:numColumns="4"
+ android:columnWidth="@dimen/wallpaper_small_width"
+ android:stretchMode="columnWidth" />
\ No newline at end of file
diff --git a/res/layout-xlarge/wallpaper_item.xml b/res/layout-xlarge/wallpaper_item.xml
new file mode 100644
index 0000000..4246b9a
--- /dev/null
+++ b/res/layout-xlarge/wallpaper_item.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/wallpaper_small_width"
+ android:layout_height="wrap_content"
+ android:padding="5dp"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="false"
+ android:focusable="false" />
diff --git a/res/layout/wallpaper_chooser_base.xml b/res/layout/wallpaper_chooser_base.xml
new file mode 100644
index 0000000..8447027
--- /dev/null
+++ b/res/layout/wallpaper_chooser_base.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/wallpaper_chooser_base"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+</FrameLayout>
diff --git a/res/values-xlarge/config.xml b/res/values-xlarge/config.xml
index fa7af5e..3654753 100644
--- a/res/values-xlarge/config.xml
+++ b/res/values-xlarge/config.xml
@@ -37,7 +37,7 @@
<!-- When dragging items on the workspace, the number of pixels by which the position of
the drag view should be offset from the position of the original view. -->
<integer name="config_dragViewOffsetX">0</integer>
- <integer name="config_dragViewOffsetY">12</integer>
+ <integer name="config_dragViewOffsetY">-12</integer>
<!-- When items are dropped on the mini screens in customize mode, we have a bounce animation
of the bright green hover outline, and then fade out the outline at the end. These are
diff --git a/res/values-xlarge/dimens.xml b/res/values-xlarge/dimens.xml
index d98674f..7033553 100644
--- a/res/values-xlarge/dimens.xml
+++ b/res/values-xlarge/dimens.xml
@@ -50,4 +50,7 @@
<dimen name="delete_zone_size">50dip</dimen>
<dimen name="delete_zone_min_padding">10dip</dimen>
<dimen name="delete_zone_max_padding">20dip</dimen>
+
+ <!-- dimensions for the wallpaper picker wallpaper thumbnail width -->
+ <dimen name="wallpaper_small_width">170dp</dimen>
</resources>
diff --git a/res/values-xlarge/strings.xml b/res/values-xlarge/strings.xml
new file mode 100644
index 0000000..d8bdbbc
--- /dev/null
+++ b/res/values-xlarge/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2010 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Title of the wallpaper selection dialog [CHAR_LIMIT=40]-->
+ <string name="wallpaper_dialog_title">Select wallpaper</string>
+
+ <!-- Negative button text for the wallpaper selection dialog [CHAR_LIMIT=40]-->
+ <string name="wallpaper_cancel">Cancel</string>
+</resources>
\ No newline at end of file
diff --git a/res/values-xlarge/styles.xml b/res/values-xlarge/styles.xml
index fcbd969..5198d30 100644
--- a/res/values-xlarge/styles.xml
+++ b/res/values-xlarge/styles.xml
@@ -18,6 +18,9 @@
-->
<resources>
+ <style name="Theme.WallpaperPicker" parent="android:Theme.Holo.Dialog.NoFrame">
+ </style>
+
<style name="Theme" parent="android:Theme.Holo">
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionModeOverlay">true</item>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d6cd3ee..39739c2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -44,4 +44,8 @@
<!-- the area at the edge of the screen that makes the workspace go left
or right while you're dragging. -->
<dimen name="scroll_zone">20dp</dimen>
+
+ <!-- How much the content view of an alert dialog should be inset (currently used
+ for the WallpaperChooser in XLarge mode) -->
+ <dimen name="alert_dialog_content_inset">15dp</dimen>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a97b3c5..c867d38 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -18,6 +18,10 @@
-->
<resources>
+ <style name="Theme.WallpaperPicker" parent="android:Theme">
+ <item name="android:windowNoTitle">true</item>
+ </style>
+
<style name="Theme.Base" parent="android:Theme.Wallpaper">
</style>
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 9764f23..66d9395 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -201,10 +201,16 @@
}
}
+ @Override
public void setDragController(DragController dragger) {
mDragController = dragger;
}
+ @Override
+ public void onDragViewVisible() {
+ }
+
+ @Override
public void onDropCompleted(View target, boolean success) {
}
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index b56a9c9..b75d08a 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -192,6 +192,7 @@
destroyRenderScript();
sRS = null;
sRollo = null;
+ super.onDetachedFromWindow();
}
}
@@ -735,10 +736,16 @@
return false;
}
+ @Override
public void setDragController(DragController dragger) {
mDragController = dragger;
}
+ @Override
+ public void onDragViewVisible() {
+ }
+
+ @Override
public void onDropCompleted(View target, boolean success) {
}
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index 1f3df5f..4ca5b47 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -237,6 +237,10 @@
}
@Override
+ public void onDragViewVisible() {
+ }
+
+ @Override
public void onDropCompleted(View target, boolean success) {
// close the choice action mode if we have a proper drop
if (target != this) {
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index e340101..023e9f4 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -1241,7 +1241,6 @@
void onDragChild(View child) {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
lp.isDragging = true;
- child.setVisibility(View.GONE);
}
/**
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 6db6aa9..b48d4ab 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -312,6 +312,10 @@
}
@Override
+ public void onDragViewVisible() {
+ }
+
+ @Override
public void onClick(View v) {
// Return early if this is not initiated from a touch
if (!v.isInTouchMode()) return;
@@ -490,16 +494,14 @@
mLauncher.getWorkspace().onDragStartedWithItemMinSize(
createWidgetInfo.minWidth, createWidgetInfo.minHeight);
- mDragController.startDrag(v, b, this, createWidgetInfo, DragController.DRAG_ACTION_COPY,
- null);
+ mDragController.startDrag(v, b, this, createWidgetInfo, DragController.DRAG_ACTION_COPY, null);
// Cleanup the icon
b.recycle();
return true;
case ShortcutCustomization:
createItemInfo = (PendingAddItemInfo) v.getTag();
- mDragController.startDrag(
- v, this, createItemInfo, DragController.DRAG_ACTION_COPY, null);
+ mDragController.startDrag(v, this, createItemInfo, DragController.DRAG_ACTION_COPY);
mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1);
return true;
case ApplicationCustomization:
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 2b566b7..a0a44a5 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -320,6 +320,13 @@
DragView dragView = mDragView = new DragView(mContext, b, registrationX, registrationY,
textureLeft, textureTop, textureWidth, textureHeight);
+ final DragSource dragSource = source;
+ dragView.setOnDrawRunnable(new Runnable() {
+ public void run() {
+ dragSource.onDragViewVisible();
+ };
+ });
+
if (dragRegion != null) {
dragView.setDragRegion(dragRegionLeft, dragRegion.top,
dragRegion.right - dragRegionLeft, dragRegion.bottom - dragRegionTop);
diff --git a/src/com/android/launcher2/DragSource.java b/src/com/android/launcher2/DragSource.java
index 7c6ca58..11cdcc9 100644
--- a/src/com/android/launcher2/DragSource.java
+++ b/src/com/android/launcher2/DragSource.java
@@ -24,5 +24,12 @@
*/
public interface DragSource {
void setDragController(DragController dragger);
+
+ /**
+ * Callback from the DragController when it begins drawing the drag view.
+ * This allows the DragSource to dim or hide the original view.
+ */
+ void onDragViewVisible();
+
void onDropCompleted(View target, boolean success);
}
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index ca0e7b4..947184f 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -19,6 +19,8 @@
import com.android.launcher.R;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -32,8 +34,9 @@
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
+import android.view.animation.DecelerateInterpolator;
-public class DragView extends View implements TweenCallback {
+public class DragView extends View {
private Bitmap mBitmap;
private Paint mPaint;
private int mRegistrationX;
@@ -44,14 +47,22 @@
private int mDragRegionWidth;
private int mDragRegionHeight;
- SymmetricalLinearTween mTween;
- private float mScale;
- private float mAnimationScale = 1.0f;
+ ValueAnimator mAnim;
+ private float mScale = 1.0f;
+ private float mOffsetX = 0.0f;
+ private float mOffsetY = 0.0f;
private WindowManager.LayoutParams mLayoutParams;
private WindowManager mWindowManager;
/**
+ * A callback to be called the first time this view is drawn.
+ * This allows the originator of the drag to dim or hide the original view as soon
+ * as the DragView is drawn.
+ */
+ private Runnable mOnDrawRunnable = null;
+
+ /**
* Construct the drag view.
* <p>
* The registration point is the point inside our view that the touch events should
@@ -70,20 +81,48 @@
final int dragScale = res.getInteger(R.integer.config_dragViewExtraPixels);
mWindowManager = WindowManagerImpl.getDefault();
-
- mTween = new SymmetricalLinearTween(false, 110 /*ms duration*/, this);
Matrix scale = new Matrix();
- float scaleFactor = width;
- scaleFactor = mScale = (scaleFactor + dragScale) / scaleFactor;
- scale.setScale(scaleFactor, scaleFactor);
+ final float scaleFactor = (width + dragScale) / width;
+ if (scaleFactor != 1.0f) {
+ scale.setScale(scaleFactor, scaleFactor);
+ }
+
+ final int offsetX = res.getInteger(R.integer.config_dragViewOffsetX);
+ final int offsetY = res.getInteger(R.integer.config_dragViewOffsetY);
+
+ // Animate the view into the correct position
+ mAnim = ValueAnimator.ofFloat(0.0f, 1.0f);
+ mAnim.setDuration(110);
+ mAnim.setInterpolator(new DecelerateInterpolator(2.5f));
+ mAnim.addUpdateListener(new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float value = (Float) animation.getAnimatedValue();
+
+ final int deltaX = (int) ((value * offsetX) - mOffsetX);
+ final int deltaY = (int) ((value * offsetY) - mOffsetY);
+
+ mOffsetX += deltaX;
+ mOffsetY += deltaY;
+
+ if (getParent() == null) {
+ animation.cancel();
+ } else {
+ WindowManager.LayoutParams lp = mLayoutParams;
+ lp.x += deltaX;
+ lp.y += deltaY;
+ mWindowManager.updateViewLayout(DragView.this, lp);
+ }
+ }
+ });
mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
setDragRegion(0, 0, width, height);
// The point in our scaled bitmap that the touch events are located
- mRegistrationX = registrationX + res.getInteger(R.integer.config_dragViewOffsetX);
- mRegistrationY = registrationY + res.getInteger(R.integer.config_dragViewOffsetY);
+ mRegistrationX = registrationX;
+ mRegistrationY = registrationY;
}
public void setDragRegion(int left, int top, int width, int height) {
@@ -93,6 +132,10 @@
mDragRegionHeight = height;
}
+ public void setOnDrawRunnable(Runnable r) {
+ mOnDrawRunnable = r;
+ }
+
public int getScaledDragRegionXOffset() {
return -(int)((mScale - 1.0f) * mDragRegionWidth / 2);
}
@@ -139,13 +182,15 @@
p.setColor(0xaaffffff);
canvas.drawRect(0, 0, getWidth(), getHeight(), p);
}
- float scale = mAnimationScale;
- if (scale < 0.999f) { // allow for some float error
- float width = mBitmap.getWidth();
- float offset = (width-(width*scale))/2;
- canvas.translate(offset, offset);
- canvas.scale(scale, scale);
+
+ // Call the callback if we haven't already been detached
+ if (getParent() != null) {
+ if (mOnDrawRunnable != null) {
+ mOnDrawRunnable.run();
+ mOnDrawRunnable = null;
+ }
}
+
canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
}
@@ -155,17 +200,6 @@
mBitmap.recycle();
}
- public void onTweenValueChanged(float value, float oldValue) {
- mAnimationScale = (1.0f+((mScale-1.0f)*value))/mScale;
- invalidate();
- }
-
- public void onTweenStarted() {
- }
-
- public void onTweenFinished() {
- }
-
public void setPaint(Paint paint) {
mPaint = paint;
invalidate();
@@ -187,7 +221,7 @@
lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
- touchX-mRegistrationX, touchY-mRegistrationY,
+ touchX - mRegistrationX, touchY - mRegistrationY,
WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
@@ -201,8 +235,7 @@
mWindowManager.addView(this, lp);
- mAnimationScale = 1.0f/mScale;
- mTween.start(true);
+ mAnim.start();
}
/**
@@ -213,8 +246,8 @@
*/
void move(int touchX, int touchY) {
WindowManager.LayoutParams lp = mLayoutParams;
- lp.x = touchX - mRegistrationX;
- lp.y = touchY - mRegistrationY;
+ lp.x = touchX - mRegistrationX + (int) mOffsetX;
+ lp.y = touchY - mRegistrationY + (int) mOffsetY;
mWindowManager.updateViewLayout(this, lp);
}
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 018b284..cb450b9 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -108,13 +108,19 @@
return true;
}
+ @Override
public void setDragController(DragController dragController) {
mDragController = dragController;
}
+ @Override
public void onDropCompleted(View target, boolean success) {
}
+ @Override
+ public void onDragViewVisible() {
+ }
+
/**
* Sets the adapter used to populate the content area. The adapter must only
* contains ShortcutInfo items.
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 55a6176..2a2d364 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -1101,7 +1101,7 @@
// supporting spring-loaded mini-screens; however, leaving the ability to directly place
// a widget on the home screen in case we want to add it in the future
int[] touchXY = null;
- if (mAddDropPosition[0] > -1 && mAddDropPosition[1] > -1) {
+ if (mAddDropPosition != null && mAddDropPosition[0] > -1 && mAddDropPosition[1] > -1) {
touchXY = mAddDropPosition;
}
boolean findNearestVacantAreaFailed = false;
@@ -1114,15 +1114,12 @@
findNearestVacantAreaFailed = (result == null);
foundCellSpan = !findNearestVacantAreaFailed;
} else {
- if (mAddIntersectCellX != -1 && mAddIntersectCellY != -1) {
- // if we long pressed on an empty cell to bring up a menu,
- // make sure we intersect the empty cell
- foundCellSpan = layout.findCellForSpanThatIntersects(cellXY, spanXY[0], spanXY[1],
- mAddIntersectCellX, mAddIntersectCellY);
- } else {
- // if we went through the menu -> add, just find any spot
- foundCellSpan = layout.findCellForSpan(cellXY, spanXY[0], spanXY[1]);
- }
+ // if we long pressed on an empty cell to bring up a menu,
+ // make sure we intersect the empty cell
+ // if mAddIntersectCellX/Y are -1 (e.g. we used menu -> add) then
+ // findCellForSpanThatIntersects will just ignore them
+ foundCellSpan = layout.findCellForSpanThatIntersects(cellXY, spanXY[0], spanXY[1],
+ mAddIntersectCellX, mAddIntersectCellY);
}
if (!foundCellSpan) {
@@ -1923,6 +1920,8 @@
*/
public void onClickSearchButton(View v) {
startSearch(null, false, null, true);
+ // Use a custom animation for launching search
+ overridePendingTransition(R.anim.fade_in_fast, R.anim.fade_out_fast);
}
/**
@@ -2776,7 +2775,9 @@
}
void showWorkspace(boolean animated, CellLayout layout) {
- if (layout != null && animated) {
+ if (layout != null) {
+ // always animated, but that's ok since we never specify a layout and
+ // want no animation
mWorkspace.unshrink(layout);
} else {
mWorkspace.unshrink(animated);
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 264e839..d24eef4 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -36,6 +36,7 @@
import android.view.ViewParent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import android.view.animation.Animation.AnimationListener;
import android.widget.Checkable;
import android.widget.Scroller;
@@ -55,10 +56,12 @@
// The min drag distance to trigger a page shift (regardless of velocity)
private static final int MIN_LENGTH_FOR_MOVE = 200;
- private static final int PAGE_SNAP_ANIMATION_DURATION = 750;
+ private static final int PAGE_SNAP_ANIMATION_DURATION = 550;
protected static final float NANOTIME_DIV = 1000000000.0f;
- private static final float OVERSCROLL_DAMP_FACTOR = 0.22f;
+ private static final float OVERSCROLL_DAMP_FACTOR = 0.08f;
+ private static final int MINIMUM_SNAP_VELOCITY = 2200;
+ private static final int MIN_FLING_VELOCITY = 250;
// the velocity at which a fling gesture will cause us to snap to the next page
protected int mSnapVelocity = 500;
@@ -209,7 +212,7 @@
mDirtyPageContent = new ArrayList<Boolean>();
mDirtyPageContent.ensureCapacity(32);
mPageViewIconCache = new PagedViewIconCache();
- mScroller = new Scroller(getContext());
+ mScroller = new Scroller(getContext(), new ScrollInterpolator());
mCurrentPage = 0;
mCenterPagesVertically = true;
@@ -353,7 +356,11 @@
mCurrentPage = Math.max(0, Math.min(mNextPage, getPageCount() - 1));
mNextPage = INVALID_PAGE;
notifyPageSwitchListener();
- pageEndMoving();
+ // We don't want to trigger a page end moving unless the page has settled
+ // and the user has stopped scrolling
+ if (mTouchState == TOUCH_STATE_REST) {
+ pageEndMoving();
+ }
return true;
}
return false;
@@ -827,8 +834,22 @@
return false;
}
+ // This curve determines how the effect of scrolling over the limits of the page dimishes
+ // as the user pulls further and further from the bounds
+ private float overScrollInfluenceCurve(float f) {
+ f -= 1.0f;
+ return f * f * f + 1.0f;
+ }
+
protected void overScroll(float amount) {
- int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * amount);
+ int screenSize = getMeasuredWidth();
+
+ float f = (amount / screenSize);
+
+ if (f == 0) return;
+ f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
+
+ int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * f * screenSize);
if (amount < 0) {
mScrollX = overScrollAmount;
} else {
@@ -902,8 +923,7 @@
final int snapVelocity = mSnapVelocity;
if ((isSignificantMove && deltaX > 0 ||
- (isfling && velocityX > snapVelocity)) &&
- mCurrentPage > 0) {
+ (isfling && velocityX > snapVelocity)) && mCurrentPage > 0) {
snapToPageWithVelocity(mCurrentPage - 1, velocityX);
} else if ((isSignificantMove && deltaX < 0 ||
(isfling && velocityX < -snapVelocity)) &&
@@ -1048,10 +1068,58 @@
snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION);
}
+ private static class ScrollInterpolator implements Interpolator {
+ public ScrollInterpolator() {
+ }
+
+ public float getInterpolation(float t) {
+ t -= 1.0f;
+ return t*t*t*t*t + 1;
+ }
+ }
+
+ // We want the duration of the page snap animation to be influenced by the distance that
+ // the screen has to travel, however, we don't want this duration to be effected in a
+ // purely linear fashion. Instead, we use this method to moderate the effect that the distance
+ // of travel has on the overall snap duration.
+ float distanceInfluenceForSnapDuration(float f) {
+ f -= 0.5f; // center the values about 0.
+ f *= 0.3f * Math.PI / 2.0f;
+ return (float) Math.sin(f);
+ }
+
protected void snapToPageWithVelocity(int whichPage, int velocity) {
- // We ignore velocity in this implementation, but children (e.g. SmoothPagedView)
- // can use it
- snapToPage(whichPage);
+ whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
+ int halfScreenSize = getMeasuredWidth() / 2;
+
+ final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
+ int delta = newX - mUnboundedScrollX;
+ int duration = 0;
+
+ if (Math.abs(velocity) < MIN_FLING_VELOCITY) {
+ // If the velocity is low enough, then treat this more as an automatic page advance
+ // as opposed to an apparent physical response to flinging
+ snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+ return;
+ }
+
+ // Here we compute a "distance" that will be used in the computation of the overall
+ // snap duration. This is a function of the actual distance that needs to be traveled;
+ // we keep this value close to half screen size in order to reduce the variance in snap
+ // duration as a function of the distance the page needs to travel.
+ float distanceRatio = 1.0f * Math.abs(delta) / 2 * halfScreenSize;
+ float distance = halfScreenSize + halfScreenSize *
+ distanceInfluenceForSnapDuration(distanceRatio);
+
+ velocity = Math.abs(velocity);
+ velocity = Math.max(MINIMUM_SNAP_VELOCITY, velocity);
+
+ // we want the page's snap velocity to approximately match the velocity at which the
+ // user flings, so we scale the duration by a value near to the derivative of the scroll
+ // interpolator at zero, ie. 5. We use 6 to make it a little slower.
+ duration = 6 * Math.round(1000 * Math.abs(distance / velocity));
+
+ snapToPage(whichPage, delta, duration);
}
protected void snapToPage(int whichPage) {
diff --git a/src/com/android/launcher2/SmoothPagedView.java b/src/com/android/launcher2/SmoothPagedView.java
index ee8bca2..8b0a835 100644
--- a/src/com/android/launcher2/SmoothPagedView.java
+++ b/src/com/android/launcher2/SmoothPagedView.java
@@ -21,7 +21,6 @@
import android.view.animation.Interpolator;
import android.widget.Scroller;
-
public abstract class SmoothPagedView extends PagedView {
private static final float SMOOTHING_SPEED = 0.75f;
private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED));
@@ -29,8 +28,8 @@
private float mBaseLineFlingVelocity;
private float mFlingVelocityInfluence;
- static final int OVERSHOOT_MODE = 0;
- static final int QUINTIC_MODE = 1;
+ static final int DEFAULT_MODE = 0;
+ static final int X_LARGE_MODE = 1;
int mScrollMode;
@@ -60,16 +59,6 @@
}
}
- private static class QuinticInterpolator implements Interpolator {
- public QuinticInterpolator() {
- }
-
- public float getInterpolation(float t) {
- t -= 1.0f;
- return t*t*t*t*t + 1;
- }
- }
-
/**
* Used to inflate the Workspace from XML.
*
@@ -93,12 +82,12 @@
mUsePagingTouchSlop = false;
// This means that we'll take care of updating the scroll parameter ourselves (we do it
- // in computeScroll)
- mDeferScrollUpdate = true;
+ // in computeScroll), we only do this in the OVERSHOOT_MODE, ie. on phones
+ mDeferScrollUpdate = mScrollMode != X_LARGE_MODE;
}
protected int getScrollMode() {
- return OVERSHOOT_MODE;
+ return DEFAULT_MODE;
}
/**
@@ -109,26 +98,30 @@
super.init();
mScrollMode = getScrollMode();
- if (mScrollMode == QUINTIC_MODE) {
- mBaseLineFlingVelocity = 700.0f;
- mFlingVelocityInfluence = 0.8f;
- mScrollInterpolator = new QuinticInterpolator();
- } else { // QUINTIC_MODE
+ if (mScrollMode == DEFAULT_MODE) {
mBaseLineFlingVelocity = 2500.0f;
mFlingVelocityInfluence = 0.4f;
mScrollInterpolator = new WorkspaceOvershootInterpolator();
+ mScroller = new Scroller(getContext(), mScrollInterpolator);
}
- mScroller = new Scroller(getContext(), mScrollInterpolator);
}
@Override
protected void snapToDestination() {
- snapToPageWithVelocity(getPageNearestToCenterOfScreen(), 0);
+ if (mScrollMode == X_LARGE_MODE) {
+ super.snapToDestination();
+ } else {
+ snapToPageWithVelocity(getPageNearestToCenterOfScreen(), 0);
+ }
}
@Override
protected void snapToPageWithVelocity(int whichPage, int velocity) {
- snapToPageWithVelocity(whichPage, 0, true);
+ if (mScrollMode == X_LARGE_MODE) {
+ super.snapToPageWithVelocity(whichPage, velocity);
+ } else {
+ snapToPageWithVelocity(whichPage, 0, true);
+ }
}
private void snapToPageWithVelocity(int whichPage, int velocity, boolean settle) {
@@ -139,23 +132,16 @@
final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage));
final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
final int delta = newX - mUnboundedScrollX;
- int duration;
- if (mScrollMode == OVERSHOOT_MODE) {
- duration = (screenDelta + 1) * 100;
- } else { // QUINTIC_MODE
- duration = Math.round(Math.abs(delta) * 0.6f);
- }
+ int duration = (screenDelta + 1) * 100;
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
- if (mScrollMode == OVERSHOOT_MODE) {
- if (settle) {
- ((WorkspaceOvershootInterpolator) mScrollInterpolator).setDistance(screenDelta);
- } else {
- ((WorkspaceOvershootInterpolator) mScrollInterpolator).disableSettle();
- }
+ if (settle) {
+ ((WorkspaceOvershootInterpolator) mScrollInterpolator).setDistance(screenDelta);
+ } else {
+ ((WorkspaceOvershootInterpolator) mScrollInterpolator).disableSettle();
}
velocity = Math.abs(velocity);
@@ -170,26 +156,33 @@
@Override
protected void snapToPage(int whichPage) {
- snapToPageWithVelocity(whichPage, 0, false);
+ if (mScrollMode == X_LARGE_MODE) {
+ super.snapToPage(whichPage);
+ } else {
+ snapToPageWithVelocity(whichPage, 0, false);
+ }
}
@Override
public void computeScroll() {
- boolean scrollComputed = computeScrollHelper();
+ if (mScrollMode == X_LARGE_MODE) {
+ super.computeScroll();
+ } else {
+ boolean scrollComputed = computeScrollHelper();
- if (!scrollComputed && mTouchState == TOUCH_STATE_SCROLLING) {
- final float now = System.nanoTime() / NANOTIME_DIV;
- final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT);
+ if (!scrollComputed && mTouchState == TOUCH_STATE_SCROLLING) {
+ final float now = System.nanoTime() / NANOTIME_DIV;
+ final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT);
- final float dx = mTouchX - mUnboundedScrollX;
- scrollTo(Math.round(mUnboundedScrollX + dx * e), mScrollY);
- mSmoothingTime = now;
+ final float dx = mTouchX - mUnboundedScrollX;
+ scrollTo(Math.round(mUnboundedScrollX + dx * e), mScrollY);
+ mSmoothingTime = now;
- // Keep generating points as long as we're more than 1px away from the target
- if (dx > 1.f || dx < -1.f) {
- invalidate();
+ // Keep generating points as long as we're more than 1px away from the target
+ if (dx > 1.f || dx < -1.f) {
+ invalidate();
+ }
}
}
-
}
}
diff --git a/src/com/android/launcher2/WallpaperChooser.java b/src/com/android/launcher2/WallpaperChooser.java
index bf8ba2e..0a8d9f4 100644
--- a/src/com/android/launcher2/WallpaperChooser.java
+++ b/src/com/android/launcher2/WallpaperChooser.java
@@ -17,7 +17,13 @@
package com.android.launcher2;
import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentTransaction;
import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.DialogInterface;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
@@ -28,27 +34,26 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
+import android.widget.GridView;
import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.SpinnerAdapter;
import java.io.IOException;
import java.util.ArrayList;
import com.android.launcher.R;
-public class WallpaperChooser extends Activity implements AdapterView.OnItemSelectedListener,
- OnClickListener {
+public class WallpaperChooser extends Activity {
private static final String TAG = "Launcher.WallpaperChooser";
- private Gallery mGallery;
- private ImageView mImageView;
- private boolean mIsWallpaperSet;
-
- private Bitmap mBitmap;
+ private ViewGroup mWallpaperChooserBase;
+ private ImageView mImageView = null;
+ private Bitmap mBitmap = null;
private ArrayList<Integer> mThumbs;
private ArrayList<Integer> mImages;
@@ -57,20 +62,35 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
+ /* We need some container to attach to in order for the fragment to be
+ * considered embedded, so inflate an empty FrameLayout and use that
+ * as the parent view
+ */
+ setContentView(R.layout.wallpaper_chooser_base);
+ mWallpaperChooserBase = (ViewGroup) findViewById(R.id.wallpaper_chooser_base);
findWallpapers();
- setContentView(R.layout.wallpaper_chooser);
+ DialogFragment newFragment = new WallpaperDialogFragment(this);
+ if (LauncherApplication.isScreenXLarge()) {
+ // Display a dialog instead of embedding the view in the activity
+ newFragment.show(getFragmentManager(), "dialog");
+ } else {
+ // Embed the fragment in the base view
+ FragmentTransaction ft = getFragmentManager().openTransaction();
+ ft.add(R.id.wallpaper_chooser_base, newFragment);
+ ft.commit();
+ }
+ }
- mGallery = (Gallery) findViewById(R.id.gallery);
- mGallery.setAdapter(new ImageAdapter(this));
- mGallery.setOnItemSelectedListener(this);
- mGallery.setCallbackDuringFling(false);
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
- findViewById(R.id.set).setOnClickListener(this);
-
- mImageView = (ImageView) findViewById(R.id.wallpaper);
+ if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+ mLoader.cancel(true);
+ mLoader = null;
+ }
}
private void findWallpapers() {
@@ -105,40 +125,7 @@
}
}
- @Override
- protected void onResume() {
- super.onResume();
- mIsWallpaperSet = false;
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
- if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
- mLoader.cancel(true);
- mLoader = null;
- }
- }
-
- public void onItemSelected(AdapterView parent, View v, int position, long id) {
- if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
- mLoader.cancel();
- }
- mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
- }
-
- /*
- * When using touch if you tap an image it triggers both the onItemClick and
- * the onTouchEvent causing the wallpaper to be set twice. Ensure we only
- * set the wallpaper once.
- */
private void selectWallpaper(int position) {
- if (mIsWallpaperSet) {
- return;
- }
-
- mIsWallpaperSet = true;
try {
WallpaperManager wpm = (WallpaperManager)getSystemService(WALLPAPER_SERVICE);
wpm.setResource(mImages.get(position));
@@ -149,10 +136,95 @@
}
}
- public void onNothingSelected(AdapterView parent) {
+ private class WallpaperDialogFragment extends DialogFragment implements
+ AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+ private Context mContext;
+
+ public WallpaperDialogFragment(Context context) {
+ super();
+ mContext = context;
+ setCancelable(true);
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ WallpaperChooser.this.finish();
+ }
+
+ /* This will only be called when in XLarge mode, since this Fragment is invoked like
+ * a dialog in that mode
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final View v = getLayoutInflater().inflate(
+ R.layout.wallpaper_chooser, mWallpaperChooserBase, false);
+
+ GridView gridView = (GridView) v.findViewById(R.id.gallery);
+ gridView.setOnItemClickListener(this);
+ gridView.setAdapter(new ImageAdapter(WallpaperChooser.this));
+
+ final int viewInset =
+ getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_inset);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+ builder.setCancelable(true);
+ builder.setNegativeButton(R.string.wallpaper_cancel, null);
+ builder.setTitle(R.string.wallpaper_dialog_title);
+ builder.setView(gridView, viewInset, viewInset, viewInset, viewInset);
+ return builder.create();
+ }
+
+ /* This will be called on both XLarge and small screens, but since the dialog
+ * is already created on XLarge, we want to skip this view creation
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ /* Only generate a custom view if this fragment is being embedded in a view,
+ * i.e: on a small screen
+ */
+ if (!LauncherApplication.isScreenXLarge()) {
+ View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
+
+ final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
+ gallery.setCallbackDuringFling(false);
+ gallery.setOnItemSelectedListener(this);
+ gallery.setAdapter(new ImageAdapter(WallpaperChooser.this));
+
+ View setButton = view.findViewById(R.id.set);
+ setButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ selectWallpaper(gallery.getSelectedItemPosition());
+ }
+ });
+ mImageView = (ImageView) view.findViewById(R.id.wallpaper);
+ return view;
+ }
+ return super.onCreateView(inflater, container, savedInstanceState);
+ }
+
+ // Click handler for the Dialog's GridView
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ selectWallpaper(position);
+ }
+
+ // Selection handler for the embedded Gallery view
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+ mLoader.cancel();
+ }
+ mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
}
- private class ImageAdapter extends BaseAdapter {
+ private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
private LayoutInflater mLayoutInflater;
ImageAdapter(WallpaperChooser context) {
@@ -179,7 +251,7 @@
} else {
image = (ImageView) convertView;
}
-
+
int thumbRes = mThumbs.get(position);
image.setImageResource(thumbRes);
Drawable thumbDrawable = image.getDrawable();
@@ -189,14 +261,11 @@
Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #"
+ position);
}
+
return image;
}
}
- public void onClick(View v) {
- selectWallpaper(mGallery.getSelectedItemPosition());
- }
-
class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
BitmapFactory.Options mOptions;
@@ -205,7 +274,8 @@
mOptions.inDither = false;
mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
}
-
+
+ @Override
protected Bitmap doInBackground(Integer... params) {
if (isCancelled()) return null;
try {
@@ -225,17 +295,20 @@
if (mBitmap != null) {
mBitmap.recycle();
}
-
- final ImageView view = mImageView;
- view.setImageBitmap(b);
-
- mBitmap = b;
-
- final Drawable drawable = view.getDrawable();
- drawable.setFilterBitmap(true);
- drawable.setDither(true);
- view.postInvalidate();
+ // This should always be the case, but check anyways
+ final ImageView view = mImageView;
+ if (view != null) {
+ view.setImageBitmap(b);
+
+ mBitmap = b;
+
+ final Drawable drawable = view.getDrawable();
+ drawable.setFilterBitmap(true);
+ drawable.setDither(true);
+
+ view.postInvalidate();
+ }
mLoader = null;
} else {
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index f9d087d..0a3f915 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -109,6 +109,7 @@
private Drawable mBackground;
private float mBackgroundAlpha = 0;
private float mOverScrollMaxBackgroundAlpha = 0.0f;
+ private int mOverScrollPageIndex = -1;
private final WallpaperManager mWallpaperManager;
@@ -268,9 +269,9 @@
@Override
protected int getScrollMode() {
if (LauncherApplication.isScreenXLarge()) {
- return SmoothPagedView.QUINTIC_MODE;
+ return SmoothPagedView.X_LARGE_MODE;
} else {
- return SmoothPagedView.OVERSHOOT_MODE;
+ return SmoothPagedView.DEFAULT_MODE;
}
}
@@ -516,6 +517,7 @@
mAnimOnPageEndMoving = null;
}
mOverScrollMaxBackgroundAlpha = 0.0f;
+ mOverScrollPageIndex = -1;
mPageMoving = false;
}
@@ -653,7 +655,7 @@
}
float overScrollBackgroundAlphaInterpolator(float r) {
- float threshold = 0.1f;
+ float threshold = 0.08f;
if (r > mOverScrollMaxBackgroundAlpha) {
mOverScrollMaxBackgroundAlpha = r;
@@ -664,23 +666,6 @@
return Math.min(r / threshold, 1.0f);
}
- protected void overScroll(float amount) {
- final int lastChildIndex = getChildCount() - 1;
-
- CellLayout cl;
- if (amount < 0) {
- cl = (CellLayout) getChildAt(0);
- } else {
- cl = (CellLayout) getChildAt(lastChildIndex);
- }
-
- final int totalDistance = cl.getMeasuredWidth() + mPageSpacing;
- float r = 1.0f * amount / totalDistance;
- float rotation = -WORKSPACE_ROTATION * r;
- cl.setBackgroundAlphaMultiplier(overScrollBackgroundAlphaInterpolator(Math.abs(r)));
- cl.setRotationY(rotation);
- }
-
@Override
protected void screenScrolled(int screenCenter) {
final int halfScreenSize = getMeasuredWidth() / 2;
@@ -696,7 +681,18 @@
scrollProgress = Math.min(scrollProgress, 1.0f);
scrollProgress = Math.max(scrollProgress, -1.0f);
- cl.setBackgroundAlphaMultiplier(backgroundAlphaInterpolator(Math.abs(scrollProgress)));
+ // If the current page (i) is being overscrolled, we use a different
+ // set of rules for setting the background alpha multiplier.
+ if ((mScrollX < 0 && i == 0) || (mScrollX > mMaxScrollX &&
+ i == getChildCount() -1 )) {
+ cl.setBackgroundAlphaMultiplier(
+ overScrollBackgroundAlphaInterpolator(Math.abs(scrollProgress)));
+ mOverScrollPageIndex = i;
+ } else if (mOverScrollPageIndex != i) {
+ cl.setBackgroundAlphaMultiplier(
+ backgroundAlphaInterpolator(Math.abs(scrollProgress)));
+
+ }
float rotation = WORKSPACE_ROTATION * scrollProgress;
float translationX = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight());
@@ -1168,24 +1164,14 @@
updateWhichPagesAcceptDrops(mShrunkenState);
}
- // We call this when we trigger an unshrink by clicking on the CellLayout cl
- public void unshrink(CellLayout clThatWasClicked) {
- int newCurrentPage = mCurrentPage;
- final int screenCount = getChildCount();
- for (int i = 0; i < screenCount; i++) {
- if (getChildAt(i) == clThatWasClicked) {
- newCurrentPage = i;
- }
- }
- unshrink(newCurrentPage);
- }
-
@Override
protected boolean handlePagingClicks() {
return true;
}
- private void unshrink(int newCurrentPage) {
+ // We call this when we trigger an unshrink by clicking on the CellLayout cl
+ public void unshrink(CellLayout clThatWasClicked) {
+ int newCurrentPage = indexOfChild(clThatWasClicked);
if (mIsSmall) {
int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
int delta = newX - mScrollX;
@@ -1360,7 +1346,6 @@
CellLayout current = getCurrentDropLayout();
current.onDragChild(child);
- child.setVisibility(View.GONE);
child.clearFocus();
child.setPressed(false);
@@ -1406,8 +1391,8 @@
// Based on the position of the drag view, find the top left of the original view
int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
- viewX -= getResources().getInteger(R.integer.config_dragViewOffsetX);
- viewY -= getResources().getInteger(R.integer.config_dragViewOffsetY);
+ viewX += getResources().getInteger(R.integer.config_dragViewOffsetX);
+ viewY += getResources().getInteger(R.integer.config_dragViewOffsetY);
// Set its old pos (in the new parent's coordinates); it will be animated
// in animateViewIntoPosition after the next layout pass
@@ -1494,7 +1479,7 @@
// If it's an external drop (e.g. from All Apps), check if it should be accepted
if (source != this) {
// Don't accept the drop if we're not over a screen at time of drop
- if (mDragTargetLayout == null) {
+ if (mDragTargetLayout == null || !mDragTargetLayout.getAcceptsDrops()) {
return false;
}
@@ -1529,7 +1514,13 @@
}
if (source != this) {
- onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
+ if (mIsSmall) {
+ // if we drag and drop to small screens, don't pass the touch x/y coords (when we
+ // enable spring-loaded adding, however, we do want to pass the touch x/y coords)
+ onDropExternal(-1, -1, dragInfo, mDragTargetLayout);
+ } else {
+ onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
+ }
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
CellLayout dropTargetLayout = mDragTargetLayout;
@@ -1936,7 +1927,7 @@
mDragTargetLayout.setHover(false);
}
mDragTargetLayout = layout;
- if (mDragTargetLayout != null) {
+ if (mDragTargetLayout != null && mDragTargetLayout.getAcceptsDrops()) {
mDragTargetLayout.setHover(true);
}
}
@@ -2046,6 +2037,7 @@
PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
// When dragging and dropping from customization tray, we deal with creating
// widgets/shortcuts/folders in a slightly different way
+ // Only set touchXY if you are supporting spring loaded adding of items
int[] touchXY = new int[2];
touchXY[0] = x;
touchXY[1] = y;
@@ -2064,38 +2056,37 @@
}
cellLayout.onDragExit();
cellLayout.animateDrop();
- return;
- }
-
- // This is for other drag/drop cases, like dragging from All Apps
- ItemInfo info = (ItemInfo) dragInfo;
-
- View view = null;
-
- switch (info.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- if (info.container == NO_ID && info instanceof ApplicationInfo) {
- // Came from all apps -- make a copy
- info = new ShortcutInfo((ApplicationInfo) info);
- }
- view = mLauncher.createShortcut(R.layout.application, cellLayout,
- (ShortcutInfo) info);
- break;
- case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
- view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
- cellLayout, (UserFolderInfo) info, mIconCache);
- break;
- default:
- throw new IllegalStateException("Unknown item type: " + info.itemType);
- }
-
- // If the view is null, it has already been added.
- if (view == null) {
- cellLayout.onDragExit();
} else {
- mTargetCell = new int[]{x, y};
- cellLayout.findCellForSpan(mTargetCell, 1, 1);
+ // This is for other drag/drop cases, like dragging from All Apps
+ ItemInfo info = (ItemInfo) dragInfo;
+
+ View view = null;
+
+ switch (info.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ if (info.container == NO_ID && info instanceof ApplicationInfo) {
+ // Came from all apps -- make a copy
+ info = new ShortcutInfo((ApplicationInfo) info);
+ }
+ view = mLauncher.createShortcut(R.layout.application, cellLayout,
+ (ShortcutInfo) info);
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
+ view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
+ cellLayout, (UserFolderInfo) info, mIconCache);
+ break;
+ default:
+ throw new IllegalStateException("Unknown item type: " + info.itemType);
+ }
+
+ mTargetCell = new int[2];
+ if (x != -1 && y != -1) {
+ // when dragging and dropping, just find the closest free spot
+ cellLayout.findNearestVacantArea(x, y, 1, 1, mTargetCell);
+ } else {
+ cellLayout.findCellForSpan(mTargetCell, 1, 1);
+ }
addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
cellLayout.onDropChild(view);
@@ -2176,6 +2167,11 @@
mDragInfo = null;
}
+ @Override
+ public void onDragViewVisible() {
+ ((View) mDragInfo.cell).setVisibility(View.GONE);
+ }
+
public boolean isDropEnabled() {
return true;
}