Merge "Import initial translations for 20 new locales."
diff --git a/proguard.flags b/proguard.flags
index 010a1db..bedc5e7 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -32,6 +32,8 @@
-keep class com.android.launcher2.Workspace {
public float getBackgroundAlpha();
public void setBackgroundAlpha(float);
+ public float getChildrenOutlineAlpha();
+ public void setChildrenOutlineAlpha(float);
}
-keep class com.android.launcher2.AllApps3D$Defines {
diff --git a/res/drawable-xlarge-hdpi/home_press.9.png b/res/drawable-xlarge-hdpi/home_press.9.png
new file mode 100644
index 0000000..4beec62
--- /dev/null
+++ b/res/drawable-xlarge-hdpi/home_press.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_voice_search.png b/res/drawable-xlarge-hdpi/ic_voice_search.png
new file mode 100644
index 0000000..66d14ae
--- /dev/null
+++ b/res/drawable-xlarge-hdpi/ic_voice_search.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/rotate_button_normal.png b/res/drawable-xlarge-hdpi/rotate_button_normal.png
deleted file mode 100644
index 3772018..0000000
--- a/res/drawable-xlarge-hdpi/rotate_button_normal.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/rotate_button_pressed.png b/res/drawable-xlarge-hdpi/rotate_button_pressed.png
deleted file mode 100644
index 7ceb996..0000000
--- a/res/drawable-xlarge-hdpi/rotate_button_pressed.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/textfield_end.9.png b/res/drawable-xlarge-hdpi/textfield_end.9.png
new file mode 100644
index 0000000..be1b2b6
--- /dev/null
+++ b/res/drawable-xlarge-hdpi/textfield_end.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
new file mode 100644
index 0000000..6b5ebe2
--- /dev/null
+++ b/res/drawable-xlarge-hdpi/textfield_start.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/home_press.9.png b/res/drawable-xlarge-mdpi/home_press.9.png
new file mode 100644
index 0000000..ff841c3
--- /dev/null
+++ b/res/drawable-xlarge-mdpi/home_press.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_voice_search.png b/res/drawable-xlarge-mdpi/ic_voice_search.png
new file mode 100644
index 0000000..a2fe874
--- /dev/null
+++ b/res/drawable-xlarge-mdpi/ic_voice_search.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/textfield_end.9.png b/res/drawable-xlarge-mdpi/textfield_end.9.png
new file mode 100644
index 0000000..94706b4
--- /dev/null
+++ b/res/drawable-xlarge-mdpi/textfield_end.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/textfield_start.9.png b/res/drawable-xlarge-mdpi/textfield_start.9.png
new file mode 100644
index 0000000..8cddc34
--- /dev/null
+++ b/res/drawable-xlarge-mdpi/textfield_start.9.png
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/glow_wallpaper_small.png b/res/drawable-xlarge-nodpi/glow_wallpaper_small.png
new file mode 100644
index 0000000..f83fc60
--- /dev/null
+++ b/res/drawable-xlarge-nodpi/glow_wallpaper_small.png
Binary files differ
diff --git a/res/drawable-xlarge/rotate_button.xml b/res/drawable-xlarge/button_bg.xml
similarity index 89%
rename from res/drawable-xlarge/rotate_button.xml
rename to res/drawable-xlarge/button_bg.xml
index c29efa4..9e6e1ff 100644
--- a/res/drawable-xlarge/rotate_button.xml
+++ b/res/drawable-xlarge/button_bg.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true" android:drawable="@drawable/rotate_button_pressed" />
- <item android:drawable="@drawable/rotate_button_normal" />
+ <item android:state_pressed="true" android:drawable="@drawable/home_press" />
+ <item android:drawable="@android:color/transparent" />
</selector>
diff --git a/res/layout-xlarge-land/launcher.xml b/res/layout-xlarge-land/launcher.xml
index 8e6f1fe..7516796 100644
--- a/res/layout-xlarge-land/launcher.xml
+++ b/res/layout-xlarge-land/launcher.xml
@@ -54,16 +54,54 @@
android:layout_height="?android:attr/actionBarSize"
android:layout_gravity="top">
- <ImageView
- android:id="@+id/search_button"
+ <LinearLayout android:id="@+id/search_button_cluster"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="left"
- android:layout_marginLeft="@dimen/toolbar_button_spacing"
+ android:layout_height="48dp"
+ android:gravity="bottom"
+ >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="16dp"
+ android:background="@drawable/textfield_start"
+ android:orientation="horizontal">
+ <!-- Global search icon -->
+ <ImageView
+ android:id="@+id/search_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:paddingTop="12dp"
+ android:src="@drawable/search_button_generic"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickSearchButton"
+ android:focusable="true"
+ android:clickable="true"/>
+ </LinearLayout>
- android:onClick="onClickSearchButton"
- android:focusable="true"
- android:clickable="true"/>
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="@drawable/textfield_end"
+ android:orientation="horizontal">
+ <!-- Voice search icon -->
+ <ImageView
+ android:id="@+id/voice_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:paddingTop="12dp"
+ android:src="@drawable/ic_voice_search"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickVoiceButton"
+ android:focusable="true"
+ android:clickable="true"/>
+ </LinearLayout>
+ </LinearLayout>
<ImageView
android:id="@+id/configure_button"
diff --git a/res/layout-xlarge-port/launcher.xml b/res/layout-xlarge-port/launcher.xml
index a6fff4a..c2ca467 100644
--- a/res/layout-xlarge-port/launcher.xml
+++ b/res/layout-xlarge-port/launcher.xml
@@ -54,16 +54,54 @@
android:layout_height="?android:attr/actionBarSize"
android:layout_gravity="top">
- <ImageView
- android:id="@+id/search_button"
+ <LinearLayout android:id="@+id/search_button_cluster"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="left"
- android:layout_marginLeft="@dimen/toolbar_button_spacing"
+ android:layout_height="48dp"
+ android:gravity="bottom"
+ >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="16dp"
+ android:background="@drawable/textfield_start"
+ android:orientation="horizontal">
+ <!-- Global search icon -->
+ <ImageView
+ android:id="@+id/search_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:paddingTop="12dp"
+ android:src="@drawable/search_button_generic"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickSearchButton"
+ android:focusable="true"
+ android:clickable="true"/>
+ </LinearLayout>
- android:onClick="onClickSearchButton"
- android:focusable="true"
- android:clickable="true"/>
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="@drawable/textfield_end"
+ android:orientation="horizontal">
+ <!-- Voice search icon -->
+ <ImageView
+ android:id="@+id/voice_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:paddingTop="12dp"
+ android:src="@drawable/ic_voice_search"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickVoiceButton"
+ android:focusable="true"
+ android:clickable="true"/>
+ </LinearLayout>
+ </LinearLayout>
<ImageView
android:id="@+id/configure_button"
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index f472600..1f3df5f 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -533,8 +533,6 @@
mDragController.removeDropTarget(this);
endChoiceMode();
-
- mLauncher.getWorkspace().shrinkToBottomHidden();
}
@Override
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index a7293c8..92140b1 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -302,6 +302,8 @@
// End the current choice mode so that we don't carry selections across tabs
endChoiceMode();
+ // Reset the touch item (if we are mid-dragging)
+ mLastTouchedItem = null;
}
@Override
@@ -417,7 +419,7 @@
boolean yMoved = yDiff > touchSlop;
boolean isUpwardMotion = (yDiff / (float) xDiff) > mDragSlopeThreshold;
- if (isUpwardMotion && yMoved) {
+ if (isUpwardMotion && yMoved && mLastTouchedItem != null) {
// Drag if the user moved far enough along the Y axis
beginDragging(mLastTouchedItem);
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 9954f39..55a6176 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -73,6 +73,7 @@
import android.os.SystemProperties;
import android.provider.LiveFolders;
import android.provider.Settings;
+import android.speech.RecognizerIntent;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
@@ -1925,6 +1926,21 @@
}
/**
+ * Event handler for the voice button
+ *
+ * @param v The view that was clicked.
+ */
+ public void onClickVoiceButton(View v) {
+ startVoiceSearch();
+ }
+
+ private void startVoiceSearch() {
+ Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+
+ /**
* Event handler for the "gear" button that appears on the home screen, which
* enters home screen customization mode.
*
@@ -2477,7 +2493,7 @@
* @param hideSeq AnimatorSet in which to put "hide" animations, or null.
*/
private void hideAndShowToolbarButtons(State newState, AnimatorSet showSeq, AnimatorSet hideSeq) {
- final View searchButton = findViewById(R.id.search_button);
+ final View searchButton = findViewById(R.id.search_button_cluster);
final View allAppsButton = findViewById(R.id.all_apps_button);
final View configureButton = findViewById(R.id.configure_button);
@@ -2898,6 +2914,21 @@
if (activityName != null) {
updateButtonWithIconFromExternalActivity(
R.id.search_button, activityName, R.drawable.search_button_generic);
+ } else {
+ findViewById(R.id.search_button).setVisibility(View.GONE);
+ }
+ }
+ }
+
+ private void updateVoiceSearchIcon() {
+ if (LauncherApplication.isScreenXLarge()) {
+ Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+ ComponentName activityName = intent.resolveActivity(getPackageManager());
+ if (activityName != null) {
+ updateButtonWithIconFromExternalActivity(
+ R.id.voice_button, activityName, R.drawable.ic_voice_search);
+ } else {
+ findViewById(R.id.voice_button).setVisibility(View.GONE);
}
}
}
@@ -3249,6 +3280,16 @@
}
/**
+ * Updates the icons on the launcher that are affected by changes to the package list
+ * on the device.
+ */
+ private void updateIconsAffectedByPackageManagerChanges() {
+ updateAppMarketIcon();
+ updateGlobalSearchIcon();
+ updateVoiceSearchIcon();
+ }
+
+ /**
* Add the icons for all apps.
*
* Implementation of the method from LauncherModel.Callbacks.
@@ -3258,8 +3299,7 @@
if (mCustomizePagedView != null) {
mCustomizePagedView.setApps(apps);
}
- updateAppMarketIcon();
- updateGlobalSearchIcon();
+ updateIconsAffectedByPackageManagerChanges();
}
/**
@@ -3274,8 +3314,7 @@
if (mCustomizePagedView != null) {
mCustomizePagedView.addApps(apps);
}
- updateAppMarketIcon();
- updateGlobalSearchIcon();
+ updateIconsAffectedByPackageManagerChanges();
}
/**
@@ -3291,8 +3330,7 @@
if (mCustomizePagedView != null) {
mCustomizePagedView.updateApps(apps);
}
- updateAppMarketIcon();
- updateGlobalSearchIcon();
+ updateIconsAffectedByPackageManagerChanges();
}
/**
@@ -3309,8 +3347,7 @@
if (mCustomizePagedView != null) {
mCustomizePagedView.removeApps(apps);
}
- updateAppMarketIcon();
- updateGlobalSearchIcon();
+ updateIconsAffectedByPackageManagerChanges();
}
/**
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index fb8b7d6..a2ed985 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -27,7 +27,6 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.ActionMode;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -36,10 +35,9 @@
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.Animation;
-import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
+import android.view.animation.Animation.AnimationListener;
import android.widget.Checkable;
-import android.widget.LinearLayout;
import android.widget.Scroller;
import com.android.launcher.R;
@@ -60,6 +58,8 @@
private static final int PAGE_SNAP_ANIMATION_DURATION = 750;
protected static final float NANOTIME_DIV = 1000000000.0f;
+ private static final float OVERSCROLL_DAMP_FACTOR = 0.22f;
+
// the velocity at which a fling gesture will cause us to snap to the next page
protected int mSnapVelocity = 500;
@@ -70,6 +70,7 @@
protected int mCurrentPage;
protected int mNextPage = INVALID_PAGE;
+ protected int mMaxScrollX;
protected Scroller mScroller;
private VelocityTracker mVelocityTracker;
@@ -103,6 +104,8 @@
protected int mCellCountX;
protected int mCellCountY;
protected boolean mCenterPagesVertically;
+ protected boolean mAllowOverScroll = true;
+ protected int mUnboundedScrollX;
protected static final int INVALID_POINTER = -1;
@@ -312,8 +315,28 @@
}
@Override
+ public void scrollBy(int x, int y) {
+ scrollTo(mUnboundedScrollX + x, mScrollY + y);
+ }
+
+ @Override
public void scrollTo(int x, int y) {
- super.scrollTo(x, y);
+ mUnboundedScrollX = x;
+
+ if (x < 0) {
+ super.scrollTo(0, y);
+ if (mAllowOverScroll) {
+ overScroll(x);
+ }
+ } else if (x > mMaxScrollX) {
+ super.scrollTo(mMaxScrollX, y);
+ if (mAllowOverScroll) {
+ overScroll(x - mMaxScrollX);
+ }
+ } else {
+ super.scrollTo(x, y);
+ }
+
mTouchX = x;
mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
}
@@ -395,6 +418,7 @@
heightSize = maxChildHeight + verticalPadding;
}
+ mMaxScrollX = getChildOffset(childCount - 1) - getRelativeChildOffset(childCount - 1);
setMeasuredDimension(widthSize, heightSize);
}
@@ -799,6 +823,16 @@
return false;
}
+ protected void overScroll(float amount) {
+ int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * amount);
+ if (amount < 0) {
+ mScrollX = overScrollAmount;
+ } else {
+ mScrollX = mMaxScrollX + overScrollAmount;
+ }
+ invalidate();
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Skip touch handling if there are no pages to swipe
@@ -834,31 +868,13 @@
final int deltaX = (int) (mLastMotionX - x);
mLastMotionX = x;
- int sx = getScrollX();
- if (deltaX < 0) {
- if (sx > 0) {
- mTouchX += Math.max(-mTouchX, deltaX);
- mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
- if (!mDeferScrollUpdate) {
- scrollBy(Math.max(-sx, deltaX), 0);
- } else {
- // This will trigger a call to computeScroll() on next drawChild() call
- invalidate();
- }
- }
- } else if (deltaX > 0) {
- final int lastChildIndex = getChildCount() - 1;
- final int availableToScroll = getChildOffset(lastChildIndex) -
- getRelativeChildOffset(lastChildIndex) - sx;
- if (availableToScroll > 0) {
- mTouchX += Math.min(availableToScroll, deltaX);
- mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
- if (!mDeferScrollUpdate) {
- scrollBy(Math.min(availableToScroll, deltaX), 0);
- } else {
- // This will trigger a call to computeScroll() on next drawChild() call
- invalidate();
- }
+ if (deltaX != 0) {
+ mTouchX += deltaX;
+ mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+ if (!mDeferScrollUpdate) {
+ scrollBy(deltaX, 0);
+ } else {
+ invalidate();
}
} else {
awakenScrollBars();
@@ -1042,7 +1058,7 @@
whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
- final int sX = getScrollX();
+ final int sX = mUnboundedScrollX;
final int delta = newX - sX;
snapToPage(whichPage, delta, duration);
}
@@ -1063,7 +1079,7 @@
}
if (!mScroller.isFinished()) mScroller.abortAnimation();
- mScroller.startScroll(getScrollX(), 0, delta, 0, duration);
+ mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
// only load some associated pages
loadAssociatedPages(mNextPage);
diff --git a/src/com/android/launcher2/SmoothPagedView.java b/src/com/android/launcher2/SmoothPagedView.java
index 8e729e4..ee8bca2 100644
--- a/src/com/android/launcher2/SmoothPagedView.java
+++ b/src/com/android/launcher2/SmoothPagedView.java
@@ -138,7 +138,7 @@
final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage));
final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
- final int delta = newX - mScrollX;
+ final int delta = newX - mUnboundedScrollX;
int duration;
if (mScrollMode == OVERSHOOT_MODE) {
duration = (screenDelta + 1) * 100;
@@ -180,8 +180,9 @@
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 - mScrollX;
- mScrollX += dx * e;
+
+ 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
@@ -189,5 +190,6 @@
invalidate();
}
}
+
}
}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 169f53f..69be008 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -20,14 +20,13 @@
import java.util.HashSet;
import java.util.List;
-import android.R.integer;
import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.AlertDialog;
import android.app.WallpaperManager;
@@ -92,14 +91,24 @@
private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
private static final float EXTRA_SCALE_FACTOR_2 = 1.10f;
- private static final int BACKGROUND_FADE_OUT_DELAY = 300;
- private static final int BACKGROUND_FADE_OUT_DURATION = 300;
- private static final int BACKGROUND_FADE_IN_DURATION = 100;
+ private static final int CHILDREN_OUTLINE_FADE_OUT_DELAY = 0;
+ private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
+ private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
- // These animators are used to fade the background
+ private static final int BACKGROUND_FADE_OUT_DURATION = 450;
+ private static final int BACKGROUND_FADE_IN_DURATION = 350;
+
+ // These animators are used to fade the children's outlines
+ private ObjectAnimator mChildrenOutlineFadeInAnimation;
+ private ObjectAnimator mChildrenOutlineFadeOutAnimation;
+ private float mChildrenOutlineAlpha = 0;
+
+ // These properties refer to the background protection gradient used for AllApps and Customize
private ObjectAnimator mBackgroundFadeInAnimation;
private ObjectAnimator mBackgroundFadeOutAnimation;
+ private Drawable mBackground;
private float mBackgroundAlpha = 0;
+ private float mOverScrollMaxBackgroundAlpha = 0.0f;
private final WallpaperManager mWallpaperManager;
@@ -236,6 +245,13 @@
mExternalDragOutlinePaint.setAntiAlias(true);
setWillNotDraw(false);
+ try {
+ final Resources res = getResources();
+ mBackground = res.getDrawable(R.drawable.all_apps_bg_gradient);
+ } catch (Resources.NotFoundException e) {
+ // In this case, we will skip drawing background protection
+ }
+
mUnshrinkAnimationListener = new LauncherAnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -499,7 +515,7 @@
mAnimOnPageEndMoving.start();
mAnimOnPageEndMoving = null;
}
-
+ mOverScrollMaxBackgroundAlpha = 0.0f;
mPageMoving = false;
}
@@ -539,33 +555,60 @@
public void showOutlines() {
if (!mIsSmall && !mIsInUnshrinkAnimation) {
- if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
- if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
- mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
- mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
- mBackgroundFadeInAnimation.start();
+ if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
+ if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
+ mChildrenOutlineFadeInAnimation = ObjectAnimator.ofFloat(this, "childrenOutlineAlpha", 1.0f);
+ mChildrenOutlineFadeInAnimation.setDuration(CHILDREN_OUTLINE_FADE_IN_DURATION);
+ mChildrenOutlineFadeInAnimation.start();
}
}
public void hideOutlines() {
if (!mIsSmall && !mIsInUnshrinkAnimation) {
- if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
- if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
- mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
- mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
- mBackgroundFadeOutAnimation.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
- mBackgroundFadeOutAnimation.start();
+ if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
+ if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
+ mChildrenOutlineFadeOutAnimation = ObjectAnimator.ofFloat(this, "childrenOutlineAlpha", 0.0f);
+ mChildrenOutlineFadeOutAnimation.setDuration(CHILDREN_OUTLINE_FADE_OUT_DURATION);
+ mChildrenOutlineFadeOutAnimation.setStartDelay(CHILDREN_OUTLINE_FADE_OUT_DELAY);
+ mChildrenOutlineFadeOutAnimation.start();
}
}
- public void setBackgroundAlpha(float alpha) {
- mBackgroundAlpha = alpha;
+ public void setChildrenOutlineAlpha(float alpha) {
+ mChildrenOutlineAlpha = alpha;
for (int i = 0; i < getChildCount(); i++) {
CellLayout cl = (CellLayout) getChildAt(i);
cl.setBackgroundAlpha(alpha);
}
}
+ public float getChildrenOutlineAlpha() {
+ return mChildrenOutlineAlpha;
+ }
+
+ public void showBackgroundGradient() {
+ if (mBackground == null) return;
+ if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
+ if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
+ mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
+ mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
+ mBackgroundFadeInAnimation.start();
+ }
+
+ public void hideBackgroundGradient() {
+ if (mBackground == null) return;
+ if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
+ if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
+ mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
+ mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
+ mBackgroundFadeOutAnimation.start();
+ }
+
+ public void setBackgroundAlpha(float alpha) {
+ mBackgroundAlpha = alpha;
+ invalidate();
+ }
+
public float getBackgroundAlpha() {
return mBackgroundAlpha;
}
@@ -595,9 +638,51 @@
return (width - mTempFloat2[0]) * (degrees > 0.0f ? 1.0f : -1.0f);
}
+ float backgroundAlphaInterpolator(float r) {
+ float pivotA = 0.1f;
+ float pivotB = 0.4f;
+ if (r < pivotA) {
+ return 0;
+ } else if (r > pivotB) {
+ return 1.0f;
+ } else {
+ return (r - pivotA)/(pivotB - pivotA);
+ }
+ }
+
+ float overScrollBackgroundAlphaInterpolator(float r) {
+ float threshold = 0.1f;
+
+ if (r > mOverScrollMaxBackgroundAlpha) {
+ mOverScrollMaxBackgroundAlpha = r;
+ } else if (r < mOverScrollMaxBackgroundAlpha) {
+ r = mOverScrollMaxBackgroundAlpha;
+ }
+
+ 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;
+
for (int i = 0; i < getChildCount(); i++) {
CellLayout cl = (CellLayout) getChildAt(i);
if (cl != null) {
@@ -609,11 +694,12 @@
scrollProgress = Math.min(scrollProgress, 1.0f);
scrollProgress = Math.max(scrollProgress, -1.0f);
- cl.setBackgroundAlphaMultiplier(Math.abs(scrollProgress));
+ cl.setBackgroundAlphaMultiplier(backgroundAlphaInterpolator(Math.abs(scrollProgress)));
float rotation = WORKSPACE_ROTATION * scrollProgress;
float translationX = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight());
cl.setTranslationX(translationX);
+
cl.setRotationY(rotation);
}
}
@@ -644,6 +730,18 @@
}
@Override
+ protected void onDraw(Canvas canvas) {
+ // Draw the background gradient if necessary
+ if (mBackground != null && mBackgroundAlpha > 0.0f) {
+ mBackground.setAlpha((int) (mBackgroundAlpha * 255));
+ mBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(), getMeasuredHeight());
+ mBackground.draw(canvas);
+ }
+
+ super.onDraw(canvas);
+ }
+
+ @Override
protected void dispatchDraw(Canvas canvas) {
if (mIsSmall || mIsInUnshrinkAnimation) {
// Draw all the workspaces if we're small
@@ -822,6 +920,8 @@
// we use this to shrink the workspace for the all apps view and the customize view
private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
+ showBackgroundGradient();
+
if (mFirstLayout) {
// (mFirstLayout == "first layout has not happened yet")
// if we get a call to shrink() as part of our initialization (for example, if
@@ -1103,6 +1203,8 @@
}
void unshrink(boolean animated) {
+ hideBackgroundGradient();
+
if (mIsSmall) {
mIsSmall = false;
if (mAnimator != null) {
@@ -1372,7 +1474,6 @@
}
});
-
view.setVisibility(View.INVISIBLE);
if (!mScroller.isFinished()) {