Merge branch 'master' into honeycomb-release
diff --git a/res/drawable-xlarge/home_screen_bg_hover.9.png b/res/drawable-xlarge/home_screen_bg_hover.9.png
new file mode 100644
index 0000000..c85bcab
--- /dev/null
+++ b/res/drawable-xlarge/home_screen_bg_hover.9.png
Binary files differ
diff --git a/res/values-xlarge-land/dimens.xml b/res/values-xlarge-land/dimens.xml
new file mode 100644
index 0000000..d1140c0
--- /dev/null
+++ b/res/values-xlarge-land/dimens.xml
@@ -0,0 +1,21 @@
+<?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>
+ <!-- the area at the edge of the screen that makes the workspace go left
+ or right while you're dragging. -->
+ <dimen name="scroll_zone">160dip</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-xlarge/config.xml b/res/values-xlarge/config.xml
index c7c68e2..73e7146 100644
--- a/res/values-xlarge/config.xml
+++ b/res/values-xlarge/config.xml
@@ -27,8 +27,6 @@
<integer name="config_toolbarButtonFadeInTime">350</integer>
<integer name="config_toolbarButtonFadeOutTime">350</integer>
- <integer name="config_crosshairsFadeInTime">600</integer>
-
<!-- When dragging items on the workspace, how much bigger (in pixels) the dragged view
should be, as compared to the original view. If 0, it will not be scaled at all.
Should be an even number, for pixel alignment. -->
@@ -38,11 +36,4 @@
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>
-
- <!-- The duration (in ms) of the fade animation on the object outlines, used when
- we are dragging objects around on the home screen. -->
- <integer name="config_dragOutlineFadeTime">900</integer>
-
- <!-- The alpha value at which to show the most recent drop visualization outline. -->
- <integer name="config_dragOutlineMaxAlpha">180</integer>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index db967ea..b6d5037 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -5,6 +5,8 @@
<integer name="config_allAppsBatchSize">0</integer>
<bool name="config_hardwareAccelerated">false</bool>
+ <integer name="config_crosshairsFadeInTime">600</integer>
+
<!-- When dragging an item on the workspace, how much bigger (in pixels) the dragged view
should be, as compared to the original view. If 0, it will not be scaled at all.
Should be an even number, for pixel alignment. -->
@@ -15,4 +17,11 @@
Setting to 1/2 of config_dragViewExtraPixels keeps it centered on its old position. -->
<integer name="config_dragViewOffsetX">20</integer>
<integer name="config_dragViewOffsetY">20</integer>
+
+ <!-- The duration (in ms) of the fade animation on the object outlines, used when
+ we are dragging objects around on the home screen. -->
+ <integer name="config_dragOutlineFadeTime">900</integer>
+
+ <!-- The alpha value at which to show the most recent drop visualization outline. -->
+ <integer name="config_dragOutlineMaxAlpha">180</integer>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 59fdfd3..bcb7e9a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -115,6 +115,8 @@
<!-- Title of dialog when user is selecting shortcut to add to homescreen -->
<string name="title_select_shortcut">Select shortcut</string>
+ <!-- Title of dialog when user is selecting an application to add to homescreen -->
+ <string name="title_select_application">Select application</string>
<!-- Title of dialog when user is selecting live folder to add to homescreen -->
<string name="title_select_live_folder">Select folder</string>
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index 3fa6e7c..769526d 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -1068,7 +1068,7 @@
initMesh();
ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(sRS);
String t = "varying vec4 varColor;\n" +
- "varying vec4 varTex0;\n" +
+ "varying vec2 varTex0;\n" +
"void main() {\n" +
// Animation
" float ani = UNI_Position.z;\n" +
@@ -1123,7 +1123,6 @@
" varColor.rgba = vec4(lum, lum, lum, 1.0);\n" +
" varTex0.xy = ATTRIB_position;\n" +
" varTex0.y = 1.0 - varTex0.y;\n" +
- " varTex0.zw = vec2(0.0, 0.0);\n" +
"}\n";
sb.setShader(t);
sb.addConstant(mUniformAlloc.getType());
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 7da6612..d26b2f9 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -41,8 +41,6 @@
import android.view.animation.Interpolator;
import android.view.animation.LayoutAnimationController;
-import java.util.Arrays;
-
public class CellLayout extends ViewGroup implements Dimmable {
static final String TAG = "CellLayout";
@@ -75,12 +73,13 @@
private OnTouchListener mInterceptTouchListener;
private float mBackgroundAlpha;
- private final Rect mBackgroundLayoutRect = new Rect();
private Drawable mBackground;
private Drawable mBackgroundMini;
private Drawable mBackgroundMiniHover;
- // If we're actively dragging something over this screen and it's small, mHover is true
+ private Drawable mBackgroundHover;
+
+ // If we're actively dragging something over this screen, mHover is true
private boolean mHover = false;
private final Point mDragCenter = new Point();
@@ -145,57 +144,59 @@
mWallpaperManager = WallpaperManager.getInstance(context);
- if (LauncherApplication.isScreenXLarge()) {
- final Resources res = getResources();
+ final Resources res = getResources();
+ if (LauncherApplication.isScreenXLarge()) {
mBackgroundMini = res.getDrawable(R.drawable.mini_home_screen_bg);
mBackgroundMini.setFilterBitmap(true);
mBackground = res.getDrawable(R.drawable.home_screen_bg);
mBackground.setFilterBitmap(true);
mBackgroundMiniHover = res.getDrawable(R.drawable.mini_home_screen_bg_hover);
mBackgroundMiniHover.setFilterBitmap(true);
+ mBackgroundHover = res.getDrawable(R.drawable.home_screen_bg_hover);
+ mBackgroundHover.setFilterBitmap(true);
+ }
- // Initialize the data structures used for the drag visualization.
+ // Initialize the data structures used for the drag visualization.
- mDragRectDrawable = res.getDrawable(R.drawable.rounded_rect_green);
- mCrosshairsDrawable = res.getDrawable(R.drawable.gardening_crosshairs);
- Interpolator interp = new DecelerateInterpolator(2.5f); // Quint ease out
+ mDragRectDrawable = res.getDrawable(R.drawable.rounded_rect_green);
+ mCrosshairsDrawable = res.getDrawable(R.drawable.gardening_crosshairs);
+ Interpolator interp = new DecelerateInterpolator(2.5f); // Quint ease out
- // Set up the animation for fading the crosshairs in and out
- int animDuration = res.getInteger(R.integer.config_crosshairsFadeInTime);
- mCrosshairsAnimator = new ValueAnimator<Float>(animDuration);
- mCrosshairsAnimator.addUpdateListener(new AnimatorUpdateListener() {
+ // Set up the animation for fading the crosshairs in and out
+ int animDuration = res.getInteger(R.integer.config_crosshairsFadeInTime);
+ mCrosshairsAnimator = new ValueAnimator<Float>(animDuration);
+ mCrosshairsAnimator.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mCrosshairsVisibility = ((Float) animation.getAnimatedValue()).floatValue();
+ CellLayout.this.invalidate();
+ }
+ });
+ mCrosshairsAnimator.setInterpolator(interp);
+
+ for (int i = 0; i < mDragRects.length; i++) {
+ mDragRects[i] = new Rect();
+ }
+
+ // When dragging things around the home screens, we show a green outline of
+ // where the item will land. The outlines gradually fade out, leaving a trail
+ // behind the drag path.
+ // Set up all the animations that are used to implement this fading.
+ final int duration = res.getInteger(R.integer.config_dragOutlineFadeTime);
+ final int fromAlphaValue = 0;
+ final int toAlphaValue = res.getInteger(R.integer.config_dragOutlineMaxAlpha);
+ for (int i = 0; i < mDragRectAnims.length; i++) {
+ final InterruptibleInOutAnimator anim =
+ new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
+ anim.setInterpolator(interp);
+ final int thisIndex = i;
+ anim.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
- mCrosshairsVisibility = ((Float) animation.getAnimatedValue()).floatValue();
- CellLayout.this.invalidate();
+ mDragRectAlphas[thisIndex] = (Integer) animation.getAnimatedValue();
+ CellLayout.this.invalidate(mDragRects[thisIndex]);
}
});
- mCrosshairsAnimator.setInterpolator(interp);
-
- for (int i = 0; i < mDragRects.length; i++) {
- mDragRects[i] = new Rect();
- }
-
- // When dragging things around the home screens, we show a green outline of
- // where the item will land. The outlines gradually fade out, leaving a trail
- // behind the drag path.
- // Set up all the animations that are used to implement this fading.
- final int duration = res.getInteger(R.integer.config_dragOutlineFadeTime);
- final int fromAlphaValue = 0;
- final int toAlphaValue = res.getInteger(R.integer.config_dragOutlineMaxAlpha);
- for (int i = 0; i < mDragRectAnims.length; i++) {
- final InterruptibleInOutAnimator anim =
- new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
- anim.setInterpolator(interp);
- final int thisIndex = i;
- anim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- mDragRectAlphas[thisIndex] = (Integer) animation.getAnimatedValue();
- CellLayout.this.invalidate(mDragRects[thisIndex]);
- }
- });
- mDragRectAnims[i] = anim;
- }
+ mDragRectAnims[i] = anim;
}
}
@@ -215,27 +216,25 @@
anim.start();
}
+ public void drawChildren(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ }
+
@Override
- public void dispatchDraw(Canvas canvas) {
+ protected void onDraw(Canvas canvas) {
if (mBackgroundAlpha > 0.0f) {
Drawable bg;
- if (mHover && getScaleX() < 0.5f) {
- bg = mBackgroundMiniHover;
- } else if (getScaleX() < 0.5f) {
- bg = mBackgroundMini;
+ if (getScaleX() < 0.5f) {
+ bg = mHover ? mBackgroundMiniHover : mBackgroundMini;
} else {
- bg = mBackground;
+ bg = mHover ? mBackgroundHover : mBackground;
}
if (bg != null) {
bg.setAlpha((int) (mBackgroundAlpha * 255));
bg.draw(canvas);
}
}
- super.dispatchDraw(canvas);
- }
- @Override
- protected void onDraw(Canvas canvas) {
if (mCrosshairsVisibility > 0.0f) {
final int countX = mCountX;
final int countY = mCountY;
@@ -641,15 +640,17 @@
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
- mBackgroundLayoutRect.set(0, 0, w, h);
if (mBackground != null) {
- mBackground.setBounds(mBackgroundLayoutRect);
+ mBackground.setBounds(0, 0, w, h);
+ }
+ if (mBackgroundHover != null) {
+ mBackgroundHover.setBounds(0, 0, w, h);
}
if (mBackgroundMiniHover != null) {
- mBackgroundMiniHover.setBounds(mBackgroundLayoutRect);
+ mBackgroundMiniHover.setBounds(0, 0, w, h);
}
if (mBackgroundMini != null) {
- mBackgroundMini.setBounds(mBackgroundLayoutRect);
+ mBackgroundMini.setBounds(0, 0, w, h);
}
}
@@ -1016,7 +1017,6 @@
mDragCell[1] = -1;
setHover(false);
- invalidate();
// Fade out the drag indicators
if (mCrosshairsAnimator != null) {
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index d544340..68dfb35 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -56,8 +56,8 @@
private static final int SCROLL_OUTSIDE_ZONE = 0;
private static final int SCROLL_WAITING_IN_ZONE = 1;
- private static final int SCROLL_LEFT = 0;
- private static final int SCROLL_RIGHT = 1;
+ static final int SCROLL_LEFT = 0;
+ static final int SCROLL_RIGHT = 1;
private Context mContext;
private Handler mHandler;
@@ -156,6 +156,10 @@
mScrollZone = context.getResources().getDimensionPixelSize(R.dimen.scroll_zone);
}
+ public boolean dragging() {
+ return mDragging;
+ }
+
/**
* Starts a drag.
*
@@ -487,18 +491,21 @@
mScrollState = SCROLL_WAITING_IN_ZONE;
mScrollRunnable.setDirection(SCROLL_LEFT);
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
+ mDragScroller.onEnterScrollArea(SCROLL_LEFT);
}
} else if (!inDeleteRegion && x > mScrollView.getWidth() - mScrollZone) {
if (mScrollState == SCROLL_OUTSIDE_ZONE) {
mScrollState = SCROLL_WAITING_IN_ZONE;
mScrollRunnable.setDirection(SCROLL_RIGHT);
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
+ mDragScroller.onEnterScrollArea(SCROLL_RIGHT);
}
} else {
if (mScrollState == SCROLL_WAITING_IN_ZONE) {
mScrollState = SCROLL_OUTSIDE_ZONE;
mScrollRunnable.setDirection(SCROLL_RIGHT);
mHandler.removeCallbacks(mScrollRunnable);
+ mDragScroller.onExitScrollArea();
}
}
}
diff --git a/src/com/android/launcher2/DragScroller.java b/src/com/android/launcher2/DragScroller.java
index c3c251c..6af9c30 100644
--- a/src/com/android/launcher2/DragScroller.java
+++ b/src/com/android/launcher2/DragScroller.java
@@ -23,4 +23,16 @@
public interface DragScroller {
void scrollLeft();
void scrollRight();
+
+ /**
+ * The touch point has entered the scroll area; a scroll is imminent.
+ *
+ * @param direction The scroll direction
+ */
+ void onEnterScrollArea(int direction);
+
+ /**
+ * The touch point has left the scroll area.
+ */
+ void onExitScrollArea();
}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 85088f8..f81a9bf 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -175,6 +175,8 @@
/** The different states that Launcher can be in. */
private enum State { WORKSPACE, ALL_APPS, CUSTOMIZE, OVERVIEW };
+ private State mState = State.WORKSPACE;
+ private AnimatorSet mStateAnimation;
static final int APPWIDGET_HOST_ID = 1024;
@@ -239,7 +241,6 @@
private CharSequence[] mHotseatLabels = null;
private Intent mAppMarketIntent = null;
- private Intent mGlobalSearchIntent = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -931,21 +932,21 @@
@SuppressWarnings({"UnusedDeclaration"})
public void previousScreen(View v) {
- if (!isAllAppsVisible()) {
+ if (mState != State.ALL_APPS) {
mWorkspace.scrollLeft();
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void nextScreen(View v) {
- if (!isAllAppsVisible()) {
+ if (mState != State.ALL_APPS) {
mWorkspace.scrollRight();
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void launchHotSeat(View v) {
- if (isAllAppsVisible()) return;
+ if (mState == State.ALL_APPS) return;
int index = -1;
if (v.getId() == R.id.hotseat_left) {
@@ -1173,8 +1174,6 @@
boolean alreadyOnHome = ((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
!= Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
- boolean allAppsVisible = isAllAppsVisible();
- boolean customizationDrawerVisible = isCustomizationDrawerVisible();
// in all these cases, only animate if we're already on home
if (LauncherApplication.isScreenXLarge()) {
@@ -1182,11 +1181,10 @@
}
if (!mWorkspace.isDefaultPageShowing()) {
// on the phone, we don't animate the change to the workspace if all apps is visible
- mWorkspace.moveToDefaultScreen(
- alreadyOnHome && (LauncherApplication.isScreenXLarge() || !allAppsVisible));
+ mWorkspace.moveToDefaultScreen(alreadyOnHome &&
+ (LauncherApplication.isScreenXLarge() || mState != State.ALL_APPS));
}
- closeAllApps(alreadyOnHome && allAppsVisible);
- hideCustomizationDrawer(alreadyOnHome);
+ showWorkspace(alreadyOnHome);
final View v = getWindow().peekDecorView();
if (v != null && v.getWindowToken() != null) {
@@ -1228,7 +1226,7 @@
}
// TODO should not do this if the drawer is currently closing.
- if (isAllAppsVisible()) {
+ if (mState == State.ALL_APPS) {
outState.putBoolean(RUNTIME_STATE_ALL_APPS_FOLDER, true);
}
@@ -1290,7 +1288,7 @@
public void startSearch(String initialQuery, boolean selectInitialQuery,
Bundle appSearchData, boolean globalSearch) {
- closeAllApps(true);
+ showWorkspace(true);
if (initialQuery == null) {
// Use any text typed in the launcher as the initial query
@@ -1408,11 +1406,11 @@
private void addItems() {
if (LauncherApplication.isScreenXLarge()) {
// Animate the widget chooser up from the bottom of the screen
- if (!isCustomizationDrawerVisible()) {
+ if (mState != State.CUSTOMIZE) {
showCustomizationDrawer(true);
}
} else {
- closeAllApps(true);
+ showWorkspace(true);
showAddDialog(-1, -1);
}
}
@@ -1485,6 +1483,7 @@
Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
+ pickIntent.putExtra(Intent.EXTRA_TITLE, getText(R.string.title_select_application));
startActivityForResultSafely(pickIntent, REQUEST_PICK_APPLICATION);
} else {
startActivityForResultSafely(intent, REQUEST_CREATE_SHORTCUT);
@@ -1614,7 +1613,7 @@
}
private void startWallpaper() {
- closeAllApps(true);
+ showWorkspace(true);
final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
Intent chooser = Intent.createChooser(pickWallpaper,
getText(R.string.chooser_wallpaper));
@@ -1667,10 +1666,8 @@
@Override
public void onBackPressed() {
- if (isAllAppsVisible()) {
- closeAllApps(true);
- } else if (isCustomizationDrawerVisible()) {
- hideCustomizationDrawer(true);
+ if (mState == State.ALL_APPS || mState == State.CUSTOMIZE) {
+ showWorkspace(true);
} else {
closeFolder();
}
@@ -1736,8 +1733,8 @@
} else if (tag instanceof FolderInfo) {
handleFolderClick((FolderInfo) tag);
} else if (v == mHandleView) {
- if (isAllAppsVisible()) {
- closeAllApps(true);
+ if (mState == State.ALL_APPS) {
+ showWorkspace(true);
} else {
showAllApps(true);
}
@@ -1746,8 +1743,8 @@
public boolean onTouch(View v, MotionEvent event) {
// this is an intercepted event being forwarded from mWorkspace;
- // clicking anywhere on the workspace causes the drawer to slide down
- hideCustomizationDrawer(true);
+ // clicking anywhere on the workspace causes the customization drawer to slide down
+ showWorkspace(true);
return false;
}
@@ -1757,13 +1754,7 @@
* @param v The view that was clicked.
*/
public void onClickSearchButton(View v) {
- if (mGlobalSearchIntent != null) {
- View b = findViewById(R.id.search_button);
- mGlobalSearchIntent.setSourceBounds(
- new Rect(b.getLeft(), b.getTop(), b.getRight(), b.getBottom()));
- startActivitySafely(mGlobalSearchIntent, "global search");
- }
-
+ startSearch(null, false, null, true);
}
/**
@@ -1899,21 +1890,21 @@
public boolean onLongClick(View v) {
switch (v.getId()) {
case R.id.previous_screen:
- if (!isAllAppsVisible()) {
+ if (mState != State.ALL_APPS) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
showPreviews(v);
}
return true;
case R.id.next_screen:
- if (!isAllAppsVisible()) {
+ if (mState != State.ALL_APPS) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
showPreviews(v);
}
return true;
case R.id.all_apps_button:
- if (!isAllAppsVisible()) {
+ if (mState != State.ALL_APPS) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
showPreviews(v);
@@ -2035,7 +2026,7 @@
final Canvas c = new Canvas(bitmap);
c.scale(scale, scale);
c.translate(-cell.getLeftPadding(), -cell.getTopPadding());
- cell.dispatchDraw(c);
+ cell.drawChildren(c);
image.setBackgroundDrawable(resources.getDrawable(R.drawable.preview_background));
image.setImageBitmap(bitmap);
@@ -2245,7 +2236,7 @@
// Now a part of LauncherModel.Callbacks. Used to reorder loading steps.
public boolean isAllAppsVisible() {
- return mAllAppsGrid != null && mAllAppsGrid.isVisible();
+ return mState == State.ALL_APPS;
}
// AllAppsView.Watcher
@@ -2407,14 +2398,15 @@
// toView should appear right at the end of the workspace shrink animation
final int startDelay = res.getInteger(R.integer.config_workspaceShrinkTime) - duration;
- AnimatorSet s = new AnimatorSet();
- s.playTogether(scaleAnim, toolbarHideAnim);
- s.play(scaleAnim).after(startDelay);
+ if (mStateAnimation != null) mStateAnimation.cancel();
+ mStateAnimation = new AnimatorSet();
+ mStateAnimation.playTogether(scaleAnim, toolbarHideAnim);
+ mStateAnimation.play(scaleAnim).after(startDelay);
// Show the new toolbar buttons just as the main animation is ending
final int fadeInTime = res.getInteger(R.integer.config_toolbarButtonFadeInTime);
- s.play(toolbarShowAnim).after(duration + startDelay - fadeInTime);
- s.start();
+ mStateAnimation.play(toolbarShowAnim).after(duration + startDelay - fadeInTime);
+ mStateAnimation.start();
} else {
toView.setTranslationX(0.0f);
toView.setTranslationY(0.0f);
@@ -2446,12 +2438,13 @@
mWorkspace.unshrink(animated);
if (animated) {
- AnimatorSet s = new AnimatorSet();
+ if (mStateAnimation != null) mStateAnimation.cancel();
+ mStateAnimation = new AnimatorSet();
ValueAnimator scaleAnim = new ObjectAnimator(duration, fromView,
new PropertyValuesHolder<Float>("scaleX", scaleFactor),
new PropertyValuesHolder<Float>("scaleY", scaleFactor));
scaleAnim.setInterpolator(new AccelerateInterpolator());
- s.addListener(new AnimatorListenerAdapter() {
+ mStateAnimation.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
fromView.setVisibility(View.GONE);
fromView.setScaleX(1.0f);
@@ -2463,13 +2456,13 @@
AnimatorSet toolbarShowAnim = new AnimatorSet();
hideAndShowToolbarButtons(State.WORKSPACE, toolbarShowAnim, toolbarHideAnim);
- s.playTogether(scaleAnim, toolbarHideAnim);
+ mStateAnimation.playTogether(scaleAnim, toolbarHideAnim);
// Show the new toolbar buttons at the very end of the whole animation
final int fadeInTime = res.getInteger(R.integer.config_toolbarButtonFadeInTime);
final int unshrinkTime = res.getInteger(R.integer.config_workspaceUnshrinkTime);
- s.play(toolbarShowAnim).after(unshrinkTime - fadeInTime);
- s.start();
+ mStateAnimation.play(toolbarShowAnim).after(unshrinkTime - fadeInTime);
+ mStateAnimation.start();
} else {
fromView.setVisibility(View.GONE);
hideAndShowToolbarButtons(State.WORKSPACE, null, null);
@@ -2508,8 +2501,9 @@
}
if (animated) {
- AnimatorSet s = new AnimatorSet();
- s.addListener(new AnimatorListenerAdapter() {
+ if (mStateAnimation != null) mStateAnimation.cancel();
+ mStateAnimation = new AnimatorSet();
+ mStateAnimation.addListener(new AnimatorListenerAdapter() {
public void onAnimationStart(Animator animation) {
toView.setVisibility(View.VISIBLE);
toView.setY(toViewStartY);
@@ -2523,15 +2517,15 @@
AnimatorSet toolbarShowAnim = new AnimatorSet();
hideAndShowToolbarButtons(toState, toolbarShowAnim, toolbarHideAnim);
- s.playTogether(
+ mStateAnimation.playTogether(
toolbarHideAnim,
new ObjectAnimator(duration, fromView, "y", fromViewStartY, fromViewEndY),
new ObjectAnimator(duration, toView, "y", toViewStartY, toViewEndY));
// Show the new toolbar buttons just as the main animation is ending
final int fadeInTime = res.getInteger(R.integer.config_toolbarButtonFadeInTime);
- s.play(toolbarShowAnim).after(duration - fadeInTime);
- s.start();
+ mStateAnimation.play(toolbarShowAnim).after(duration - fadeInTime);
+ mStateAnimation.start();
} else {
fromView.setY(fromViewEndY);
fromView.setVisibility(View.GONE);
@@ -2542,11 +2536,11 @@
}
void showAllApps(boolean animated) {
- if (mAllAppsGrid.isVisible())
+ if (mState == State.ALL_APPS)
return;
if (LauncherApplication.isScreenXLarge()) {
- if (isCustomizationDrawerVisible()) {
+ if (mState == State.CUSTOMIZE) {
cameraPan(State.CUSTOMIZE, State.ALL_APPS, animated);
} else {
cameraZoomOut(State.ALL_APPS, animated);
@@ -2560,6 +2554,28 @@
// TODO: fade these two too
mDeleteZone.setVisibility(View.GONE);
+ // Change the state *after* we've called all the transition code
+ mState = State.ALL_APPS;
+ }
+
+
+ void showWorkspace(boolean animated) {
+ showWorkspace(animated, null);
+ }
+
+ void showWorkspace(boolean animated, CellLayout layout) {
+ if (layout != null && animated) {
+ mWorkspace.unshrink(layout);
+ } else {
+ mWorkspace.unshrink(animated);
+ }
+ if (mState == State.ALL_APPS) {
+ closeAllApps(animated);
+ } else if (mState == State.CUSTOMIZE) {
+ hideCustomizationDrawer(animated);
+ }
+ // Change the state *after* we've called all the transition code
+ mState = State.WORKSPACE;
}
/**
@@ -2602,7 +2618,7 @@
* - From another workspace
*/
void closeAllApps(boolean animated) {
- if (mAllAppsGrid.isVisible()) {
+ if (mState == State.ALL_APPS) {
mWorkspace.setVisibility(View.VISIBLE);
if (LauncherApplication.isScreenXLarge()) {
cameraZoomIn(State.ALL_APPS, animated);
@@ -2622,23 +2638,20 @@
// TODO
}
- private boolean isCustomizationDrawerVisible() {
- return mHomeCustomizationDrawer != null &&
- mHomeCustomizationDrawer.getVisibility() == View.VISIBLE;
- }
-
// Show the customization drawer (only exists in x-large configuration)
private void showCustomizationDrawer(boolean animated) {
- if (isAllAppsVisible()) {
+ if (mState == State.ALL_APPS) {
cameraPan(State.ALL_APPS, State.CUSTOMIZE, animated);
} else {
cameraZoomOut(State.CUSTOMIZE, animated);
}
+ // Change the state *after* we've called all the transition code
+ mState = State.CUSTOMIZE;
}
// Hide the customization drawer (only exists in x-large configuration)
void hideCustomizationDrawer(boolean animated) {
- if (isCustomizationDrawerVisible()) {
+ if (mState == State.CUSTOMIZE) {
cameraZoomIn(State.CUSTOMIZE, animated);
}
}
@@ -2651,12 +2664,7 @@
if (itemInfo == null) {
// No items are chosen in All Apps or Customize, so just zoom into the workspace
- mWorkspace.unshrink(layout);
- if (isAllAppsVisible()) {
- closeAllApps(true);
- } else if (isCustomizationDrawerVisible()) {
- hideCustomizationDrawer(true);
- }
+ showWorkspace(true, layout);
} else {
// Act as if the chosen item was dropped on the given CellLayout
if (mWorkspace.addExternalItemToScreen(itemInfo, layout)) {
@@ -2668,56 +2676,60 @@
}
}
- /* Core logic for updating market and search button icons. Intent is used to resolve which
- * activity to ask for an icon. Returns intent to launch the activity, or null if it wasn't
- * resolved */
- private Intent updateExternalIcon(int buttonId, Intent intent, int fallbackDrawableId) {
- if (LauncherApplication.isScreenXLarge()) {
- // Find the app market activity by resolving an intent.
- // (If multiple app markets are installed, it will return the ResolverActivity.)
+ private void updateButtonWithIconFromExternalActivity(
+ int buttonId, ComponentName activityName, int fallbackDrawableId) {
+ ImageView button = (ImageView) findViewById(buttonId);
+ Drawable toolbarIcon = null;
+ try {
PackageManager packageManager = getPackageManager();
- ComponentName activityName = intent.resolveActivity(getPackageManager());
+ // Look for the toolbar icon specified in the activity meta-data
+ Bundle metaData = packageManager.getActivityInfo(
+ activityName, PackageManager.GET_META_DATA).metaData;
+ if (metaData != null) {
+ int iconResId = metaData.getInt(TOOLBAR_ICON_METADATA_NAME);
+ if (iconResId != 0) {
+ Resources res = packageManager.getResourcesForActivity(activityName);
+ toolbarIcon = res.getDrawable(iconResId);
+ }
+ }
+ } catch (NameNotFoundException e) {
+ // Do nothing
+ }
+ // If we were unable to find the icon via the meta-data, use a generic one
+ if (toolbarIcon == null) {
+ button.setImageResource(fallbackDrawableId);
+ } else {
+ button.setImageDrawable(toolbarIcon);
+ }
+ }
+
+ private void updateGlobalSearchIcon() {
+ if (LauncherApplication.isScreenXLarge()) {
+ final SearchManager searchManager =
+ (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+ ComponentName activityName = searchManager.getGlobalSearchActivity();
if (activityName != null) {
- ImageView button = (ImageView) findViewById(buttonId);
- Drawable toolbarIcon = null;
- try {
- // Look for the toolbar icon specified in the activity meta-data
- Bundle metaData = packageManager.getActivityInfo(
- activityName, PackageManager.GET_META_DATA).metaData;
- if (metaData != null) {
- int iconResId = metaData.getInt(TOOLBAR_ICON_METADATA_NAME);
- if (iconResId != 0) {
- Resources res = packageManager.getResourcesForActivity(activityName);
- toolbarIcon = res.getDrawable(iconResId);
- }
- }
- } catch (NameNotFoundException e) {
- // Do nothing
- }
- // If we were unable to find the icon via the meta-data, use a generic one
- if (toolbarIcon == null) {
- button.setImageResource(fallbackDrawableId);
- } else {
- button.setImageDrawable(toolbarIcon);
- }
- return intent;
+ updateButtonWithIconFromExternalActivity(
+ R.id.search_button, activityName, R.drawable.search_button_generic);
}
}
- return null;
}
+
/**
* Sets the app market icon (shown when all apps is visible on x-large screens)
*/
private void updateAppMarketIcon() {
- Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
- mAppMarketIntent = updateExternalIcon(
- R.id.market_button, intent, R.drawable.app_market_generic);
- }
-
- private void updateGlobalSearchIcon() {
- Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
- mGlobalSearchIntent = updateExternalIcon(
- R.id.search_button, intent, R.drawable.search_button_generic);
+ if (LauncherApplication.isScreenXLarge()) {
+ Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
+ // Find the app market activity by resolving an intent.
+ // (If multiple app markets are installed, it will return the ResolverActivity.)
+ ComponentName activityName = intent.resolveActivity(getPackageManager());
+ if (activityName != null) {
+ mAppMarketIntent = intent;
+ updateButtonWithIconFromExternalActivity(
+ R.id.market_button, activityName, R.drawable.app_market_generic);
+ }
+ }
}
/**
@@ -2836,8 +2848,7 @@
if (mPaused || "lock".equals(reason)) {
animate = false;
}
- closeAllApps(animate);
- hideCustomizationDrawer(animate);
+ showWorkspace(animate);
}
}
}
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 732bfbd..578bbcc 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -133,6 +133,8 @@
// (SmoothPagedView does this)
protected boolean mDeferScrollUpdate = false;
+ protected boolean mIsPageMoving = false;
+
/**
* Simple cache mechanism for PagedViewIcon outlines.
*/
@@ -159,11 +161,6 @@
void onPageSwitch(View newPage, int newPageIndex);
}
- public interface PageMovingListener {
- void onPageBeginMoving();
- void onPageEndMoving();
- }
-
public PagedView(Context context) {
this(context, null);
}
@@ -245,7 +242,9 @@
if (getChildCount() == 0) return;
mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
- scrollTo(getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage), 0);
+ int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage);
+ scrollTo(newX, 0);
+ mScroller.setFinalX(newX);
invalidate();
notifyPageSwitchListener();
@@ -257,12 +256,22 @@
}
}
- // a method that subclasses can override to add behavior
- protected void pageBeginMoving() {
+ private void pageBeginMoving() {
+ mIsPageMoving = true;
+ onPageBeginMoving();
+ }
+
+ private void pageEndMoving() {
+ onPageEndMoving();
+ mIsPageMoving = false;
}
// a method that subclasses can override to add behavior
- protected void pageEndMoving() {
+ protected void onPageBeginMoving() {
+ }
+
+ // a method that subclasses can override to add behavior
+ protected void onPageEndMoving() {
}
/**
@@ -657,12 +666,9 @@
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
- // Release the drag
- pageEndMoving();
mTouchState = TOUCH_STATE_REST;
mAllowLongPress = false;
mActivePointerId = INVALID_POINTER;
-
break;
case MotionEvent.ACTION_POINTER_UP:
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 47e172f..881fb59 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -33,9 +33,7 @@
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.Camera;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -78,9 +76,6 @@
private static final int BACKGROUND_FADE_OUT_DURATION = 300;
private static final int BACKGROUND_FADE_IN_DURATION = 100;
- static final int SCROLL_RIGHT = 0;
- static final int SCROLL_LEFT = 1;
-
// These animators are used to fade the
private ObjectAnimator<Float> mBackgroundFadeIn;
private ObjectAnimator<Float> mBackgroundFadeOut;
@@ -126,11 +121,14 @@
private Drawable mPreviousIndicator;
private Drawable mNextIndicator;
- // State variable that indicated whether the pages are small (ie when you're
+ // State variable that indicates whether the pages are small (ie when you're
// in all apps or customize mode)
- private boolean mIsSmall;
+ private boolean mIsSmall = false;
+ private boolean mIsInUnshrinkAnimation = false;
private AnimatorListener mUnshrinkAnimationListener;
+ private boolean mInScrollArea = false;
+
/**
* Used to inflate the Workspace from XML.
*
@@ -182,9 +180,11 @@
mIconCache = app.getIconCache();
mUnshrinkAnimationListener = new AnimatorListener() {
- public void onAnimationStart(Animator animation) {}
+ public void onAnimationStart(Animator animation) {
+ mIsInUnshrinkAnimation = true;
+ }
public void onAnimationEnd(Animator animation) {
- mIsSmall = false;
+ mIsInUnshrinkAnimation = false;
}
public void onAnimationCancel(Animator animation) {}
public void onAnimationRepeat(Animator animation) {}
@@ -364,7 +364,7 @@
public boolean onTouch(View v, MotionEvent event) {
// this is an intercepted event being forwarded from a cell layout
- if (mIsSmall) {
+ if (mIsSmall || mIsInUnshrinkAnimation) {
mLauncher.onWorkspaceClick((CellLayout) v);
return true;
}
@@ -373,7 +373,7 @@
@Override
public boolean dispatchUnhandledMove(View focused, int direction) {
- if (mIsSmall) {
+ if (mIsSmall || mIsInUnshrinkAnimation) {
// when the home screens are shrunken, shouldn't allow side-scrolling
return false;
}
@@ -382,14 +382,14 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mIsSmall) {
+ if (mIsSmall || mIsInUnshrinkAnimation) {
// when the home screens are shrunken, shouldn't allow side-scrolling
return false;
}
return super.onInterceptTouchEvent(ev);
}
- protected void pageBeginMoving() {
+ protected void onPageBeginMoving() {
if (mNextPage != INVALID_PAGE) {
// we're snapping to a particular screen
enableChildrenCache(mCurrentPage, mNextPage);
@@ -401,9 +401,13 @@
showOutlines();
}
- protected void pageEndMoving() {
+ protected void onPageEndMoving() {
clearChildrenCache();
- hideOutlines();
+
+ // Hide the outlines, as long as we're not dragging
+ if (!mDragController.dragging()) {
+ hideOutlines();
+ }
}
@Override
@@ -500,11 +504,11 @@
getRelativeChildOffset(mCurrentPage) + halfScreenSize);
float scrollProgress = Math.abs(delta/(pageWidth*1.0f + mPageSpacing));
- int scrollDirection = delta > 0 ? SCROLL_LEFT : SCROLL_RIGHT;
+ boolean scrollRight = (delta <= 0);
float rotation;
- if (scrollDirection == SCROLL_RIGHT) {
+ if (scrollRight) {
rotation = -scrollProgress * WORKSPACE_ROTATION;
cur.setRotationY(rotation);
cur.setScaleX(getScaleXForRotation(rotation));
@@ -561,7 +565,7 @@
@Override
protected void dispatchDraw(Canvas canvas) {
- if (mIsSmall) {
+ if (mIsSmall || mIsInUnshrinkAnimation) {
// Draw all the workspaces if we're small
final int pageCount = getChildCount();
final long drawingTime = getDrawingTime();
@@ -787,10 +791,8 @@
CellLayout cl = (CellLayout) getChildAt(i);
cl.setX(cl.getX() + delta);
}
- snapToPage(newCurrentPage);
- unshrink();
-
setCurrentPage(newCurrentPage);
+ unshrink();
}
}
@@ -800,6 +802,7 @@
void unshrink(boolean animated) {
if (mIsSmall) {
+ mIsSmall = false;
AnimatorSet s = new AnimatorSet();
final int screenCount = getChildCount();
@@ -877,7 +880,7 @@
CellLayout cellLayout;
int originX = x - xOffset;
int originY = y - yOffset;
- if (mIsSmall) {
+ if (mIsSmall || mIsInUnshrinkAnimation) {
cellLayout = findMatchingPageForDragOver(dragView, originX, originY);
if (cellLayout == null) {
// cancel the drag if we're not over a mini-screen at time of drop
@@ -933,12 +936,13 @@
public void onDragEnter(DragSource source, int x, int y, int xOffset,
int yOffset, DragView dragView, Object dragInfo) {
getCurrentDropLayout().onDragEnter(dragView);
+ showOutlines();
}
public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
- if (mIsSmall) {
+ if (mIsSmall || mIsInUnshrinkAnimation) {
// If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
return null;
}
@@ -1050,6 +1054,7 @@
mDragTargetLayout.onDragExit();
}
mDragTargetLayout = bestMatchingScreen;
+ // TODO: Should we be calling mDragTargetLayout.onDragEnter() here?
}
return bestMatchingScreen;
}
@@ -1059,7 +1064,7 @@
CellLayout currentLayout;
int originX = x - xOffset;
int originY = y - yOffset;
- if (mIsSmall) {
+ if (mIsSmall || mIsInUnshrinkAnimation) {
currentLayout = findMatchingPageForDragOver(dragView, originX, originY);
if (currentLayout == null) {
@@ -1103,23 +1108,27 @@
}
}
}
- if (currentLayout != mDragTargetLayout) {
- if (mDragTargetLayout != null) {
- mDragTargetLayout.onDragExit();
- currentLayout.onDragEnter(dragView);
- }
- mDragTargetLayout = currentLayout;
- }
- // only visualize the drop locations for moving icons within the home screen on tablet
- // on phone, we also visualize icons dragged in from All Apps
- if ((!LauncherApplication.isScreenXLarge() || source == this)
- && mDragTargetLayout != null) {
- final View child = (mDragInfo == null) ? null : mDragInfo.cell;
- int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
- int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
- mDragTargetLayout.visualizeDropLocation(
- child, localOriginX, localOriginY, item.spanX, item.spanY);
+ // When touch is inside the scroll area, skip dragOver actions for the current screen
+ if (!mInScrollArea) {
+ if (currentLayout != mDragTargetLayout) {
+ if (mDragTargetLayout != null) {
+ mDragTargetLayout.onDragExit();
+ }
+ currentLayout.onDragEnter(dragView);
+ mDragTargetLayout = currentLayout;
+ }
+
+ // only visualize the drop locations for moving icons within the home screen on tablet
+ // on phone, we also visualize icons dragged in from All Apps
+ if ((!LauncherApplication.isScreenXLarge() || source == this)
+ && mDragTargetLayout != null) {
+ final View child = (mDragInfo == null) ? null : mDragInfo.cell;
+ int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
+ int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
+ mDragTargetLayout.visualizeDropLocation(
+ child, localOriginX, localOriginY, item.spanX, item.spanY);
+ }
}
}
@@ -1129,6 +1138,9 @@
mDragTargetLayout.onDragExit();
mDragTargetLayout = null;
}
+ if (!mIsPageMoving) {
+ hideOutlines();
+ }
}
private void onDropExternal(int x, int y, Object dragInfo,
@@ -1246,7 +1258,7 @@
public boolean acceptDrop(DragSource source, int x, int y,
int xOffset, int yOffset, DragView dragView, Object dragInfo) {
CellLayout layout;
- if (mIsSmall) {
+ if (mIsSmall || mIsInUnshrinkAnimation) {
layout = findMatchingPageForDragOver(dragView, x - xOffset, y - yOffset);
if (layout == null) {
// cancel the drag if we're not over a mini-screen at time of drop
@@ -1330,18 +1342,41 @@
@Override
public void scrollLeft() {
- if (!mIsSmall) {
+ if (!mIsSmall && !mIsInUnshrinkAnimation) {
super.scrollLeft();
}
}
@Override
public void scrollRight() {
- if (!mIsSmall) {
+ if (!mIsSmall && !mIsInUnshrinkAnimation) {
super.scrollRight();
}
}
+ @Override
+ public void onEnterScrollArea(int direction) {
+ mInScrollArea = true;
+ final int screen = getCurrentPage() + ((direction == DragController.SCROLL_LEFT) ? -1 : 1);
+ if (0 <= screen && screen < getChildCount()) {
+ ((CellLayout) getChildAt(screen)).setHover(true);
+ }
+
+ if (mDragTargetLayout != null) {
+ mDragTargetLayout.onDragExit();
+ mDragTargetLayout = null;
+ }
+ }
+
+ @Override
+ public void onExitScrollArea() {
+ mInScrollArea = false;
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ ((CellLayout) getChildAt(i)).setHover(false);
+ }
+ }
+
public Folder getFolderForTag(Object tag) {
final int screenCount = getChildCount();
for (int screen = 0; screen < screenCount; screen++) {
@@ -1525,12 +1560,10 @@
}
void moveToDefaultScreen(boolean animate) {
- if (animate) {
- if (mIsSmall) {
- unshrink(mDefaultPage);
- } else {
- snapToPage(mDefaultPage);
- }
+ if (mIsSmall || mIsInUnshrinkAnimation) {
+ mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
+ } else if (animate) {
+ snapToPage(mDefaultPage);
} else {
setCurrentPage(mDefaultPage);
}