Merge "Tab indicator of work tab should be in orange color" into ub-launcher3-master
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index b59e4ee..60cd0c2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -17,7 +17,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;
@@ -25,8 +24,8 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.anim.AnimationLayerSet;
import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsView;
@@ -54,18 +53,18 @@
}
@Override
- public void setStateWithAnimation(LauncherState toState, AnimationLayerSet layerViews,
- AnimatorSet anim, AnimationConfig config) {
+ public void setStateWithAnimation(LauncherState toState,
+ AnimatorSetBuilder builder, AnimationConfig config) {
ObjectAnimator progressAnim =
mTransitionProgress.animateToValue(toState == LauncherState.OVERVIEW ? 1 : 0);
progressAnim.setDuration(config.duration);
progressAnim.setInterpolator(Interpolators.LINEAR);
- anim.play(progressAnim);
+ builder.play(progressAnim);
ObjectAnimator visibilityAnim = animateVisibility(toState == LauncherState.OVERVIEW);
visibilityAnim.setDuration(config.duration);
visibilityAnim.setInterpolator(Interpolators.LINEAR);
- anim.play(visibilityAnim);
+ builder.play(visibilityAnim);
}
public void setVisibility(boolean isVisible) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java
new file mode 100644
index 0000000..9081865
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+package com.android.launcher3.uioverrides;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.anim.SpringAnimationHandler.Y_DIRECTION;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.support.animation.SpringAnimation;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.SpringAnimationHandler;
+import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.util.TouchController;
+
+import java.util.ArrayList;
+
+/**
+ * Handles vertical touch gesture on the DragLayer
+ */
+public class TwoStepSwipeController extends AnimatorListenerAdapter
+ implements TouchController, SwipeDetector.Listener {
+
+ private static final String TAG = "TwoStepSwipeController";
+
+ private static final float RECATCH_REJECTION_FRACTION = .0875f;
+ private static final int SINGLE_FRAME_MS = 16;
+
+ // Progress after which the transition is assumed to be a success in case user does not fling
+ private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
+
+ private final Launcher mLauncher;
+ private final SwipeDetector mDetector;
+
+ private boolean mNoIntercept;
+ private int mStartContainerType;
+
+ private AnimatorPlaybackController mCurrentAnimation;
+ private LauncherState mToState;
+
+ private float mStartProgress;
+ // Ratio of transition process [0, 1] to drag displacement (px)
+ private float mProgressMultiplier;
+
+ private SpringAnimationHandler[] mSpringHandlers;
+
+ public TwoStepSwipeController(Launcher l) {
+ mLauncher = l;
+ mDetector = new SwipeDetector(l, this, SwipeDetector.VERTICAL);
+ }
+
+ private boolean canInterceptTouch(MotionEvent ev) {
+ if (!mLauncher.isInState(NORMAL) && !mLauncher.isInState(ALL_APPS)) {
+ // Don't listen for the swipe gesture if we are already in some other state.
+ return false;
+ }
+ if (mCurrentAnimation != null) {
+ // If we are already animating from a previous state, we can intercept.
+ return true;
+ }
+ if (mLauncher.isInState(ALL_APPS) && !mLauncher.getAppsView().shouldContainerScroll(ev)) {
+ return false;
+ }
+ if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ if (mCurrentAnimation != null && animation == mCurrentAnimation.getTarget()) {
+ Log.e(TAG, "Who dare cancel the animation when I am in control", new Exception());
+ mDetector.finishedScrolling();
+ mCurrentAnimation = null;
+ }
+ }
+
+ private void initSprings() {
+ AllAppsContainerView appsView = mLauncher.getAppsView();
+
+ SpringAnimationHandler handler = appsView.getSpringAnimationHandler();
+ if (handler == null) {
+ mSpringHandlers = new SpringAnimationHandler[0];
+ return;
+ }
+
+ ArrayList<SpringAnimationHandler> handlers = new ArrayList<>();
+ handlers.add(handler);
+
+ SpringAnimation searchSpring = appsView.getSearchUiManager().getSpringForFling();
+ if (searchSpring != null) {
+ SpringAnimationHandler searchHandler =
+ new SpringAnimationHandler(Y_DIRECTION, handler.getFactory());
+ searchHandler.add(searchSpring, true /* setDefaultValues */);
+ handlers.add(searchHandler);
+ }
+
+ mSpringHandlers = handlers.toArray(new SpringAnimationHandler[handlers.size()]);
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mNoIntercept = !canInterceptTouch(ev);
+ if (mNoIntercept) {
+ return false;
+ }
+
+ // Now figure out which direction scroll events the controller will start
+ // calling the callbacks.
+ final int directionsToDetectScroll;
+ boolean ignoreSlopWhenSettling = false;
+
+ if (mCurrentAnimation != null) {
+ if (mCurrentAnimation.getProgressFraction() > 1 - RECATCH_REJECTION_FRACTION) {
+ directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
+ } else if (mCurrentAnimation.getProgressFraction() < RECATCH_REJECTION_FRACTION ) {
+ directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE;
+ } else {
+ directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
+ ignoreSlopWhenSettling = true;
+ }
+ } else {
+ if (mLauncher.isInState(ALL_APPS)) {
+ directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE;
+ mStartContainerType = ContainerType.ALLAPPS;
+ } else {
+ directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
+ mStartContainerType = mLauncher.getDragLayer().isEventOverHotseat(ev) ?
+ ContainerType.HOTSEAT : ContainerType.WORKSPACE;
+ }
+ }
+
+ mDetector.setDetectableScrollConditions(
+ directionsToDetectScroll, ignoreSlopWhenSettling);
+
+ if (mSpringHandlers == null) {
+ initSprings();
+ }
+ }
+
+ if (mNoIntercept) {
+ return false;
+ }
+
+ onControllerTouchEvent(ev);
+ return mDetector.isDraggingOrSettling();
+ }
+
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ for (SpringAnimationHandler h : mSpringHandlers) {
+ h.addMovement(ev);
+ }
+ return mDetector.onTouchEvent(ev);
+ }
+
+ @Override
+ public void onDragStart(boolean start) {
+ if (mCurrentAnimation == null) {
+ float range = getShiftRange();
+ long maxAccuracy = (long) (2 * range);
+
+ // Build current animation
+ mToState = mLauncher.isInState(ALL_APPS) ? NORMAL : ALL_APPS;
+ mCurrentAnimation = mLauncher.getStateManager()
+ .createAnimationToNewWorkspace(mToState, maxAccuracy);
+ mCurrentAnimation.getTarget().addListener(this);
+ mStartProgress = 0;
+ mProgressMultiplier = (mLauncher.isInState(ALL_APPS) ? 1 : -1) / range;
+ mCurrentAnimation.dispatchOnStart();
+ } else {
+ mCurrentAnimation.pause();
+ mStartProgress = mCurrentAnimation.getProgressFraction();
+ }
+
+ for (SpringAnimationHandler h : mSpringHandlers) {
+ h.skipToEnd();
+ }
+ }
+
+ private float getShiftRange() {
+ return mLauncher.getAllAppsController().getShiftRange();
+ }
+
+ @Override
+ public boolean onDrag(float displacement, float velocity) {
+ float deltaProgress = mProgressMultiplier * displacement;
+ mCurrentAnimation.setPlayFraction(deltaProgress + mStartProgress);
+ return true;
+ }
+
+ @Override
+ public void onDragEnd(float velocity, boolean fling) {
+ final long animationDuration;
+ final int logAction;
+ final LauncherState targetState;
+ final float progress = mCurrentAnimation.getProgressFraction();
+
+ if (fling) {
+ logAction = Touch.FLING;
+ if (velocity < 0) {
+ targetState = ALL_APPS;
+ animationDuration = SwipeDetector.calculateDuration(velocity,
+ mToState == ALL_APPS ? (1 - progress) : progress);
+ } else {
+ targetState = NORMAL;
+ animationDuration = SwipeDetector.calculateDuration(velocity,
+ mToState == ALL_APPS ? progress : (1 - progress));
+ }
+ // snap to top or bottom using the release velocity
+ } else {
+ logAction = Touch.SWIPE;
+ if (progress > SUCCESS_TRANSITION_PROGRESS) {
+ targetState = mToState;
+ animationDuration = SwipeDetector.calculateDuration(velocity, 1 - progress);
+ } else {
+ targetState = mToState == ALL_APPS ? NORMAL : ALL_APPS;
+ animationDuration = SwipeDetector.calculateDuration(velocity, progress);
+ }
+ }
+
+ if (fling && targetState == ALL_APPS) {
+ for (SpringAnimationHandler h : mSpringHandlers) {
+ // The icons are moving upwards, so we go to 0 from 1. (y-axis 1 is below 0.)
+ h.animateToFinalPosition(0 /* pos */, 1 /* startValue */);
+ }
+ }
+
+ mCurrentAnimation.setEndAction(new Runnable() {
+ @Override
+ public void run() {
+ if (targetState == mToState) {
+ // Transition complete. log the action
+ mLauncher.getUserEventDispatcher().logActionOnContainer(logAction,
+ mToState == ALL_APPS ? Direction.UP : Direction.DOWN,
+ mStartContainerType, mLauncher.getWorkspace().getCurrentPage());
+ } else {
+ mLauncher.getStateManager().goToState(
+ mToState == ALL_APPS ? NORMAL : ALL_APPS, false);
+ }
+ mDetector.finishedScrolling();
+ mCurrentAnimation = null;
+ }
+ });
+
+ float nextFrameProgress = Utilities.boundToRange(
+ progress + velocity * SINGLE_FRAME_MS / getShiftRange(), 0f, 1f);
+
+ ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
+ anim.setFloatValues(nextFrameProgress, targetState == mToState ? 1f : 0f);
+ anim.setDuration(animationDuration);
+ anim.setInterpolator(scrollInterpolatorForVelocity(velocity));
+ anim.start();
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index a48a65c..5e280b6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -24,14 +24,13 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.R;
-import com.android.launcher3.VerticalSwipeController;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.widget.WidgetsFullSheet;
public class UiFactory {
public static TouchController[] createTouchControllers(Launcher launcher) {
- return new TouchController[] {new VerticalSwipeController(launcher)};
+ return new TouchController[] {new TwoStepSwipeController(launcher)};
}
public static AccessibilityDelegate newPageIndicatorAccessibilityDelegate() {
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 73ed38a..6750c72 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -48,12 +48,16 @@
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/all_apps_tabs_side_padding"
+ android:layout_marginRight="@dimen/all_apps_tabs_side_padding"
android:layout_alignBottom="@+id/tabs" />
<com.android.launcher3.allapps.PersonalWorkSlidingTabStrip
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="@dimen/all_apps_header_tab_height"
+ android:layout_marginLeft="@dimen/all_apps_tabs_side_padding"
+ android:layout_marginRight="@dimen/all_apps_tabs_side_padding"
android:layout_below="@id/header_content"
android:orientation="horizontal">
<Button
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 294425d..3e34e16 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -132,4 +132,8 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Pessoal"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Trabalho"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil de trabalho"</string>
+ <!-- no translation found for bottom_work_tab_user_education_title (5785851780786322825) -->
+ <skip />
+ <!-- no translation found for bottom_work_tab_user_education_body (5834430249581360068) -->
+ <skip />
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e7f45c2..e22c7c2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -96,6 +96,7 @@
<dimen name="all_apps_prediction_row_divider_height">17dp</dimen>
<dimen name="all_apps_work_profile_tab_footer_top_padding">16dp</dimen>
<dimen name="all_apps_work_profile_tab_footer_bottom_padding">20dp</dimen>
+ <dimen name="all_apps_tabs_side_padding">12dp</dimen>
<!-- Search bar in All Apps -->
<dimen name="all_apps_header_max_elevation">3dp</dimen>
diff --git a/src/com/android/launcher3/BaseRecyclerView.java b/src/com/android/launcher3/BaseRecyclerView.java
index bce0e2e..76c7845 100644
--- a/src/com/android/launcher3/BaseRecyclerView.java
+++ b/src/com/android/launcher3/BaseRecyclerView.java
@@ -17,13 +17,11 @@
package com.android.launcher3;
import android.content.Context;
-import android.graphics.Canvas;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
import com.android.launcher3.views.RecyclerViewFastScroller;
@@ -91,8 +89,10 @@
*/
private boolean handleTouchEvent(MotionEvent ev) {
// Move to mScrollbar's coordinate system.
- int left = getLeft() - mScrollbar.getLeft();
- int top = getTop() - mScrollbar.getTop();
+ // We need to take parent into account (view pager's location)
+ ViewGroup parent = (ViewGroup) getParent();
+ int left = parent.getLeft() + getLeft() - mScrollbar.getLeft();
+ int top = parent.getTop() + getTop() - mScrollbar.getTop() - getScrollBarTop();
ev.offsetLocation(left, top);
try {
return mScrollbar.handleTouchEvent(ev);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a9b1619..0c573ac 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -42,13 +42,11 @@
import android.annotation.TargetApi;
import android.app.ActivityOptions;
import android.app.AlertDialog;
-import android.app.SearchManager;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
-import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.DialogInterface;
@@ -70,8 +68,6 @@
import android.os.StrictMode;
import android.os.UserHandle;
import android.support.annotation.Nullable;
-import android.text.Selection;
-import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
import android.util.Log;
@@ -89,7 +85,6 @@
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.OvershootInterpolator;
-import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import com.android.launcher3.DropTarget.DragObject;
@@ -243,8 +238,6 @@
// that results in widgets being inflated in the wrong orientation.
private int mOrientation;
- private SpannableStringBuilder mDefaultKeySsb = null;
-
@Thunk boolean mWorkspaceLoading = true;
private boolean mPaused = true;
@@ -259,14 +252,13 @@
private ModelWriter mModelWriter;
private IconCache mIconCache;
private LauncherAccessibilityDelegate mAccessibilityDelegate;
- private boolean mHasFocus = false;
private ObjectAnimator mScrimAnimator;
private boolean mShouldFadeInScrim;
private PopupDataProvider mPopupDataProvider;
- private final ArrayList<Integer> mSynchronouslyBoundPages = new ArrayList<>();
+ private int mSynchronouslyBoundPage = PagedView.INVALID_PAGE;
// We only want to get the SharedPreferences once since it does an FS stat each time we get
// it from the context.
@@ -400,8 +392,7 @@
}
// For handling default keys
- mDefaultKeySsb = new SpannableStringBuilder();
- Selection.setSelection(mDefaultKeySsb, 0);
+ setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
// On large interfaces, or on devices that a user has specifically enabled screen rotation,
// we want the screen to auto-rotate based on the current orientation
@@ -851,8 +842,6 @@
mLauncherCallbacks.onResume();
}
- clearTypedText();
-
TraceHelper.endSection("ON_RESUME");
}
@@ -920,72 +909,6 @@
}
}
- @Override
- public Object onRetainNonConfigurationInstance() {
- // Flag the loader to stop early before switching
- if (mModel.isCurrentCallbacks(this)) {
- mModel.stopLoader();
- }
- //TODO(hyunyoungs): stop the widgets loader when there is a rotation.
-
- return Boolean.TRUE;
- }
-
- // We can't hide the IME if it was forced open. So don't bother
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- mHasFocus = hasFocus;
-
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onWindowFocusChanged(hasFocus);
- }
- }
-
- private boolean acceptFilter() {
- final InputMethodManager inputManager = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- return !inputManager.isFullscreenMode();
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- final int uniChar = event.getUnicodeChar();
- final boolean handled = super.onKeyDown(keyCode, event);
- final boolean isKeyNotWhitespace = uniChar > 0 && !Character.isWhitespace(uniChar);
- if (!handled && acceptFilter() && isKeyNotWhitespace) {
- boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
- keyCode, event);
- if (gotKey && mDefaultKeySsb != null && mDefaultKeySsb.length() > 0) {
- // something usable has been typed - start a search
- // the typed text will be retrieved and cleared by
- // showSearchDialog()
- // If there are multiple keystrokes before the search dialog takes focus,
- // onSearchRequested() will be called for every keystroke,
- // but it is idempotent, so it's fine.
- return onSearchRequested();
- }
- }
-
- // Eat the long press event so the keyboard doesn't come up.
- if (keyCode == KeyEvent.KEYCODE_MENU && event.isLongPress()) {
- return true;
- }
-
- return handled;
- }
-
- private String getTypedText() {
- return mDefaultKeySsb.toString();
- }
-
- @Override
- public void clearTypedText() {
- mDefaultKeySsb.clear();
- mDefaultKeySsb.clearSpans();
- Selection.setSelection(mDefaultKeySsb, 0);
- }
-
public boolean isInState(LauncherState state) {
return mStateManager.getState() == state;
}
@@ -1337,7 +1260,7 @@
TraceHelper.beginSection("NEW_INTENT");
super.onNewIntent(intent);
- boolean alreadyOnHome = mHasFocus && ((intent.getFlags() &
+ boolean alreadyOnHome = hasWindowFocus() && ((intent.getFlags() &
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
!= Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
@@ -1393,9 +1316,7 @@
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
- for (int page: mSynchronouslyBoundPages) {
- mWorkspace.restoreInstanceStateForChild(page);
- }
+ mWorkspace.restoreInstanceStateForChild(mSynchronouslyBoundPage);
}
@Override
@@ -1459,7 +1380,6 @@
} catch (NullPointerException ex) {
Log.w(TAG, "problem while stopping AppWidgetHost during Launcher destruction", ex);
}
- mAppWidgetHost = null;
TextKeyListener.getInstance().release();
WallpaperColorInfo.getInstance(this).setOnThemeChangeListener(null);
@@ -1504,11 +1424,6 @@
@Override
public void startSearch(String initialQuery, boolean selectInitialQuery,
Bundle appSearchData, boolean globalSearch) {
-
- if (initialQuery == null) {
- // Use any text typed in the launcher as the initial query
- initialQuery = getTypedText();
- }
if (appSearchData == null) {
appSearchData = new Bundle();
appSearchData.putString("source", "launcher-search");
@@ -1517,69 +1432,13 @@
if (mLauncherCallbacks == null ||
!mLauncherCallbacks.startSearch(initialQuery, selectInitialQuery, appSearchData)) {
// Starting search from the callbacks failed. Start the default global search.
- startGlobalSearch(initialQuery, selectInitialQuery, appSearchData, null);
+ super.startSearch(initialQuery, selectInitialQuery, appSearchData, true);
}
// We need to show the workspace after starting the search
mStateManager.goToState(NORMAL);
}
- /**
- * Starts the global search activity. This code is a copied from SearchManager
- */
- public void startGlobalSearch(String initialQuery,
- boolean selectInitialQuery, Bundle appSearchData, Rect sourceBounds) {
- final SearchManager searchManager =
- (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity();
- if (globalSearchActivity == null) {
- Log.w(TAG, "No global search activity found.");
- return;
- }
- Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setComponent(globalSearchActivity);
- // Make sure that we have a Bundle to put source in
- if (appSearchData == null) {
- appSearchData = new Bundle();
- } else {
- appSearchData = new Bundle(appSearchData);
- }
- // Set source to package name of app that starts global search if not set already.
- if (!appSearchData.containsKey("source")) {
- appSearchData.putString("source", getPackageName());
- }
- intent.putExtra(SearchManager.APP_DATA, appSearchData);
- if (!TextUtils.isEmpty(initialQuery)) {
- intent.putExtra(SearchManager.QUERY, initialQuery);
- }
- if (selectInitialQuery) {
- intent.putExtra(SearchManager.EXTRA_SELECT_QUERY, selectInitialQuery);
- }
- intent.setSourceBounds(sourceBounds);
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException ex) {
- Log.e(TAG, "Global search activity not found: " + globalSearchActivity);
- }
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- if (mLauncherCallbacks != null) {
- return mLauncherCallbacks.onPrepareOptionsMenu(menu);
- }
- return false;
- }
-
- @Override
- public boolean onSearchRequested() {
- startSearch(null, false, null, true);
- // Use a custom animation for launching search
- return true;
- }
-
public boolean isWorkspaceLocked() {
return mWorkspaceLoading || mPendingRequestArgs != null;
}
@@ -2767,7 +2626,7 @@
}
public void onPageBoundSynchronously(int page) {
- mSynchronouslyBoundPages.add(page);
+ mSynchronouslyBoundPage = page;
}
@Override
@@ -2817,11 +2676,7 @@
* Implementation of the method from LauncherModel.Callbacks.
*/
public void finishBindingItems() {
- Runnable r = new Runnable() {
- public void run() {
- finishBindingItems();
- }
- };
+ Runnable r = this::finishBindingItems;
if (waitUntilResume(r)) {
return;
}
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index 928258f..914d9eb 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -48,10 +48,8 @@
void onActivityResult(int requestCode, int resultCode, Intent data);
void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults);
- void onWindowFocusChanged(boolean hasFocus);
void onAttachedToWindow();
void onDetachedFromWindow();
- boolean onPrepareOptionsMenu(Menu menu);
void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args);
void onHomeIntent();
boolean handleBackPressed();
diff --git a/src/com/android/launcher3/LauncherExterns.java b/src/com/android/launcher3/LauncherExterns.java
index 887859c..272bbf6 100644
--- a/src/com/android/launcher3/LauncherExterns.java
+++ b/src/com/android/launcher3/LauncherExterns.java
@@ -24,11 +24,9 @@
*/
public interface LauncherExterns {
- public boolean setLauncherCallbacks(LauncherCallbacks callbacks);
+ boolean setLauncherCallbacks(LauncherCallbacks callbacks);
- public SharedPreferences getSharedPrefs();
+ SharedPreferences getSharedPrefs();
- public void setLauncherOverlay(Launcher.LauncherOverlay overlay);
-
- void clearTypedText();
+ void setLauncherOverlay(Launcher.LauncherOverlay overlay);
}
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 2cad95e..e3768e2 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -25,9 +25,9 @@
import android.os.Looper;
import android.view.View;
-import com.android.launcher3.anim.AnimationLayerSet;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.uioverrides.UiFactory;
/**
@@ -178,7 +178,8 @@
// transition plays in reverse and use the same duration as previous state.
mConfig.duration = state == NORMAL ? mState.transitionDuration : state.transitionDuration;
- AnimatorSet animation = createAnimationToNewWorkspaceInternal(state, onCompleteRunnable);
+ AnimatorSet animation = createAnimationToNewWorkspaceInternal(
+ state, new AnimatorSetBuilder(), onCompleteRunnable);
Runnable runnable = new StartAnimRunnable(animation, state.getFinalFocus(mLauncher));
if (delay > 0) {
mUiHandler.postDelayed(runnable, delay);
@@ -196,22 +197,26 @@
*/
public AnimatorPlaybackController createAnimationToNewWorkspace(
LauncherState state, long duration) {
+ return createAnimationToNewWorkspace(state, new AnimatorSetBuilder(), duration);
+ }
+
+ public AnimatorPlaybackController createAnimationToNewWorkspace(
+ LauncherState state, AnimatorSetBuilder builder, long duration) {
mConfig.reset();
mConfig.userControlled = true;
mConfig.duration = duration;
return AnimatorPlaybackController.wrap(
- createAnimationToNewWorkspaceInternal(state, null), duration);
+ createAnimationToNewWorkspaceInternal(state, builder, null), duration);
}
protected AnimatorSet createAnimationToNewWorkspaceInternal(final LauncherState state,
- final Runnable onCompleteRunnable) {
- final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
- final AnimationLayerSet layerViews = new AnimationLayerSet();
-
+ AnimatorSetBuilder builder, final Runnable onCompleteRunnable) {
for (StateHandler handler : getStateHandlers()) {
- handler.setStateWithAnimation(state, layerViews, animation, mConfig);
+ builder.startTag(handler);
+ handler.setStateWithAnimation(state, builder, mConfig);
}
- animation.addListener(layerViews);
+
+ final AnimatorSet animation = builder.build();
animation.addListener(new AnimationSuccessListener() {
@Override
@@ -330,8 +335,8 @@
/**
* Sets the UI to {@param state} by animating any changes.
*/
- void setStateWithAnimation(LauncherState toState, AnimationLayerSet layerViews,
- AnimatorSet anim, AnimationConfig config);
+ void setStateWithAnimation(LauncherState toState,
+ AnimatorSetBuilder builder, AnimationConfig config);
}
public interface StateListener {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 3d59bad..9dc8bb7 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -26,7 +26,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
@@ -63,7 +62,7 @@
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
-import com.android.launcher3.anim.AnimationLayerSet;
+import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.badge.FolderBadgeInfo;
import com.android.launcher3.compat.AppWidgetManagerCompat;
@@ -1547,10 +1546,10 @@
* Sets the current workspace {@link LauncherState}, then animates the UI
*/
@Override
- public void setStateWithAnimation(LauncherState toState, AnimationLayerSet layerViews,
- AnimatorSet anim, AnimationConfig config) {
+ public void setStateWithAnimation(LauncherState toState,
+ AnimatorSetBuilder builder, AnimationConfig config) {
StateTransitionListener listener = new StateTransitionListener(toState);
- mStateTransitionAnimation.setStateWithAnimation(toState, anim, layerViews, config);
+ mStateTransitionAnimation.setStateWithAnimation(toState, builder, config);
// Invalidate the pages now, so that we have the visible pages before the
// animation is started
@@ -1562,8 +1561,8 @@
ValueAnimator stepAnimator = ValueAnimator.ofFloat(0, 1);
stepAnimator.addUpdateListener(listener);
stepAnimator.setDuration(config.duration);
- anim.play(stepAnimator);
- anim.addListener(listener);
+ stepAnimator.addListener(listener);
+ builder.play(stepAnimator);
}
public void updateAccessibilityFlags() {
@@ -3502,17 +3501,17 @@
mRefreshPending = false;
- mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
- @Override
- public boolean evaluate(ItemInfo info, View view) {
- if (view instanceof PendingAppWidgetHostView && mInfos.contains(info)) {
- mLauncher.removeItem(view, info, false /* deleteFromDb */);
- mLauncher.bindAppWidget((LauncherAppWidgetInfo) info);
- }
- // process all the shortcuts
- return false;
+ ArrayList<PendingAppWidgetHostView> views = new ArrayList<>(mInfos.size());
+ mapOverItems(MAP_NO_RECURSE, (info, view) -> {
+ if (view instanceof PendingAppWidgetHostView && mInfos.contains(info)) {
+ views.add((PendingAppWidgetHostView) view);
}
+ // process all children
+ return false;
});
+ for (PendingAppWidgetHostView view : views) {
+ view.reinflate();
+ }
}
@Override
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index edf5ada..abc140d 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -21,7 +21,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
@@ -32,7 +31,7 @@
import com.android.launcher3.LauncherState.PageAlphaProvider;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
-import com.android.launcher3.anim.AnimationLayerSet;
+import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
/**
@@ -110,10 +109,10 @@
setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER);
}
- public void setStateWithAnimation(LauncherState toState, AnimatorSet anim,
- AnimationLayerSet layerViews, AnimationConfig config) {
+ public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
+ AnimationConfig config) {
AnimatedPropertySetter propertySetter =
- new AnimatedPropertySetter(config.duration, layerViews, anim);
+ new AnimatedPropertySetter(config.duration, builder);
setWorkspaceProperty(toState, propertySetter);
}
@@ -189,14 +188,11 @@
public static class AnimatedPropertySetter extends PropertySetter {
private final long mDuration;
- private final AnimationLayerSet mLayerViews;
- private final AnimatorSet mStateAnimator;
+ private final AnimatorSetBuilder mStateAnimator;
- public AnimatedPropertySetter(
- long duration, AnimationLayerSet layerView, AnimatorSet anim) {
+ public AnimatedPropertySetter(long duration, AnimatorSetBuilder builder) {
mDuration = duration;
- mLayerViews = layerView;
- mStateAnimator = anim;
+ mStateAnimator = builder;
}
@Override
@@ -210,7 +206,6 @@
}
anim.setDuration(mDuration).setInterpolator(getFadeInterpolator(alpha));
- mLayerViews.addView(view);
mStateAnimator.play(anim);
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 8724c2c..7b89c5c 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -260,9 +260,6 @@
if (mLauncher.getDragLayer().isEventOverView(mSearchContainer, ev)) {
return true;
}
- if (mUsingTabs && mLauncher.getDragLayer().isEventOverView(mHeader, ev)) {
- return true;
- }
AllAppsRecyclerView rv = getActiveRecyclerView();
return rv == null || rv.shouldContainerScroll(ev, mLauncher.getDragLayer());
}
@@ -554,20 +551,9 @@
return;
}
mHeader.setVisibility(View.VISIBLE);
+ mHeader.setup(mAH, mComponentToAppMap, mNumPredictedAppsPerRow);
- boolean usePredictionRow = mHasPredictions && !mSearchModeWhileUsingTabs;
- int contentHeight = usePredictionRow ? mLauncher.getDeviceProfile().allAppsCellHeightPx : 0;;
- if (usePredictionRow && !mUsingTabs) {
- contentHeight += getResources()
- .getDimensionPixelSize(R.dimen.all_apps_prediction_row_divider_height);
- }
- AllAppsRecyclerView mainRV = mAH[AdapterHolder.MAIN].recyclerView;
- AllAppsRecyclerView workRV = mAH[AdapterHolder.WORK].recyclerView;
- mHeader.setup(mainRV, workRV, contentHeight);
- mHeader.getPredictionRow().setup(mAH[AdapterHolder.MAIN].adapter,
- mComponentToAppMap, mNumPredictedAppsPerRow);
-
- int padding = contentHeight;
+ int padding = mHeader.getPredictionRow().getExpectedHeight();
if (mHasPredictions && !mUsingTabs) {
padding += mHeader.getPaddingTop() + mHeader.getPaddingBottom();
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 7ce032f..5de58b4 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -5,7 +5,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.util.Property;
import android.view.View;
@@ -19,8 +18,8 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.AnimationLayerSet;
import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.GradientView;
import com.android.launcher3.util.SystemUiController;
@@ -122,7 +121,7 @@
* @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace
*
* @see #setState(LauncherState)
- * @see #setStateWithAnimation(LauncherState, AnimationLayerSet, AnimatorSet, AnimationConfig)
+ * @see #setStateWithAnimation(LauncherState, AnimatorSetBuilder, AnimationConfig)
*/
public void setProgress(float progress) {
mProgress = progress;
@@ -167,8 +166,8 @@
* dependent UI using various animation events
*/
@Override
- public void setStateWithAnimation(LauncherState toState, AnimationLayerSet layerViews,
- AnimatorSet animationOut, AnimationConfig config) {
+ public void setStateWithAnimation(LauncherState toState,
+ AnimatorSetBuilder builder, AnimationConfig config) {
if (Float.compare(mProgress, toState.verticalProgress) == 0) {
// Fail fast
onProgressAnimationEnd();
@@ -182,7 +181,7 @@
anim.setInterpolator(interpolator);
anim.addListener(getProgressAnimatorListener());
- animationOut.play(anim);
+ builder.play(anim);
}
public AnimatorListenerAdapter getProgressAnimatorListener() {
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 39e6818..dc3afb5 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -19,43 +19,38 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Point;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
+import com.android.launcher3.AppInfo;
import com.android.launcher3.R;
+import com.android.launcher3.util.ComponentKey;
+
+import java.util.HashMap;
public class FloatingHeaderView extends RelativeLayout implements
ValueAnimator.AnimatorUpdateListener {
- private static final boolean SHOW_PREDICTIONS_ONLY_ON_TOP = true;
private final Rect mClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
+ private final Point mTempOffset = new Point();
private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
- if (SHOW_PREDICTIONS_ONLY_ON_TOP) {
- return;
- }
- if (!mTopOnlyMode && newState == RecyclerView.SCROLL_STATE_IDLE
- && mTranslationY != -mMaxTranslation && mTranslationY != 0) {
- float scroll = Math.abs(getCurrentScroll());
- boolean expand = scroll > mMaxTranslation
- ? Math.abs(mTranslationY) < mMaxTranslation / 2 : true;
- setExpanded(expand);
- }
}
@Override
public void onScrolled(RecyclerView rv, int dx, int dy) {
- boolean isMainRV = rv == mMainRV;
- if (isMainRV != mMainRVActive) {
+ if (rv != mCurrentRV) {
return;
}
@@ -63,9 +58,7 @@
mAnimator.cancel();
}
- int current = - (isMainRV
- ? mMainRV.getCurrentScrollY()
- : mWorkRV.getCurrentScrollY());
+ int current = -mCurrentRV.getCurrentScrollY();
moved(current);
apply();
}
@@ -76,14 +69,14 @@
private View mDivider;
private AllAppsRecyclerView mMainRV;
private AllAppsRecyclerView mWorkRV;
- private boolean mTopOnlyMode;
- private boolean mHeaderHidden;
+ private AllAppsRecyclerView mCurrentRV;
+ private ViewGroup mParent;
+ private boolean mTabsHidden;
+ private boolean mHeaderCollapsed;
private int mMaxTranslation;
private int mSnappedScrolledY;
private int mTranslationY;
- private int mMainScrolledY;
- private int mWorkScrolledY;
- private boolean mMainRVActive;
+ private boolean mForwardToRecyclerView;
public FloatingHeaderView(@NonNull Context context) {
this(context, null);
@@ -101,14 +94,18 @@
mPredictionRow = findViewById(R.id.header_content);
}
- public void setup(@NonNull AllAppsRecyclerView personalRV, @Nullable AllAppsRecyclerView workRV,
- int predictionRowHeight) {
- mTopOnlyMode = workRV == null;
- mTabLayout.setVisibility(mTopOnlyMode ? View.GONE : View.VISIBLE);
- mPredictionRow.getLayoutParams().height = predictionRowHeight;
- mMaxTranslation = predictionRowHeight;
- mMainRV = setupRV(mMainRV, personalRV);
- mWorkRV = setupRV(mWorkRV, workRV);
+ public void setup(AllAppsContainerView.AdapterHolder[] mAH,
+ HashMap<ComponentKey, AppInfo> componentToAppMap, int numPredictedAppsPerRow) {
+ mTabsHidden = mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView == null;
+ mTabLayout.setVisibility(mTabsHidden ? View.GONE : View.VISIBLE);
+ mPredictionRow.setPadding(0, 0, 0, mTabsHidden ? getResources()
+ .getDimensionPixelSize(R.dimen.all_apps_prediction_row_divider_height) : 0);
+ mPredictionRow.setup(mAH[AllAppsContainerView.AdapterHolder.MAIN].adapter,
+ componentToAppMap, numPredictedAppsPerRow);
+ mMaxTranslation = mPredictionRow.getExpectedHeight();
+ mMainRV = setupRV(mMainRV, mAH[AllAppsContainerView.AdapterHolder.MAIN].recyclerView);
+ mWorkRV = setupRV(mWorkRV, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView);
+ mParent = (ViewGroup) mMainRV.getParent();
setMainActive(true);
setupDivider();
}
@@ -124,16 +121,16 @@
Resources res = getResources();
int verticalGap = res.getDimensionPixelSize(R.dimen.all_apps_divider_margin_vertical);
int sideGap = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
- mDivider.setPadding(sideGap, verticalGap,sideGap, mTopOnlyMode ? verticalGap : 0);
+ mDivider.setPadding(sideGap, verticalGap,sideGap, mTabsHidden ? verticalGap : 0);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mDivider.getLayoutParams();
lp.removeRule(RelativeLayout.ALIGN_BOTTOM);
- lp.addRule(RelativeLayout.ALIGN_BOTTOM, mTopOnlyMode ? R.id.header_content : R.id.tabs);
+ lp.addRule(RelativeLayout.ALIGN_BOTTOM, mTabsHidden ? R.id.header_content : R.id.tabs);
mDivider.setLayoutParams(lp);
}
public void setMainActive(boolean active) {
- mMainRVActive = active;
- mSnappedScrolledY = getCurrentScroll() - mMaxTranslation;
+ mCurrentRV = active ? mMainRV : mWorkRV;
+ mSnappedScrolledY = mCurrentRV.getCurrentScrollY() - mMaxTranslation;
setExpanded(true);
}
@@ -141,36 +138,29 @@
return mPredictionRow;
}
- public ViewGroup getTabLayout() {
- return mTabLayout;
- }
-
public View getDivider() {
return mDivider;
}
public void reset() {
- mMainScrolledY = 0;
- mWorkScrolledY = 0;
setExpanded(true);
}
private boolean canSnapAt(int currentScrollY) {
- boolean snapOnlyOnTop = SHOW_PREDICTIONS_ONLY_ON_TOP || mTopOnlyMode;
- return !snapOnlyOnTop || Math.abs(currentScrollY) <= mPredictionRow.getHeight();
+ return Math.abs(currentScrollY) <= mPredictionRow.getHeight();
}
private void moved(final int currentScrollY) {
- if (mHeaderHidden) {
+ if (mHeaderCollapsed) {
if (currentScrollY <= mSnappedScrolledY) {
if (canSnapAt(currentScrollY)) {
mSnappedScrolledY = currentScrollY;
}
} else {
- mHeaderHidden = false;
+ mHeaderCollapsed = false;
}
mTranslationY = currentScrollY;
- } else if (!mHeaderHidden) {
+ } else if (!mHeaderCollapsed) {
mTranslationY = currentScrollY - mSnappedScrolledY - mMaxTranslation;
// update state vars
@@ -178,7 +168,7 @@
mTranslationY = 0;
mSnappedScrolledY = currentScrollY - mMaxTranslation;
} else if (mTranslationY <= -mMaxTranslation) { // hide or stay hidden
- mHeaderHidden = true;
+ mHeaderCollapsed = true;
mSnappedScrolledY = currentScrollY;
}
}
@@ -195,7 +185,7 @@
mPredictionRow.setTranslationY(uncappedTranslationY);
}
mTabLayout.setTranslationY(mTranslationY);
- mDivider.setTranslationY(mTopOnlyMode ? uncappedTranslationY : mTranslationY);
+ mDivider.setTranslationY(mTabsHidden ? uncappedTranslationY : mTranslationY);
mClip.top = mMaxTranslation + mTranslationY;
// clipping on a draw might cause additional redraw
mMainRV.setClipBounds(mClip);
@@ -210,16 +200,14 @@
mAnimator.addUpdateListener(this);
mAnimator.setDuration(150);
mAnimator.start();
- mHeaderHidden = !expand;
- mSnappedScrolledY = expand ? getCurrentScroll() - mMaxTranslation : getCurrentScroll();
+ mHeaderCollapsed = !expand;
+ mSnappedScrolledY = expand
+ ? mCurrentRV.getCurrentScrollY() - mMaxTranslation
+ : mCurrentRV.getCurrentScrollY();
}
public boolean isExpanded() {
- return !mHeaderHidden;
- }
-
- private int getCurrentScroll() {
- return mMainRVActive ? mMainScrolledY : mWorkScrolledY;
+ return !mHeaderCollapsed;
}
@Override
@@ -228,6 +216,36 @@
apply();
}
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ calcOffset(mTempOffset);
+ ev.offsetLocation(mTempOffset.x, mTempOffset.y);
+ mForwardToRecyclerView = mCurrentRV.onInterceptTouchEvent(ev);
+ ev.offsetLocation(-mTempOffset.x, -mTempOffset.y);
+ return mForwardToRecyclerView || super.onInterceptTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mForwardToRecyclerView) {
+ // take this view's and parent view's (view pager) location into account
+ calcOffset(mTempOffset);
+ event.offsetLocation(mTempOffset.x, mTempOffset.y);
+ try {
+ return mCurrentRV.onTouchEvent(event);
+ } finally {
+ event.offsetLocation(-mTempOffset.x, -mTempOffset.y);
+ }
+ } else {
+ return super.onTouchEvent(event);
+ }
+ }
+
+ private void calcOffset(Point p) {
+ p.x = getLeft() - mCurrentRV.getLeft() - mParent.getLeft();
+ p.y = getTop() - mCurrentRV.getTop() - mParent.getTop();
+ }
+
}
diff --git a/src/com/android/launcher3/allapps/PredictionRowView.java b/src/com/android/launcher3/allapps/PredictionRowView.java
index ea91770..30c30c8 100644
--- a/src/com/android/launcher3/allapps/PredictionRowView.java
+++ b/src/com/android/launcher3/allapps/PredictionRowView.java
@@ -26,6 +26,7 @@
import com.android.launcher3.AppInfo;
import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.Launcher;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ComponentKeyMapper;
@@ -57,11 +58,28 @@
setOrientation(LinearLayout.HORIZONTAL);
}
- public void setup(AllAppsGridAdapter adapter,
- HashMap<ComponentKey, AppInfo> componentToAppMap, int numPredictedAppsPerRow) {
+ public void setup(AllAppsGridAdapter adapter, HashMap<ComponentKey, AppInfo> componentToAppMap,
+ int numPredictedAppsPerRow) {
mAdapter = adapter;
mComponentToAppMap = componentToAppMap;
mNumPredictedAppsPerRow = numPredictedAppsPerRow;
+ setVisibility(mPredictedAppComponents.isEmpty() ? View.GONE : View.VISIBLE);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getExpectedHeight(),
+ MeasureSpec.EXACTLY));
+ }
+
+ public int getExpectedHeight() {
+ int height = 0;
+ if (!mPredictedAppComponents.isEmpty()) {
+ height += Launcher.getLauncher(getContext())
+ .getDeviceProfile().allAppsCellHeightPx;
+ height += getPaddingTop() + getPaddingBottom();
+ }
+ return height;
}
/**
diff --git a/src/com/android/launcher3/anim/AnimationLayerSet.java b/src/com/android/launcher3/anim/AnimationLayerSet.java
deleted file mode 100644
index f0b3458..0000000
--- a/src/com/android/launcher3/anim/AnimationLayerSet.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-package com.android.launcher3.anim;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.util.ArrayMap;
-import android.view.View;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Helper class to automatically build view hardware layers for the duration of an animation.
- */
-public class AnimationLayerSet extends AnimatorListenerAdapter {
-
- private final ArrayMap<View, Integer> mViewsToLayerTypeMap;
-
- public AnimationLayerSet() {
- mViewsToLayerTypeMap = new ArrayMap<>();
- }
-
- public AnimationLayerSet(View v) {
- mViewsToLayerTypeMap = new ArrayMap<>(1);
- addView(v);
- }
-
- public void addView(View v) {
- mViewsToLayerTypeMap.put(v, v.getLayerType());
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- // Enable all necessary layers
- Iterator<Map.Entry<View, Integer>> itr = mViewsToLayerTypeMap.entrySet().iterator();
- while (itr.hasNext()) {
- Map.Entry<View, Integer> entry = itr.next();
- View v = entry.getKey();
- entry.setValue(v.getLayerType());
- v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- if (v.isAttachedToWindow() && v.getVisibility() == View.VISIBLE) {
- v.buildLayer();
- }
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- Iterator<Map.Entry<View, Integer>> itr = mViewsToLayerTypeMap.entrySet().iterator();
- while (itr.hasNext()) {
- Map.Entry<View, Integer> entry = itr.next();
- entry.getKey().setLayerType(entry.getValue(), null);
- }
- }
-}
diff --git a/src/com/android/launcher3/anim/AnimatorSetBuilder.java b/src/com/android/launcher3/anim/AnimatorSetBuilder.java
new file mode 100644
index 0000000..63e67ff
--- /dev/null
+++ b/src/com/android/launcher3/anim/AnimatorSetBuilder.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+package com.android.launcher3.anim;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+
+import com.android.launcher3.LauncherAnimUtils;
+
+import java.util.ArrayList;
+
+/**
+ * Utility class for building animator set
+ */
+public class AnimatorSetBuilder {
+
+ protected final ArrayList<Animator> mAnims = new ArrayList<>();
+
+ /**
+ * Associates a tag with all the animations added after this call.
+ */
+ public void startTag(Object obj) { }
+
+ public void play(Animator anim) {
+ mAnims.add(anim);
+ }
+
+ public AnimatorSet build() {
+ AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
+ anim.playTogether(mAnims);
+ return anim;
+ }
+}
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 7cf3da0..0d92d45 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -60,7 +60,7 @@
public static final boolean GO_DISABLE_WIDGETS = false;
// When enabled shows a work profile tab in all apps
- public static final boolean ALL_APPS_TABS_ENABLED = false;
+ public static final boolean ALL_APPS_TABS_ENABLED = true;
// When enabled prediction row is rendered as it's own custom view
- public static final boolean ALL_APPS_PREDICTION_ROW_VIEW = false;
+ public static final boolean ALL_APPS_PREDICTION_ROW_VIEW = true;
}
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index b36a0ff..fc121d3 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -322,7 +322,7 @@
* Returns whether the specified point is inside the thumb bounds.
*/
private boolean isNearThumb(int x, int y) {
- int offset = y - mRv.getScrollBarTop() - mThumbOffsetY;
+ int offset = y - mThumbOffsetY;
return x >= 0 && x < getWidth() && offset >= 0 && offset <= mThumbHeight;
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewPanel.java b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewPanel.java
index 3ce1014..b23927b 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewPanel.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewPanel.java
@@ -17,7 +17,6 @@
import static com.android.launcher3.WorkspaceStateTransitionAnimation.NO_ANIM_PROPERTY_SETTER;
-import android.animation.AnimatorSet;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -37,7 +36,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.WorkspaceStateTransitionAnimation.AnimatedPropertySetter;
import com.android.launcher3.WorkspaceStateTransitionAnimation.PropertySetter;
-import com.android.launcher3.anim.AnimationLayerSet;
+import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.widget.WidgetsFullSheet;
@@ -168,9 +167,9 @@
}
@Override
- public void setStateWithAnimation(LauncherState toState, AnimationLayerSet layerViews,
- AnimatorSet anim, AnimationConfig config) {
- setState(toState, new AnimatedPropertySetter(config.duration, layerViews, anim));
+ public void setStateWithAnimation(LauncherState toState,
+ AnimatorSetBuilder builder, AnimationConfig config) {
+ setState(toState, new AnimatedPropertySetter(config.duration, builder));
}
private void setState(LauncherState state, PropertySetter setter) {