Merge "Fixing screen jump when going to spring_loaded mode in rtl" into ub-launcher3-master
diff --git a/src/com/android/launcher3/BaseContainerView.java b/src/com/android/launcher3/BaseContainerView.java
index 4b7b977..c8de9df 100644
--- a/src/com/android/launcher3/BaseContainerView.java
+++ b/src/com/android/launcher3/BaseContainerView.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.widget.LinearLayout;
/**
@@ -26,11 +27,13 @@
*/
public abstract class BaseContainerView extends LinearLayout implements Insettable {
+ private final static String TAG = "BaseContainerView";
+
// The window insets
private Rect mInsets = new Rect();
// The bounds of the search bar. Only the left, top, right are used to inset the
// search bar and the height is determined by the measurement of the layout
- private Rect mSearchBarBounds = new Rect();
+ private Rect mFixedSearchBarBounds = new Rect();
// The bounds of the container
protected Rect mContentBounds = new Rect();
// The padding to apply to the container to achieve the bounds
@@ -66,7 +69,11 @@
* Sets the search bar bounds for this container view to match.
*/
final public void setSearchBarBounds(Rect bounds) {
- mSearchBarBounds.set(bounds);
+ if (LauncherAppState.isDogfoodBuild() && !isValidSearchBarBounds(bounds)) {
+ Log.e(TAG, "Invalid search bar bounds: " + bounds);
+ }
+
+ mFixedSearchBarBounds.set(bounds);
// Post the updates since they can trigger a relayout, and this call can be triggered from
// a layout pass itself.
@@ -83,9 +90,9 @@
*/
protected void updateBackgroundAndPaddings() {
Rect padding;
- Rect searchBarBounds = new Rect(mSearchBarBounds);
- if (mSearchBarBounds.isEmpty()) {
- // Use the normal bounds
+ Rect searchBarBounds = new Rect(mFixedSearchBarBounds);
+ if (!isValidSearchBarBounds(mFixedSearchBarBounds)) {
+ // Use the default bounds
padding = new Rect(mInsets.left + mContainerBoundsInset,
(mHasSearchBar ? 0 : (mInsets.top + mContainerBoundsInset)),
mInsets.right + mContainerBoundsInset,
@@ -99,18 +106,18 @@
} else {
// Use the search bounds, if there is a search bar, the bounds will contain
// the offsets for the insets so we can ignore that
- padding = new Rect(mSearchBarBounds.left,
+ padding = new Rect(mFixedSearchBarBounds.left,
(mHasSearchBar ? 0 : (mInsets.top + mContainerBoundsInset)),
- getMeasuredWidth() - mSearchBarBounds.right,
+ getMeasuredWidth() - mFixedSearchBarBounds.right,
mInsets.bottom + mContainerBoundsInset);
}
- if (!padding.equals(mContentPadding) || !searchBarBounds.equals(mSearchBarBounds)) {
+ if (!padding.equals(mContentPadding) || !searchBarBounds.equals(mFixedSearchBarBounds)) {
mContentPadding.set(padding);
mContentBounds.set(padding.left, padding.top,
getMeasuredWidth() - padding.right,
getMeasuredHeight() - padding.bottom);
- mSearchBarBounds.set(searchBarBounds);
- onUpdateBackgroundAndPaddings(mSearchBarBounds, padding);
+ mFixedSearchBarBounds.set(searchBarBounds);
+ onUpdateBackgroundAndPaddings(mFixedSearchBarBounds, padding);
}
}
@@ -118,4 +125,13 @@
* To be implemented by container views to update themselves when the bounds changes.
*/
protected abstract void onUpdateBackgroundAndPaddings(Rect searchBarBounds, Rect padding);
+
+ /**
+ * Returns whether the search bar bounds we got are considered valid.
+ */
+ private boolean isValidSearchBarBounds(Rect searchBarBounds) {
+ return !searchBarBounds.isEmpty() &&
+ searchBarBounds.right <= getMeasuredWidth() &&
+ searchBarBounds.bottom <= getMeasuredHeight();
+ }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 9b6c5be..21f23b5 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -959,32 +959,22 @@
int centerY = (int) (sTempRect.top + sTempRect.height() * scale / 2);
int centeredLeft = centerX - width / 2;
int centeredTop = centerY - height / 2;
- int currentPage = mLauncher.getWorkspace().getNextPage();
- // In case the workspace is scrolling, we need to use the final scroll to compute
- // the folders bounds.
- mLauncher.getWorkspace().setFinalScrollForPageChange(currentPage);
- // We first fetch the currently visible CellLayoutChildren
- CellLayout currentLayout = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPage);
- ShortcutAndWidgetContainer boundingLayout = currentLayout.getShortcutsAndWidgets();
- Rect bounds = new Rect();
- parent.getDescendantRectRelativeToSelf(boundingLayout, bounds);
- // We reset the workspaces scroll
- mLauncher.getWorkspace().resetFinalScrollForPageChange(currentPage);
- // We need to bound the folder to the currently visible CellLayoutChildren
- int left = Math.min(Math.max(bounds.left, centeredLeft),
- bounds.left + bounds.width() - width);
- int top = Math.min(Math.max(bounds.top, centeredTop),
- bounds.top + bounds.height() - height);
+ // We need to bound the folder to the currently visible workspace area
+ mLauncher.getWorkspace().getPageAreaRelativeToDragLayer(sTempRect);
+ int left = Math.min(Math.max(sTempRect.left, centeredLeft),
+ sTempRect.left + sTempRect.width() - width);
+ int top = Math.min(Math.max(sTempRect.top, centeredTop),
+ sTempRect.top + sTempRect.height() - height);
if (grid.isPhone && (grid.availableWidthPx - width) < grid.iconSizePx) {
// Center the folder if it is full (on phones only)
left = (grid.availableWidthPx - width) / 2;
- } else if (width >= bounds.width()) {
+ } else if (width >= sTempRect.width()) {
// If the folder doesn't fit within the bounds, center it about the desired bounds
- left = bounds.left + (bounds.width() - width) / 2;
+ left = sTempRect.left + (sTempRect.width() - width) / 2;
}
- if (height >= bounds.height()) {
- top = bounds.top + (bounds.height() - height) / 2;
+ if (height >= sTempRect.height()) {
+ top = sTempRect.top + (sTempRect.height() - height) / 2;
}
int folderPivotX = width / 2 + (centeredLeft - left);
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index ff4c93a..17fdeb1 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -123,9 +123,10 @@
allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
if (mLauncher != null) {
- allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
mLauncher.setAllAppsButton(allAppsButton);
+ allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
allAppsButton.setOnClickListener(mLauncher);
+ allAppsButton.setOnLongClickListener(mLauncher);
allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 5768b87..3b10253 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -986,7 +986,7 @@
// view after launching an app, as they may be depending on the UI to be static to
// switch to another app, otherwise, if it was
showAppsView(false /* animated */, false /* resetListToTop */,
- !launchedFromApp /* updatePredictedApps */);
+ !launchedFromApp /* updatePredictedApps */, false /* focusSearchBar */);
} else if (mOnResumeState == State.WIDGETS) {
showWidgetsView(false, false);
}
@@ -2533,12 +2533,17 @@
*/
protected void onClickAllAppsButton(View v) {
if (LOGD) Log.d(TAG, "onClickAllAppsButton");
- if (isAppsViewVisible()) {
- showWorkspace(true);
- } else {
- // Try and refresh the set of predicted apps before we enter launcher
+ if (!isAppsViewVisible()) {
showAppsView(true /* animated */, false /* resetListToTop */,
- true /* updatePredictedApps */);
+ true /* updatePredictedApps */, false /* focusSearchBar */);
+ }
+ }
+
+ protected void onLongClickAllAppsButton(View v) {
+ if (LOGD) Log.d(TAG, "onLongClickAllAppsButton");
+ if (!isAppsViewVisible()) {
+ showAppsView(true /* animated */, false /* resetListToTop */,
+ true /* updatePredictedApps */, true /* focusSearchBar */);
}
}
@@ -3115,6 +3120,11 @@
if (isWorkspaceLocked()) return false;
if (mState != State.WORKSPACE) return false;
+ if (v == mAllAppsButton) {
+ onLongClickAllAppsButton(v);
+ return true;
+ }
+
if (v instanceof Workspace) {
if (!mWorkspace.isInOverviewMode()) {
if (!mWorkspace.isTouchActive()) {
@@ -3297,14 +3307,15 @@
/**
* Shows the apps view.
*/
- void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps) {
+ void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps,
+ boolean focusSearchBar) {
if (resetListToTop) {
mAppsView.scrollToTop();
}
if (updatePredictedApps) {
tryAndUpdatePredictedApps();
}
- showAppsOrWidgets(animated, State.APPS);
+ showAppsOrWidgets(State.APPS, animated, focusSearchBar);
}
/**
@@ -3315,7 +3326,7 @@
if (resetPageToZero) {
mWidgetsView.scrollToTop();
}
- showAppsOrWidgets(animated, State.WIDGETS);
+ showAppsOrWidgets(State.WIDGETS, animated, false);
mWidgetsView.post(new Runnable() {
@Override
@@ -3332,7 +3343,7 @@
*/
// TODO: calling method should use the return value so that when {@code false} is returned
// the workspace transition doesn't fall into invalid state.
- private boolean showAppsOrWidgets(boolean animated, State toState) {
+ private boolean showAppsOrWidgets(State toState, boolean animated, boolean focusSearchBar) {
if (mState != State.WORKSPACE && mState != State.APPS_SPRING_LOADED &&
mState != State.WIDGETS_SPRING_LOADED) {
return false;
@@ -3342,7 +3353,7 @@
}
if (toState == State.APPS) {
- mStateTransitionAnimation.startAnimationToAllApps(mState, animated);
+ mStateTransitionAnimation.startAnimationToAllApps(animated, focusSearchBar);
} else {
mStateTransitionAnimation.startAnimationToWidgets(animated);
}
@@ -3411,7 +3422,7 @@
void exitSpringLoadedDragMode() {
if (mState == State.APPS_SPRING_LOADED) {
showAppsView(true /* animated */, false /* resetListToTop */,
- false /* updatePredictedApps */);
+ false /* updatePredictedApps */, false /* focusSearchBar */);
} else if (mState == State.WIDGETS_SPRING_LOADED) {
showWidgetsView(true, false);
}
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index 3d31d33..f63e0f4 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -91,7 +91,6 @@
*/
static abstract class PrivateTransitionCallbacks {
void onRevealViewVisible(View revealView, View contentView, View allAppsButtonView) {}
- void onAnimationComplete(View revealView, View contentView, View allAppsButtonView) {}
float getMaterialRevealViewFinalAlpha(View revealView) {
return 0;
}
@@ -108,6 +107,7 @@
View allAppsButtonView) {
return null;
}
+ void onTransitionComplete() {}
}
public static final String TAG = "LauncherStateTransitionAnimation";
@@ -128,8 +128,12 @@
/**
* Starts an animation to the apps view.
+ *
+ * @param startSearchAfterTransition Immediately starts app search after the transition to
+ * All Apps is completed.
*/
- public void startAnimationToAllApps(final Launcher.State fromState, final boolean animated) {
+ public void startAnimationToAllApps(final boolean animated,
+ final boolean startSearchAfterTransition) {
final AllAppsContainerView toView = mLauncher.getAppsView();
PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
private int[] mAllAppsToPanelDelta;
@@ -171,10 +175,17 @@
}
};
}
+ @Override
+ void onTransitionComplete() {
+ if (startSearchAfterTransition) {
+ toView.startAppsSearch();
+ }
+ }
};
// Only animate the search bar if animating from spring loaded mode back to all apps
startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, toView, toView.getContentView(),
- toView.getRevealView(), toView.getSearchBarView(), animated, true, cb);
+ toView.getRevealView(), toView.getSearchBarView(), animated,
+ true /* hideSearchBar */, cb);
}
/**
@@ -345,7 +356,6 @@
// Hide the reveal view
revealView.setVisibility(View.INVISIBLE);
- pCb.onAnimationComplete(revealView, contentView, allAppsButtonView);
// Disable all necessary layers
for (View v : layerViews.keySet()) {
@@ -360,6 +370,7 @@
// This can hold unnecessary references to views.
mStateAnimation = null;
+ pCb.onTransitionComplete();
}
});
@@ -425,6 +436,7 @@
dispatchOnLauncherTransitionPrepare(toView, animated, false);
dispatchOnLauncherTransitionStart(toView, animated, false);
dispatchOnLauncherTransitionEnd(toView, animated, false);
+ pCb.onTransitionComplete();
}
}
@@ -678,9 +690,6 @@
onCompleteRunnable.run();
}
- // Animation complete callback
- pCb.onAnimationComplete(revealView, contentView, allAppsButtonView);
-
// Disable all necessary layers
for (View v : layerViews.keySet()) {
if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
@@ -700,6 +709,7 @@
// This can hold unnecessary references to views.
mStateAnimation = null;
+ pCb.onTransitionComplete();
}
});
@@ -735,6 +745,7 @@
dispatchOnLauncherTransitionPrepare(toView, animated, true);
dispatchOnLauncherTransitionStart(toView, animated, true);
dispatchOnLauncherTransitionEnd(toView, animated, true);
+ pCb.onTransitionComplete();
// Run any queued runnables
if (onCompleteRunnable != null) {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 54450f0..c9bbe0a 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -885,11 +885,6 @@
}
}
- if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < childCount) {
- updateCurrentPageScroll();
- mFirstLayout = false;
- }
-
final LayoutTransition transition = getLayoutTransition();
// If the transition is running defer updating max scroll, as some empty pages could
// still be present, and a max scroll change could cause sudden jumps in scroll.
@@ -914,6 +909,11 @@
updateMaxScrollX();
}
+ if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < childCount) {
+ updateCurrentPageScroll();
+ mFirstLayout = false;
+ }
+
if (mScroller.isFinished() && mChildCountOnLastLayout != childCount) {
if (mRestorePage != INVALID_RESTORE_PAGE) {
setCurrentPage(mRestorePage);
@@ -1147,7 +1147,7 @@
if (!mEdgeGlowRight.isFinished()) {
final int restoreCount = canvas.save();
Rect display = mViewport;
- canvas.translate(display.left + mPageScrolls[getChildCount() - 1], display.top);
+ canvas.translate(display.left + mPageScrolls[mIsRtl ? 0 : (getPageCount() - 1)], display.top);
canvas.rotate(90);
getEdgeVerticalPostion(sTmpIntPoint);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index afaecff..6e8e7b3 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -241,11 +241,6 @@
private SparseArray<Parcelable> mSavedStates;
private final ArrayList<Integer> mRestoredPages = new ArrayList<Integer>();
- // These variables are used for storing the initial and final values during workspace animations
- private int mSavedScrollX;
- private float mSavedRotationY;
- private float mSavedTranslationX;
-
private float mCurrentScale;
private float mTransitionProgress;
@@ -2770,26 +2765,26 @@
}
}
- public void setFinalScrollForPageChange(int pageIndex) {
- CellLayout cl = (CellLayout) getChildAt(pageIndex);
- if (cl != null) {
- mSavedScrollX = getScrollX();
- mSavedTranslationX = cl.getTranslationX();
- mSavedRotationY = cl.getRotationY();
- final int newX = getScrollForPage(pageIndex);
- setScrollX(newX);
- cl.setTranslationX(0f);
- cl.setRotationY(0f);
+ /**
+ * Computes the area relative to dragLayer which is used to display a page.
+ */
+ public void getPageAreaRelativeToDragLayer(Rect outArea) {
+ CellLayout child = (CellLayout) getChildAt(getNextPage());
+ if (child == null) {
+ return;
}
- }
+ ShortcutAndWidgetContainer boundingLayout = child.getShortcutsAndWidgets();
- public void resetFinalScrollForPageChange(int pageIndex) {
- if (pageIndex >= 0) {
- CellLayout cl = (CellLayout) getChildAt(pageIndex);
- setScrollX(mSavedScrollX);
- cl.setTranslationX(mSavedTranslationX);
- cl.setRotationY(mSavedRotationY);
- }
+ // Use the absolute left instead of the child left, as we want the visible area
+ // irrespective of the visible child. Since the view can only scroll horizontally, the
+ // top position is not affected.
+ mTempXY[0] = getViewportOffsetX() + getPaddingLeft() + boundingLayout.getLeft();
+ mTempXY[1] = child.getTop() + boundingLayout.getTop();
+
+ float scale = mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempXY);
+ outArea.set(mTempXY[0], mTempXY[1],
+ (int) (mTempXY[0] + scale * boundingLayout.getMeasuredWidth()),
+ (int) (mTempXY[1] + scale * boundingLayout.getMeasuredHeight()));
}
public void getViewLocationRelativeToSelf(View v, int[] location) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 3b104e2..32c9012 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -284,6 +284,15 @@
return new DefaultAppSearchController(getContext(), this, mAppsRecyclerView);
}
+ /**
+ * Focuses the search field and begins an app search.
+ */
+ public void startAppsSearch() {
+ if (mSearchBarController != null) {
+ mSearchBarController.focusSearchField();
+ }
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();