summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2016-01-29 13:14:14 -0800
committerSunny Goyal <sunnygoyal@google.com>2016-02-08 14:55:22 -0800
commit0ac7ede56afebe4401c0636196f5844be573ad68 (patch)
treec4bdfce0b5f788880354845ab51ae293bd608d1b /src
parent0e0498031092488ff166145c12ce36cc0a80c490 (diff)
downloadandroid_packages_apps_Trebuchet-0ac7ede56afebe4401c0636196f5844be573ad68.tar.gz
android_packages_apps_Trebuchet-0ac7ede56afebe4401c0636196f5844be573ad68.tar.bz2
android_packages_apps_Trebuchet-0ac7ede56afebe4401c0636196f5844be573ad68.zip
Merging search bar with all apps
Change-Id: I78577124cd3c05d52669c3e52b0294d6eb1d194d
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/BaseContainerView.java112
-rw-r--r--src/com/android/launcher3/Launcher.java3
-rw-r--r--src/com/android/launcher3/LauncherStateTransitionAnimation.java153
-rw-r--r--src/com/android/launcher3/SearchDropTargetBar.java170
-rw-r--r--src/com/android/launcher3/Workspace.java2
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java166
-rw-r--r--src/com/android/launcher3/allapps/AllAppsRecyclerView.java9
-rw-r--r--src/com/android/launcher3/allapps/AllAppsSearchBarController.java148
-rw-r--r--src/com/android/launcher3/allapps/DefaultAppSearchController.java255
-rw-r--r--src/com/android/launcher3/allapps/HeaderElevationController.java101
-rw-r--r--src/com/android/launcher3/widget/WidgetsContainerView.java28
11 files changed, 519 insertions, 628 deletions
diff --git a/src/com/android/launcher3/BaseContainerView.java b/src/com/android/launcher3/BaseContainerView.java
index c11824054..8bb8c55fd 100644
--- a/src/com/android/launcher3/BaseContainerView.java
+++ b/src/com/android/launcher3/BaseContainerView.java
@@ -17,32 +17,38 @@
package com.android.launcher3;
import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
import android.util.AttributeSet;
import android.util.Log;
-import android.widget.LinearLayout;
+import android.view.View;
+import android.widget.FrameLayout;
/**
* A base container view, which supports resizing.
*/
-public abstract class BaseContainerView extends LinearLayout implements Insettable {
+public abstract class BaseContainerView extends FrameLayout implements Insettable {
private final static String TAG = "BaseContainerView";
// The window insets
- private Rect mInsets = new Rect();
+ private final 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 mFixedSearchBarBounds = new Rect();
- // The computed bounds of the search bar
- private Rect mSearchBarBounds = new Rect();
+ private final Rect mFixedSearchBarBounds = new Rect();
// The computed bounds of the container
- protected Rect mContentBounds = new Rect();
+ protected final Rect mContentBounds = new Rect();
// The computed padding to apply to the container to achieve the container bounds
- private Rect mContentPadding = new Rect();
+ private final Rect mContentPadding = new Rect();
// The inset to apply to the edges and between the search bar and the container
- private int mContainerBoundsInset;
- private boolean mHasSearchBar;
+ private final int mContainerBoundsInset;
+
+ private final Drawable mRevealDrawable;
+
+ private View mRevealView;
+ private View mContent;
public BaseContainerView(Context context) {
this(context, null);
@@ -55,6 +61,19 @@ public abstract class BaseContainerView extends LinearLayout implements Insettab
public BaseContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContainerBoundsInset = getResources().getDimensionPixelSize(R.dimen.container_bounds_inset);
+
+ TypedArray a = context.obtainStyledAttributes(attrs,
+ R.styleable.BaseContainerView, defStyleAttr, 0);
+ mRevealDrawable = a.getDrawable(R.styleable.BaseContainerView_revealBackground);
+ a.recycle();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mContent = findViewById(R.id.main_content);
+ mRevealView = findViewById(R.id.reveal_view);
}
@Override
@@ -63,10 +82,6 @@ public abstract class BaseContainerView extends LinearLayout implements Insettab
updateBackgroundAndPaddings();
}
- protected void setHasSearchBar() {
- mHasSearchBar = true;
- }
-
/**
* Sets the search bar bounds for this container view to match.
*/
@@ -92,47 +107,48 @@ public abstract class BaseContainerView extends LinearLayout implements Insettab
*/
protected void updateBackgroundAndPaddings() {
Rect padding;
- Rect searchBarBounds = new Rect();
- if (!isValidSearchBarBounds(mFixedSearchBarBounds)) {
- // Use the default bounds
- padding = new Rect(mInsets.left + mContainerBoundsInset,
- (mHasSearchBar ? 0 : (mInsets.top + mContainerBoundsInset)),
- mInsets.right + mContainerBoundsInset,
- mInsets.bottom + mContainerBoundsInset);
-
- // Special case -- we have the search bar, but no specific bounds, so just give it
- // the inset bounds without a height.
- searchBarBounds.set(mInsets.left + mContainerBoundsInset,
+ if (isValidSearchBarBounds(mFixedSearchBarBounds)) {
+ padding = new Rect(
+ mFixedSearchBarBounds.left,
mInsets.top + mContainerBoundsInset,
- getMeasuredWidth() - (mInsets.right + mContainerBoundsInset), 0);
- } 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(mFixedSearchBarBounds.left,
- (mHasSearchBar ? 0 : (mInsets.top + mContainerBoundsInset)),
getMeasuredWidth() - mFixedSearchBarBounds.right,
- mInsets.bottom + mContainerBoundsInset);
-
- // Use the search bounds
- searchBarBounds.set(mFixedSearchBarBounds);
+ mInsets.bottom + mContainerBoundsInset
+ );
+ } else {
+ padding = new Rect(
+ mInsets.left + mContainerBoundsInset,
+ mInsets.top + mContainerBoundsInset,
+ mInsets.right + mContainerBoundsInset,
+ mInsets.bottom + mContainerBoundsInset
+ );
}
- // If either the computed container padding has changed, or the computed search bar bounds
- // has changed, then notify the container
- if (!padding.equals(mContentPadding) || !searchBarBounds.equals(mSearchBarBounds)) {
+ // The container padding changed, notify the container.
+ if (!padding.equals(mContentPadding)) {
mContentPadding.set(padding);
mContentBounds.set(padding.left, padding.top,
getMeasuredWidth() - padding.right,
getMeasuredHeight() - padding.bottom);
- mSearchBarBounds.set(searchBarBounds);
- onUpdateBackgroundAndPaddings(mSearchBarBounds, padding);
+ onUpdateBackgroundAndPaddings(padding);
}
}
- /**
- * To be implemented by container views to update themselves when the bounds changes.
- */
- protected abstract void onUpdateBackgroundAndPaddings(Rect searchBarBounds, Rect padding);
+ private void onUpdateBackgroundAndPaddings(Rect padding) {
+ // Apply the top-bottom padding to itself so that the launcher transition is
+ // clipped correctly
+ setPadding(0, padding.top, 0, padding.bottom);
+
+ InsetDrawable background = new InsetDrawable(mRevealDrawable,
+ padding.left, 0, padding.right, 0);
+ mRevealView.setBackground(background.getConstantState().newDrawable());
+ mContent.setBackground(background);
+
+ Rect bgPadding = new Rect();
+ background.getPadding(bgPadding);
+ onUpdateBgPadding(padding, bgPadding);
+ }
+
+ protected abstract void onUpdateBgPadding(Rect padding, Rect bgPadding);
/**
* Returns whether the search bar bounds we got are considered valid.
@@ -142,4 +158,12 @@ public abstract class BaseContainerView extends LinearLayout implements Insettab
searchBarBounds.right <= getMeasuredWidth() &&
searchBarBounds.bottom <= getMeasuredHeight();
}
+
+ public final View getContentView() {
+ return mContent;
+ }
+
+ public final View getRevealView() {
+ return mRevealView;
+ }
} \ No newline at end of file
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 0599eb8d9..987698e23 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -97,6 +97,7 @@ import android.widget.Toast;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.PagedView.PageSwitchListener;
import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.DefaultAppSearchController;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -1408,7 +1409,7 @@ public class Launcher extends Activity
if (mLauncherCallbacks != null && mLauncherCallbacks.getAllAppsSearchBarController() != null) {
mAppsView.setSearchBarController(mLauncherCallbacks.getAllAppsSearchBarController());
} else {
- mAppsView.setSearchBarController(mAppsView.newDefaultAppSearchController());
+ mAppsView.setSearchBarController(new DefaultAppSearchController());
}
// Setup the drag controller (drop targets have to be added in reverse order in priority)
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index 83b12a99d..30cae3114 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -80,13 +80,18 @@ import java.util.HashMap;
*/
public class LauncherStateTransitionAnimation {
+ private static final float FINAL_REVEAL_ALPHA_FOR_WIDGETS = 0.3f;
+
/**
* Private callbacks made during transition setup.
*/
- static abstract class PrivateTransitionCallbacks {
- float getMaterialRevealViewFinalAlpha(View revealView) {
- return 0;
+ private static class PrivateTransitionCallbacks {
+ private final float materialRevealViewFinalAlpha;
+
+ PrivateTransitionCallbacks(float revealAlpha) {
+ materialRevealViewFinalAlpha = revealAlpha;
}
+
float getMaterialRevealViewStartFinalRadius() {
return 0;
}
@@ -97,7 +102,7 @@ public class LauncherStateTransitionAnimation {
void onTransitionComplete() {}
}
- public static final String TAG = "LauncherStateTransitionAnimation";
+ public static final String TAG = "LSTAnimation";
// Flags to determine how to set the layers on views before the transition animation
public static final int BUILD_LAYER = 0;
@@ -121,11 +126,7 @@ public class LauncherStateTransitionAnimation {
final boolean animated, final boolean startSearchAfterTransition) {
final AllAppsContainerView toView = mLauncher.getAppsView();
final View buttonView = mLauncher.getAllAppsButton();
- PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
- @Override
- public float getMaterialRevealViewFinalAlpha(View revealView) {
- return 1f;
- }
+ PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks(1f) {
@Override
public float getMaterialRevealViewStartFinalRadius() {
int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
@@ -152,8 +153,7 @@ public class LauncherStateTransitionAnimation {
};
// Only animate the search bar if animating from spring loaded mode back to all apps
mCurrentAnimation = startAnimationToOverlay(fromWorkspaceState,
- Workspace.State.NORMAL_HIDDEN, buttonView, toView, toView.getContentView(),
- toView.getRevealView(), toView.getSearchBarView(), animated, cb);
+ Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, cb);
}
/**
@@ -164,15 +164,9 @@ public class LauncherStateTransitionAnimation {
final WidgetsContainerView toView = mLauncher.getWidgetsView();
final View buttonView = mLauncher.getWidgetsButton();
- PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
- @Override
- public float getMaterialRevealViewFinalAlpha(View revealView) {
- return 0.3f;
- }
- };
mCurrentAnimation = startAnimationToOverlay(fromWorkspaceState,
- Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, toView.getContentView(),
- toView.getRevealView(), null, animated, cb);
+ Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, animated,
+ new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS));
}
/**
@@ -200,16 +194,15 @@ public class LauncherStateTransitionAnimation {
* Creates and starts a new animation to a particular overlay view.
*/
@SuppressLint("NewApi")
- private AnimatorSet startAnimationToOverlay(final Workspace.State fromWorkspaceState,
- final Workspace.State toWorkspaceState, final View buttonView, final View toView,
- final View contentView, final View revealView, final View overlaySearchBarView,
+ private AnimatorSet startAnimationToOverlay(
+ final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
+ final View buttonView, final BaseContainerView toView,
final boolean animated, final PrivateTransitionCallbacks pCb) {
final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
final Resources res = mLauncher.getResources();
final boolean material = Utilities.ATLEAST_LOLLIPOP;
final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
- final int itemsAlphaStagger =
- res.getInteger(R.integer.config_overlayItemsAlphaStagger);
+ final int itemsAlphaStagger = res.getInteger(R.integer.config_overlayItemsAlphaStagger);
final View fromView = mLauncher.getWorkspace();
@@ -227,13 +220,17 @@ public class LauncherStateTransitionAnimation {
animated, layerViews);
// Animate the search bar
- startWorkspaceSearchBarAnimation(animation, fromWorkspaceState, toWorkspaceState,
- animated ? revealDuration : 0, overlaySearchBarView);
+ startWorkspaceSearchBarAnimation(
+ toWorkspaceState, animated ? revealDuration : 0, animation);
Animator updateTransitionStepAnim = dispatchOnLauncherTransitionStepAnim(fromView, toView);
+ final View contentView = toView.getContentView();
+
if (animated && initialized) {
// Setup the reveal view animation
+ final View revealView = toView.getRevealView();
+
int width = revealView.getMeasuredWidth();
int height = revealView.getMeasuredHeight();
float revealRadius = (float) Math.hypot(width / 2, height / 2);
@@ -247,9 +244,9 @@ public class LauncherStateTransitionAnimation {
final float revealViewToXDrift;
final float revealViewToYDrift;
if (material) {
- int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
- buttonView, null);
- revealViewToAlpha = pCb.getMaterialRevealViewFinalAlpha(revealView);
+ int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(
+ revealView, buttonView, null);
+ revealViewToAlpha = pCb.materialRevealViewFinalAlpha;
revealViewToYDrift = buttonViewToPanelDelta[1];
revealViewToXDrift = buttonViewToPanelDelta[0];
} else {
@@ -274,15 +271,6 @@ public class LauncherStateTransitionAnimation {
layerViews.put(revealView, BUILD_AND_SET_LAYER);
animation.play(panelAlphaAndDrift);
- if (overlaySearchBarView != null) {
- overlaySearchBarView.setAlpha(0f);
- ObjectAnimator searchBarAlpha = ObjectAnimator.ofFloat(overlaySearchBarView, "alpha", 0f, 1f);
- searchBarAlpha.setDuration(revealDuration / 2);
- searchBarAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
- layerViews.put(overlaySearchBarView, BUILD_AND_SET_LAYER);
- animation.play(searchBarAlpha);
- }
-
// Setup the animation for the content view
contentView.setVisibility(View.VISIBLE);
contentView.setAlpha(0f);
@@ -430,12 +418,8 @@ public class LauncherStateTransitionAnimation {
final Workspace.State toWorkspaceState, final int toWorkspacePage,
final boolean animated, final Runnable onCompleteRunnable) {
AllAppsContainerView appsView = mLauncher.getAppsView();
- PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
- @Override
- float getMaterialRevealViewFinalAlpha(View revealView) {
- // No alpha anim from all apps
- return 1f;
- }
+ // No alpha anim from all apps
+ PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks(1f) {
@Override
float getMaterialRevealViewStartFinalRadius() {
int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
@@ -463,9 +447,8 @@ public class LauncherStateTransitionAnimation {
};
// Only animate the search bar if animating to spring loaded mode from all apps
mCurrentAnimation = startAnimationToWorkspaceFromOverlay(fromWorkspaceState, toWorkspaceState,
- toWorkspacePage, mLauncher.getAllAppsButton(), appsView, appsView.getContentView(),
- appsView.getRevealView(), appsView.getSearchBarView(), animated,
- onCompleteRunnable, cb);
+ toWorkspacePage, mLauncher.getAllAppsButton(), appsView,
+ animated, onCompleteRunnable, cb);
}
/**
@@ -475,11 +458,8 @@ public class LauncherStateTransitionAnimation {
final Workspace.State toWorkspaceState, final int toWorkspacePage,
final boolean animated, final Runnable onCompleteRunnable) {
final WidgetsContainerView widgetsView = mLauncher.getWidgetsView();
- PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
- @Override
- float getMaterialRevealViewFinalAlpha(View revealView) {
- return 0.3f;
- }
+ PrivateTransitionCallbacks cb =
+ new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS) {
@Override
public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
final View revealView, final View widgetsButtonView) {
@@ -491,19 +471,20 @@ public class LauncherStateTransitionAnimation {
};
}
};
- mCurrentAnimation = startAnimationToWorkspaceFromOverlay(fromWorkspaceState,
- toWorkspaceState, toWorkspacePage, mLauncher.getWidgetsButton(), widgetsView,
- widgetsView.getContentView(), widgetsView.getRevealView(), null, animated,
- onCompleteRunnable, cb);
+ mCurrentAnimation = startAnimationToWorkspaceFromOverlay(
+ fromWorkspaceState, toWorkspaceState,
+ toWorkspacePage, mLauncher.getWidgetsButton(), widgetsView,
+ animated, onCompleteRunnable, cb);
}
/**
* Creates and starts a new animation to the workspace.
*/
- private AnimatorSet startAnimationToWorkspaceFromOverlay(final Workspace.State fromWorkspaceState,
- final Workspace.State toWorkspaceState, final int toWorkspacePage, final View buttonView,
- final View fromView, final View contentView, final View revealView,
- final View overlaySearchBarView, final boolean animated, final Runnable onCompleteRunnable,
+ private AnimatorSet startAnimationToWorkspaceFromOverlay(
+ final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
+ final int toWorkspacePage,
+ final View buttonView, final BaseContainerView fromView,
+ final boolean animated, final Runnable onCompleteRunnable,
final PrivateTransitionCallbacks pCb) {
final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
final Resources res = mLauncher.getResources();
@@ -528,8 +509,8 @@ public class LauncherStateTransitionAnimation {
toWorkspacePage, animated, layerViews);
// Animate the search bar
- startWorkspaceSearchBarAnimation(animation, fromWorkspaceState, toWorkspaceState,
- animated ? revealDuration : 0, overlaySearchBarView);
+ startWorkspaceSearchBarAnimation(
+ toWorkspaceState, animated ? revealDuration : 0, animation);
Animator updateTransitionStepAnim = dispatchOnLauncherTransitionStepAnim(fromView, toView);
@@ -540,6 +521,8 @@ public class LauncherStateTransitionAnimation {
}
animation.play(updateTransitionStepAnim);
+ final View revealView = fromView.getRevealView();
+ final View contentView = fromView.getContentView();
// hideAppsCustomizeHelper is called in some cases when it is already hidden
// don't perform all these no-op animations. In particularly, this was causing
@@ -588,7 +571,7 @@ public class LauncherStateTransitionAnimation {
// Setup animation for the reveal panel alpha
final float revealViewToAlpha = !material ? 0f :
- pCb.getMaterialRevealViewFinalAlpha(revealView);
+ pCb.materialRevealViewFinalAlpha;
if (revealViewToAlpha != 1f) {
ObjectAnimator panelAlpha = ObjectAnimator.ofFloat(revealView, "alpha",
1f, revealViewToAlpha);
@@ -616,16 +599,6 @@ public class LauncherStateTransitionAnimation {
itemsAlpha.setInterpolator(decelerateInterpolator);
animation.play(itemsAlpha);
- if (overlaySearchBarView != null) {
- overlaySearchBarView.setAlpha(1f);
- ObjectAnimator searchAlpha = ObjectAnimator.ofFloat(overlaySearchBarView, "alpha", 1f, 0f);
- searchAlpha.setDuration(revealDuration / 2);
- searchAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
- searchAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY);
- layerViews.put(overlaySearchBarView, BUILD_AND_SET_LAYER);
- animation.play(searchAlpha);
- }
-
if (material) {
// Animate the all apps button
float finalRadius = pCb.getMaterialRevealViewStartFinalRadius();
@@ -671,9 +644,6 @@ public class LauncherStateTransitionAnimation {
contentView.setTranslationY(0);
contentView.setAlpha(1);
}
- if (overlaySearchBarView != null) {
- overlaySearchBarView.setAlpha(1f);
- }
// This can hold unnecessary references to views.
cleanupAnimation();
@@ -729,36 +699,11 @@ public class LauncherStateTransitionAnimation {
/**
* Coordinates the workspace search bar animation along with the launcher state animation.
*/
- private void startWorkspaceSearchBarAnimation(AnimatorSet animation,
- final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState, int duration,
- View overlaySearchBar) {
+ private void startWorkspaceSearchBarAnimation(
+ final Workspace.State toWorkspaceState, int duration, AnimatorSet animation) {
final SearchDropTargetBar.State toSearchBarState =
toWorkspaceState.getSearchDropTargetBarState();
-
- if (overlaySearchBar != null) {
- if (mLauncher.launcherCallbacksProvidesSearch()) {
- if ((toWorkspaceState == Workspace.State.NORMAL) &&
- (fromWorkspaceState == Workspace.State.NORMAL_HIDDEN)) {
- // If we are transitioning from the overlay to the workspace, then show the
- // workspace search bar immediately and let the overlay search bar fade out on
- // top
- mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, 0);
- return;
- } else if (fromWorkspaceState == Workspace.State.NORMAL) {
- // If we are transitioning from the workspace to the overlay, then keep the
- // workspace search bar visible until the overlay search bar fades in on top
- animation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, 0);
- }
- });
- return;
- }
- }
- }
- // Fallback to the default search bar animation otherwise
- mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, duration);
+ mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, duration, animation);
}
/**
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
index aad6dbc9f..f7288a0a0 100644
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ b/src/com/android/launcher3/SearchDropTargetBar.java
@@ -18,12 +18,18 @@ package com.android.launcher3;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import com.android.launcher3.util.Thunk;
@@ -34,35 +40,32 @@ import com.android.launcher3.util.Thunk;
*/
public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener {
+ private static final TimeInterpolator MOVE_DOWN_INTERPOLATOR = new DecelerateInterpolator(0.6f);
+ private static final TimeInterpolator MOVE_UP_INTERPOLATOR = new DecelerateInterpolator(1.5f);
+ private static final TimeInterpolator DEFAULT_INTERPOLATOR = new AccelerateInterpolator();
+
/** The different states that the search bar space can be in. */
public enum State {
- INVISIBLE (0f, 0f),
- SEARCH_BAR (1f, 0f),
- DROP_TARGET (0f, 1f);
+ INVISIBLE (0f, 0f, 0f),
+ INVISIBLE_TRANSLATED (0f, 0f, -1f),
+ SEARCH_BAR (1f, 0f, 0f),
+ DROP_TARGET (0f, 1f, 0f);
private final float mSearchBarAlpha;
private final float mDropTargetBarAlpha;
+ private final float mTranslation;
- State(float sbAlpha, float dtbAlpha) {
+ State(float sbAlpha, float dtbAlpha, float translation) {
mSearchBarAlpha = sbAlpha;
mDropTargetBarAlpha = dtbAlpha;
+ mTranslation = translation;
}
- float getSearchBarAlpha() {
- return mSearchBarAlpha;
- }
-
- float getDropTargetBarAlpha() {
- return mDropTargetBarAlpha;
- }
}
private static int DEFAULT_DRAG_FADE_DURATION = 175;
- private LauncherViewPropertyAnimator mDropTargetBarAnimator;
- private LauncherViewPropertyAnimator mQSBSearchBarAnimator;
- private static final AccelerateInterpolator sAccelerateInterpolator =
- new AccelerateInterpolator();
+ private AnimatorSet mCurrentAnimation;
private State mState = State.SEARCH_BAR;
@Thunk View mQSB;
@@ -117,50 +120,10 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
// Create the various fade animations
mDropTargetBar.setAlpha(0f);
AlphaUpdateListener.updateVisibility(mDropTargetBar, mAccessibilityEnabled);
-
- mDropTargetBarAnimator = new LauncherViewPropertyAnimator(mDropTargetBar);
- mDropTargetBarAnimator.setInterpolator(sAccelerateInterpolator);
- mDropTargetBarAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- // Ensure that the view is visible for the animation
- mDropTargetBar.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mDropTargetBar != null) {
- AlphaUpdateListener.updateVisibility(mDropTargetBar, mAccessibilityEnabled);
- }
- }
- });
}
public void setQsbSearchBar(View qsb) {
mQSB = qsb;
- if (mQSB != null) {
- // Update the search ber animation
- mQSBSearchBarAnimator = new LauncherViewPropertyAnimator(mQSB);
- mQSBSearchBarAnimator.setInterpolator(sAccelerateInterpolator);
- mQSBSearchBarAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- // Ensure that the view is visible for the animation
- if (mQSB != null) {
- mQSB.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mQSB != null) {
- AlphaUpdateListener.updateVisibility(mQSB, mAccessibilityEnabled);
- }
- }
- });
- } else {
- mQSBSearchBarAnimator = null;
- }
}
/**
@@ -168,6 +131,10 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
* the state is applied immediately.
*/
public void animateToState(State newState, int duration) {
+ animateToState(newState, duration, null);
+ }
+
+ public void animateToState(State newState, int duration, AnimatorSet animation) {
if (mState != newState) {
mState = newState;
@@ -176,33 +143,66 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
mAccessibilityEnabled = am.isEnabled();
- animateViewAlpha(mQSBSearchBarAnimator, mQSB, newState.getSearchBarAlpha(),
- duration);
- animateViewAlpha(mDropTargetBarAnimator, mDropTargetBar, newState.getDropTargetBarAlpha(),
- duration);
- }
- }
-
- /**
- * Convenience method to animate the alpha of a view using hardware layers.
- */
- private void animateViewAlpha(LauncherViewPropertyAnimator animator, View v, float alpha,
- int duration) {
- if (v == null) {
- return;
- }
+ if (mCurrentAnimation != null) {
+ mCurrentAnimation.cancel();
+ mCurrentAnimation = null;
+ }
+ mCurrentAnimation = null;
- animator.cancel();
- if (Float.compare(v.getAlpha(), alpha) != 0) {
if (duration > 0) {
- animator.alpha(alpha).withLayer().setDuration(duration).start();
+ mCurrentAnimation = new AnimatorSet();
+ mCurrentAnimation.setDuration(duration);
+
+ animateAlpha(mDropTargetBar, mState.mDropTargetBarAlpha, DEFAULT_INTERPOLATOR);
} else {
- v.setAlpha(alpha);
- AlphaUpdateListener.updateVisibility(v, mAccessibilityEnabled);
+ mDropTargetBar.setAlpha(mState.mDropTargetBarAlpha);
+ AlphaUpdateListener.updateVisibility(mDropTargetBar, mAccessibilityEnabled);
+ }
+
+ if (mQSB != null) {
+ boolean isVertical = ((Launcher) getContext()).getDeviceProfile()
+ .isVerticalBarLayout();
+ float translation = isVertical ? 0 : mState.mTranslation * getMeasuredHeight();
+
+ if (duration > 0) {
+ int translationChange = Float.compare(mQSB.getTranslationY(), translation);
+
+ animateAlpha(mQSB, mState.mSearchBarAlpha,
+ translationChange == 0 ? DEFAULT_INTERPOLATOR
+ : (translationChange < 0 ? MOVE_DOWN_INTERPOLATOR
+ : MOVE_UP_INTERPOLATOR));
+
+ if (translationChange != 0) {
+ mCurrentAnimation.play(
+ ObjectAnimator.ofFloat(mQSB, View.TRANSLATION_Y, translation));
+ }
+ } else {
+ mQSB.setTranslationY(translation);
+ mQSB.setAlpha(mState.mSearchBarAlpha);
+ AlphaUpdateListener.updateVisibility(mQSB, mAccessibilityEnabled);
+ }
+ }
+
+ // Start the final animation
+ if (duration > 0) {
+ if (animation != null) {
+ animation.play(mCurrentAnimation);
+ } else {
+ mCurrentAnimation.start();
+ }
}
}
}
+ private void animateAlpha(View v, float alpha, TimeInterpolator interpolator) {
+ if (Float.compare(v.getAlpha(), alpha) != 0) {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.ALPHA, alpha);
+ anim.setInterpolator(interpolator);
+ anim.addListener(new ViewVisiblilyUpdateHandler(v));
+ mCurrentAnimation.play(anim);
+ }
+ }
+
/*
* DragController.DragListener implementation
*/
@@ -255,4 +255,24 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
mDeleteDropTarget.enableAccessibleDrag(enable);
mUninstallDropTarget.enableAccessibleDrag(enable);
}
+
+ private class ViewVisiblilyUpdateHandler extends AnimatorListenerAdapter {
+ private final View mView;
+
+ ViewVisiblilyUpdateHandler(View v) {
+ mView = v;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ // Ensure that the view is visible for the animation
+ mView.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation){
+ AlphaUpdateListener.updateVisibility(mView, mAccessibilityEnabled);
+ }
+
+ }
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 56801ff61..7b873d420 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -181,7 +181,7 @@ public class Workspace extends PagedView
enum State {
NORMAL (SearchDropTargetBar.State.SEARCH_BAR),
- NORMAL_HIDDEN (SearchDropTargetBar.State.INVISIBLE),
+ NORMAL_HIDDEN (SearchDropTargetBar.State.INVISIBLE_TRANSLATED),
SPRING_LOADED (SearchDropTargetBar.State.DROP_TARGET),
OVERVIEW (SearchDropTargetBar.State.INVISIBLE),
OVERVIEW_HIDDEN (SearchDropTargetBar.State.INVISIBLE);
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index f9bb13450..8f8858fb6 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -17,11 +17,9 @@ package com.android.launcher3.allapps;
import android.annotation.SuppressLint;
import android.content.Context;
-import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.drawable.InsetDrawable;
import android.support.v7.widget.RecyclerView;
import android.text.Selection;
import android.text.SpannableStringBuilder;
@@ -32,8 +30,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
+
import com.android.launcher3.AppInfo;
import com.android.launcher3.BaseContainerView;
import com.android.launcher3.BubbleTextView;
@@ -42,6 +39,7 @@ import com.android.launcher3.DeleteDropTarget;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
+import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Folder;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
@@ -50,7 +48,6 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.Thunk;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
@@ -135,19 +132,19 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
private static final int MIN_ROWS_IN_MERGED_SECTION_PHONE = 3;
private static final int MAX_NUM_MERGES_PHONE = 2;
- @Thunk Launcher mLauncher;
- @Thunk AlphabeticalAppsList mApps;
- private AllAppsGridAdapter mAdapter;
- private RecyclerView.LayoutManager mLayoutManager;
- private RecyclerView.ItemDecoration mItemDecoration;
-
- @Thunk View mContent;
- @Thunk View mContainerView;
- @Thunk View mRevealView;
- @Thunk AllAppsRecyclerView mAppsRecyclerView;
- @Thunk AllAppsSearchBarController mSearchBarController;
- private ViewGroup mSearchBarContainerView;
- private View mSearchBarView;
+ private final Launcher mLauncher;
+ private final AlphabeticalAppsList mApps;
+ private final AllAppsGridAdapter mAdapter;
+ private final RecyclerView.LayoutManager mLayoutManager;
+ private final RecyclerView.ItemDecoration mItemDecoration;
+
+ private AllAppsRecyclerView mAppsRecyclerView;
+ private AllAppsSearchBarController mSearchBarController;
+
+ private View mSearchContainer;
+ private ExtendedEditText mSearchInput;
+ private HeaderElevationController mElevationController;
+
private SpannableStringBuilder mSearchQueryBuilder = null;
private int mSectionNamesMargin;
@@ -159,14 +156,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
// This coordinate is relative to its parent
private final Point mIconLastTouchPos = new Point();
- private View.OnClickListener mSearchClickListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent searchIntent = (Intent) v.getTag();
- mLauncher.startActivitySafely(v, searchIntent, null);
- }
- };
-
public AllAppsContainerView(Context context) {
this(context, null);
}
@@ -236,14 +225,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
throw new RuntimeException("Expected search bar controller to only be set once");
}
mSearchBarController = searchController;
- mSearchBarController.initialize(mApps, this);
-
- // Add the new search view to the layout
- View searchBarView = searchController.getView(mSearchBarContainerView);
- mSearchBarContainerView.addView(searchBarView);
- mSearchBarContainerView.setVisibility(View.VISIBLE);
- mSearchBarView = searchBarView;
- setHasSearchBar();
+ mSearchBarController.initialize(mApps, mSearchInput, mAppsRecyclerView, this);
updateBackgroundAndPaddings();
}
@@ -256,34 +238,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
}
/**
- * Returns the content view used for the launcher transitions.
- */
- public View getContentView() {
- return mContainerView;
- }
-
- /**
- * Returns the all apps search view.
- */
- public View getSearchBarView() {
- return mSearchBarView;
- }
-
- /**
- * Returns the reveal view used for the launcher transitions.
- */
- public View getRevealView() {
- return mRevealView;
- }
-
- /**
- * Returns an new instance of the default app search controller.
- */
- public AllAppsSearchBarController newDefaultAppSearchController() {
- return new DefaultAppSearchController(getContext(), this, mAppsRecyclerView);
- }
-
- /**
* Focuses the search field and begins an app search.
*/
public void startAppsSearch() {
@@ -304,25 +258,24 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- boolean isRtl = Utilities.isRtl(getResources());
- mAdapter.setRtl(isRtl);
- mContent = findViewById(R.id.content);
+ mAdapter.setRtl(Utilities.isRtl(getResources()));
// This is a focus listener that proxies focus from a view into the list view. This is to
// work around the search box from getting first focus and showing the cursor.
- View.OnFocusChangeListener focusProxyListener = new View.OnFocusChangeListener() {
+ getContentView().setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
mAppsRecyclerView.requestFocus();
}
}
- };
- mSearchBarContainerView = (ViewGroup) findViewById(R.id.search_box_container);
- mSearchBarContainerView.setOnFocusChangeListener(focusProxyListener);
- mContainerView = findViewById(R.id.all_apps_container);
- mContainerView.setOnFocusChangeListener(focusProxyListener);
- mRevealView = findViewById(R.id.all_apps_reveal);
+ });
+
+ mSearchContainer = findViewById(R.id.search_container);
+ mSearchInput = (ExtendedEditText) findViewById(R.id.search_box_input);
+ mElevationController = Utilities.ATLEAST_LOLLIPOP
+ ? new HeaderElevationController.ControllerVL(mSearchContainer)
+ : new HeaderElevationController.ControllerV16(mSearchContainer);
// Load the all apps recycler view
mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view);
@@ -330,22 +283,28 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
mAppsRecyclerView.setLayoutManager(mLayoutManager);
mAppsRecyclerView.setAdapter(mAdapter);
mAppsRecyclerView.setHasFixedSize(true);
+ mAppsRecyclerView.addOnScrollListener(mElevationController);
+ mAppsRecyclerView.setElevationController(mElevationController);
+
if (mItemDecoration != null) {
mAppsRecyclerView.addItemDecoration(mItemDecoration);
}
// Precalculate the prediction icon and normal icon sizes
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+ final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ getResources().getDisplayMetrics().widthPixels, MeasureSpec.AT_MOST);
+ final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ getResources().getDisplayMetrics().heightPixels, MeasureSpec.AT_MOST);
+
BubbleTextView icon = (BubbleTextView) layoutInflater.inflate(
R.layout.all_apps_icon, this, false);
icon.applyDummyInfo();
- icon.measure(MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST));
+ icon.measure(widthMeasureSpec, heightMeasureSpec);
BubbleTextView predIcon = (BubbleTextView) layoutInflater.inflate(
R.layout.all_apps_prediction_bar_icon, this, false);
predIcon.applyDummyInfo();
- predIcon.measure(MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST));
+ predIcon.measure(widthMeasureSpec, heightMeasureSpec);
mAppsRecyclerView.setPremeasuredIconHeights(predIcon.getMeasuredHeight(),
icon.getMeasuredHeight());
@@ -360,8 +319,11 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Update the number of items in the grid before we measure the view
- int availableWidth = !mContentBounds.isEmpty() ? mContentBounds.width() :
- MeasureSpec.getSize(widthMeasureSpec);
+ // TODO: mSectionNamesMargin is currently 0, but also account for it,
+ // if it's enabled in the future.
+ int availableWidth = (!mContentBounds.isEmpty() ? mContentBounds.width() :
+ MeasureSpec.getSize(widthMeasureSpec))
+ - 2 * mAppsRecyclerView.getMaxScrollbarWidth();
DeviceProfile grid = mLauncher.getDeviceProfile();
grid.updateAppsViewNumCols(getResources(), availableWidth);
if (mNumAppsPerRow != grid.allAppsNumCols ||
@@ -380,6 +342,12 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
mAppsRecyclerView.setNumAppsPerRow(grid, mNumAppsPerRow);
mAdapter.setNumAppsPerRow(mNumAppsPerRow);
mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, mergeAlgorithm);
+
+ if (mNumAppsPerRow > 0) {
+ int iconSize = availableWidth / mNumAppsPerRow;
+ int iconSpacing = (iconSize - grid.allAppsIconSizePx) / 2;
+ mSearchInput.setPaddingRelative(iconSpacing, 0, iconSpacing, 0);
+ }
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -391,51 +359,33 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
* recycler view to handle touch events (for fast scrolling) all the way to the edge.
*/
@Override
- protected void onUpdateBackgroundAndPaddings(Rect searchBarBounds, Rect padding) {
- boolean isRtl = Utilities.isRtl(getResources());
-
- // TODO: Use quantum_panel instead of quantum_panel_shape
- InsetDrawable background = new InsetDrawable(
- getResources().getDrawable(R.drawable.quantum_panel_shape), padding.left, 0,
- padding.right, 0);
- Rect bgPadding = new Rect();
- background.getPadding(bgPadding);
- mContainerView.setBackground(background);
- mRevealView.setBackground(background.getConstantState().newDrawable());
+ protected void onUpdateBgPadding(Rect padding, Rect bgPadding) {
mAppsRecyclerView.updateBackgroundPadding(bgPadding);
mAdapter.updateBackgroundPadding(bgPadding);
+ mElevationController.updateBackgroundPadding(bgPadding);
// Hack: We are going to let the recycler view take the full width, so reset the padding on
// the container to zero after setting the background and apply the top-bottom padding to
// the content view instead so that the launcher transition clips correctly.
- mContent.setPadding(0, padding.top, 0, padding.bottom);
- mContainerView.setPadding(0, 0, 0, 0);
+ getContentView().setPadding(0, 0, 0, 0);
// Pad the recycler view by the background padding plus the start margin (for the section
// names)
- int startInset = Math.max(mSectionNamesMargin, mAppsRecyclerView.getMaxScrollbarWidth());
+ int maxScrollBarWidth = mAppsRecyclerView.getMaxScrollbarWidth();
+ int startInset = Math.max(mSectionNamesMargin, maxScrollBarWidth);
int topBottomPadding = mRecyclerViewTopBottomPadding;
- if (isRtl) {
- mAppsRecyclerView.setPadding(padding.left + mAppsRecyclerView.getMaxScrollbarWidth(),
+ if (Utilities.isRtl(getResources())) {
+ mAppsRecyclerView.setPadding(padding.left + maxScrollBarWidth,
topBottomPadding, padding.right + startInset, topBottomPadding);
} else {
mAppsRecyclerView.setPadding(padding.left + startInset, topBottomPadding,
- padding.right + mAppsRecyclerView.getMaxScrollbarWidth(), topBottomPadding);
+ padding.right + maxScrollBarWidth, topBottomPadding);
}
- // Inset the search bar to fit its bounds above the container
- if (mSearchBarView != null) {
- Rect backgroundPadding = new Rect();
- if (mSearchBarView.getBackground() != null) {
- mSearchBarView.getBackground().getPadding(backgroundPadding);
- }
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
- mSearchBarContainerView.getLayoutParams();
- lp.leftMargin = searchBarBounds.left - backgroundPadding.left;
- lp.topMargin = searchBarBounds.top - backgroundPadding.top;
- lp.rightMargin = (getMeasuredWidth() - searchBarBounds.right) - backgroundPadding.right;
- mSearchBarContainerView.requestLayout();
- }
+ MarginLayoutParams lp = (MarginLayoutParams) mSearchContainer.getLayoutParams();
+ lp.leftMargin = padding.left;
+ lp.rightMargin = padding.right;
+ mSearchContainer.setLayoutParams(lp);
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 1cb03c989..2b3d061e6 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -53,6 +53,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView
private AllAppsBackgroundDrawable mEmptySearchBackground;
private int mEmptySearchBackgroundTopOffset;
+ private HeaderElevationController mElevationController;
+
public AllAppsRecyclerView(Context context) {
this(context, null);
}
@@ -83,6 +85,10 @@ public class AllAppsRecyclerView extends BaseRecyclerView
mFastScrollHelper = new AllAppsFastScrollHelper(this, apps);
}
+ public void setElevationController(HeaderElevationController elevationController) {
+ mElevationController = elevationController;
+ }
+
/**
* Sets the number of apps per row in this recycler view.
*/
@@ -116,6 +122,9 @@ public class AllAppsRecyclerView extends BaseRecyclerView
mScrollbar.reattachThumbToScroll();
}
scrollToPosition(0);
+ if (mElevationController != null) {
+ mElevationController.reset();
+ }
}
/**
diff --git a/src/com/android/launcher3/allapps/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
index 2b363c0cb..fdce3895f 100644
--- a/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
@@ -15,65 +15,179 @@
*/
package com.android.launcher3.allapps;
-import android.content.ComponentName;
+import android.content.Context;
import android.graphics.Rect;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+import com.android.launcher3.ExtendedEditText;
+import com.android.launcher3.Utilities;
import com.android.launcher3.util.ComponentKey;
import java.util.ArrayList;
+import java.util.List;
/**
* An interface to a search box that AllApps can command.
*/
-public abstract class AllAppsSearchBarController {
+public abstract class AllAppsSearchBarController
+ implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener {
+ private static final boolean ALLOW_SINGLE_APP_LAUNCH = true;
+
+ protected AllAppsRecyclerView mAppsRecyclerView;
protected AlphabeticalAppsList mApps;
protected Callbacks mCb;
+ protected ExtendedEditText mInput;
+
+ protected DefaultAppSearchAlgorithm mSearchAlgorithm;
+ protected InputMethodManager mInputMethodManager;
/**
* Sets the references to the apps model and the search result callback.
*/
- public final void initialize(AlphabeticalAppsList apps, Callbacks cb) {
+ public final void initialize(
+ AlphabeticalAppsList apps, ExtendedEditText input,
+ AllAppsRecyclerView recycleView, Callbacks cb) {
mApps = apps;
mCb = cb;
- onInitialize();
+ mAppsRecyclerView = recycleView;
+
+ mInput = input;
+ mInput.addTextChangedListener(this);
+ mInput.setOnEditorActionListener(this);
+ mInput.setOnBackKeyListener(this);
+
+ mInputMethodManager = (InputMethodManager)
+ mInput.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ mSearchAlgorithm = onInitializeSearch();
}
/**
- * To be overridden by subclasses. This method will get called when the controller is set,
- * before getView().
+ * To be overridden by subclasses. This method will get called when the controller is set.
*/
- protected abstract void onInitialize();
+ protected DefaultAppSearchAlgorithm onInitializeSearch() {
+ return null;
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // Do nothing
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // Do nothing
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+ String query = s.toString();
+ if (query.isEmpty()) {
+ mSearchAlgorithm.cancel(true);
+ mCb.clearSearchResult();
+ } else {
+ mSearchAlgorithm.cancel(false);
+ mSearchAlgorithm.doSearch(query, mCb);
+ }
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ // Skip if we disallow app-launch-on-enter
+ if (!ALLOW_SINGLE_APP_LAUNCH) {
+ return false;
+ }
+ // Skip if it's not the right action
+ if (actionId != EditorInfo.IME_ACTION_SEARCH) {
+ return false;
+ }
+ // Skip if there are more than one icon
+ if (mApps.getNumFilteredApps() > 1) {
+ return false;
+ }
+ // Otherwise, find the first icon, or fallback to the search-market-view and launch it
+ List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+ for (int i = 0; i < items.size(); i++) {
+ AlphabeticalAppsList.AdapterItem item = items.get(i);
+ switch (item.viewType) {
+ case AllAppsGridAdapter.ICON_VIEW_TYPE:
+ case AllAppsGridAdapter.SEARCH_MARKET_VIEW_TYPE:
+ mAppsRecyclerView.getChildAt(i).performClick();
+ mInputMethodManager.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onBackKey() {
+ // Only hide the search field if there is no query, or if there
+ // are no filtered results
+ String query = Utilities.trim(mInput.getEditableText().toString());
+ if (query.isEmpty() || mApps.hasNoFilteredResults()) {
+ reset();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Resets the search bar state.
+ */
+ public void reset() {
+ unfocusSearchField();
+ mCb.clearSearchResult();
+ mInput.setText("");
+ mInputMethodManager.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
+ }
+
+ protected void unfocusSearchField() {
+ View nextFocus = mInput.focusSearch(View.FOCUS_DOWN);
+ if (nextFocus != null) {
+ nextFocus.requestFocus();
+ }
+ }
/**
* Returns the search bar view.
* @param parent the parent to attach the search bar view to.
*/
- public abstract View getView(ViewGroup parent);
+ public View getView(ViewGroup parent) {
+ return null;
+ }
/**
* Focuses the search field to handle key events.
*/
- public abstract void focusSearchField();
+ public void focusSearchField() {
+ mInput.requestFocus();
+ mInputMethodManager.showSoftInput(mInput, InputMethodManager.SHOW_IMPLICIT);
+ }
/**
* Returns whether the search field is focused.
*/
- public abstract boolean isSearchFieldFocused();
-
- /**
- * Resets the search bar state.
- */
- public abstract void reset();
+ public boolean isSearchFieldFocused() {
+ return mInput.isFocused();
+ }
/**
* Returns whether the prediction bar should currently be visible depending on the state of
* the search bar.
*/
- @Deprecated
- public abstract boolean shouldShowPredictionBar();
+ public boolean shouldShowPredictionBar() {
+ return false;
+ }
/**
* Callback for getting search results.
diff --git a/src/com/android/launcher3/allapps/DefaultAppSearchController.java b/src/com/android/launcher3/allapps/DefaultAppSearchController.java
index 3169f842a..57747e367 100644
--- a/src/com/android/launcher3/allapps/DefaultAppSearchController.java
+++ b/src/com/android/launcher3/allapps/DefaultAppSearchController.java
@@ -15,261 +15,12 @@
*/
package com.android.launcher3.allapps;
-import android.content.Context;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.TextView;
-import com.android.launcher3.ExtendedEditText;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.util.Thunk;
-
-import java.util.List;
-
-
/**
* The default search controller.
*/
-final class DefaultAppSearchController extends AllAppsSearchBarController
- implements TextWatcher, TextView.OnEditorActionListener, View.OnClickListener {
-
- private static final boolean ALLOW_SINGLE_APP_LAUNCH = true;
-
- private static final int FADE_IN_DURATION = 175;
- private static final int FADE_OUT_DURATION = 100;
- private static final int SEARCH_TRANSLATION_X_DP = 18;
-
- private final Context mContext;
- @Thunk final InputMethodManager mInputMethodManager;
-
- private DefaultAppSearchAlgorithm mSearchManager;
-
- private ViewGroup mContainerView;
- private View mSearchView;
- @Thunk View mSearchBarContainerView;
- private View mSearchButtonView;
- private View mDismissSearchButtonView;
- @Thunk
- ExtendedEditText mSearchBarEditView;
- @Thunk AllAppsRecyclerView mAppsRecyclerView;
- @Thunk Runnable mFocusRecyclerViewRunnable = new Runnable() {
- @Override
- public void run() {
- mAppsRecyclerView.requestFocus();
- }
- };
-
- public DefaultAppSearchController(Context context, ViewGroup containerView,
- AllAppsRecyclerView appsRecyclerView) {
- mContext = context;
- mInputMethodManager = (InputMethodManager)
- mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
- mContainerView = containerView;
- mAppsRecyclerView = appsRecyclerView;
- }
-
- @Override
- public View getView(ViewGroup parent) {
- LayoutInflater inflater = LayoutInflater.from(parent.getContext());
- mSearchView = inflater.inflate(R.layout.all_apps_search_bar, parent, false);
- mSearchView.setOnClickListener(this);
-
- mSearchButtonView = mSearchView.findViewById(R.id.search_button);
- mSearchBarContainerView = mSearchView.findViewById(R.id.search_container);
- mDismissSearchButtonView = mSearchBarContainerView.findViewById(R.id.dismiss_search_button);
- mDismissSearchButtonView.setOnClickListener(this);
- mSearchBarEditView = (ExtendedEditText)
- mSearchBarContainerView.findViewById(R.id.search_box_input);
- mSearchBarEditView.addTextChangedListener(this);
- mSearchBarEditView.setOnEditorActionListener(this);
- mSearchBarEditView.setOnBackKeyListener(
- new ExtendedEditText.OnBackKeyListener() {
- @Override
- public boolean onBackKey() {
- // Only hide the search field if there is no query, or if there
- // are no filtered results
- String query = Utilities.trim(
- mSearchBarEditView.getEditableText().toString());
- if (query.isEmpty() || mApps.hasNoFilteredResults()) {
- hideSearchField(true, mFocusRecyclerViewRunnable);
- return true;
- }
- return false;
- }
- });
- return mSearchView;
- }
-
- @Override
- public void focusSearchField() {
- mSearchBarEditView.requestFocus();
- showSearchField();
- }
-
- @Override
- public boolean isSearchFieldFocused() {
- return mSearchBarEditView.isFocused();
- }
-
- @Override
- protected void onInitialize() {
- mSearchManager = new DefaultAppSearchAlgorithm(mApps.getApps());
- }
-
- @Override
- public void reset() {
- hideSearchField(false, null);
- }
-
- @Override
- public boolean shouldShowPredictionBar() {
- return false;
- }
-
- @Override
- public void onClick(View v) {
- if (v == mSearchView) {
- showSearchField();
- } else if (v == mDismissSearchButtonView) {
- hideSearchField(true, mFocusRecyclerViewRunnable);
- }
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // Do nothing
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- // Do nothing
- }
-
- @Override
- public void afterTextChanged(final Editable s) {
- String query = s.toString();
- if (query.isEmpty()) {
- mSearchManager.cancel(true);
- mCb.clearSearchResult();
- } else {
- mSearchManager.cancel(false);
- mSearchManager.doSearch(query, mCb);
- }
- }
-
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- // Skip if we disallow app-launch-on-enter
- if (!ALLOW_SINGLE_APP_LAUNCH) {
- return false;
- }
- // Skip if it's not the right action
- if (actionId != EditorInfo.IME_ACTION_SEARCH) {
- return false;
- }
- // Skip if there are more than one icon
- if (mApps.getNumFilteredApps() > 1) {
- return false;
- }
- // Otherwise, find the first icon, or fallback to the search-market-view and launch it
- List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
- for (int i = 0; i < items.size(); i++) {
- AlphabeticalAppsList.AdapterItem item = items.get(i);
- switch (item.viewType) {
- case AllAppsGridAdapter.ICON_VIEW_TYPE:
- case AllAppsGridAdapter.SEARCH_MARKET_VIEW_TYPE:
- mAppsRecyclerView.getChildAt(i).performClick();
- mInputMethodManager.hideSoftInputFromWindow(
- mContainerView.getWindowToken(), 0);
- return true;
- }
- }
- return false;
- }
-
- /**
- * Focuses the search field.
- */
- private void showSearchField() {
- // Show the search bar and focus the search
- final int translationX = Utilities.pxFromDp(SEARCH_TRANSLATION_X_DP,
- mContext.getResources().getDisplayMetrics());
- mSearchBarContainerView.setVisibility(View.VISIBLE);
- mSearchBarContainerView.setAlpha(0f);
- mSearchBarContainerView.setTranslationX(translationX);
- mSearchBarContainerView.animate()
- .alpha(1f)
- .translationX(0)
- .setDuration(FADE_IN_DURATION)
- .withLayer()
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mSearchBarEditView.requestFocus();
- mInputMethodManager.showSoftInput(mSearchBarEditView,
- InputMethodManager.SHOW_IMPLICIT);
- }
- });
- mSearchButtonView.animate()
- .alpha(0f)
- .translationX(-translationX)
- .setDuration(FADE_OUT_DURATION)
- .withLayer();
- }
-
- /**
- * Unfocuses the search field.
- */
- @Thunk void hideSearchField(boolean animated, final Runnable postAnimationRunnable) {
- mSearchManager.cancel(true);
+public class DefaultAppSearchController extends AllAppsSearchBarController {
- final boolean resetTextField = mSearchBarEditView.getText().toString().length() > 0;
- final int translationX = Utilities.pxFromDp(SEARCH_TRANSLATION_X_DP,
- mContext.getResources().getDisplayMetrics());
- if (animated) {
- // Hide the search bar and focus the recycler view
- mSearchBarContainerView.animate()
- .alpha(0f)
- .translationX(0)
- .setDuration(FADE_IN_DURATION)
- .withLayer()
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mSearchBarContainerView.setVisibility(View.INVISIBLE);
- if (resetTextField) {
- mSearchBarEditView.setText("");
- }
- mCb.clearSearchResult();
- if (postAnimationRunnable != null) {
- postAnimationRunnable.run();
- }
- }
- });
- mSearchButtonView.setTranslationX(-translationX);
- mSearchButtonView.animate()
- .alpha(1f)
- .translationX(0)
- .setDuration(FADE_OUT_DURATION)
- .withLayer();
- } else {
- mSearchBarContainerView.setVisibility(View.INVISIBLE);
- if (resetTextField) {
- mSearchBarEditView.setText("");
- }
- mCb.clearSearchResult();
- mSearchButtonView.setAlpha(1f);
- mSearchButtonView.setTranslationX(0f);
- if (postAnimationRunnable != null) {
- postAnimationRunnable.run();
- }
- }
- mInputMethodManager.hideSoftInputFromWindow(mContainerView.getWindowToken(), 0);
+ public DefaultAppSearchAlgorithm onInitializeSearch() {
+ return new DefaultAppSearchAlgorithm(mApps.getApps());
}
}
diff --git a/src/com/android/launcher3/allapps/HeaderElevationController.java b/src/com/android/launcher3/allapps/HeaderElevationController.java
new file mode 100644
index 000000000..07f583caa
--- /dev/null
+++ b/src/com/android/launcher3/allapps/HeaderElevationController.java
@@ -0,0 +1,101 @@
+package com.android.launcher3.allapps;
+
+import android.annotation.TargetApi;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.graphics.drawable.GradientDrawable;
+import android.os.Build;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.R;
+
+/**
+ * Helper class for controlling the header elevation in response to RecyclerView scroll.
+ */
+public abstract class HeaderElevationController extends RecyclerView.OnScrollListener {
+
+ private int mCurrentY = 0;
+
+ public void reset() {
+ mCurrentY = 0;
+ onScroll(mCurrentY);
+ }
+
+ @Override
+ public final void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ mCurrentY += dy;
+ onScroll(mCurrentY);
+ }
+
+ public void updateBackgroundPadding(Rect bgPadding) { }
+
+ abstract void onScroll(int scrollY);
+
+ public static class ControllerV16 extends HeaderElevationController {
+
+ private final View mShadow;
+ private final float mScrollToElevation;
+
+ public ControllerV16(View header) {
+ Resources res = header.getContext().getResources();
+ mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
+
+ mShadow = new View(header.getContext());
+ mShadow.setBackground(new GradientDrawable(
+ GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x1E000000, 0x00000000}));
+ mShadow.setAlpha(0);
+
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ res.getDimensionPixelSize(R.dimen.all_apps_header_shadow_height));
+ lp.topMargin = ((FrameLayout.LayoutParams) header.getLayoutParams()).height;
+
+ ((ViewGroup) header.getParent()).addView(mShadow, lp);
+ }
+
+ @Override
+ public void onScroll(int scrollY) {
+ float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
+ mScrollToElevation;
+ mShadow.setAlpha(elevationPct);
+ }
+
+ @Override
+ public void updateBackgroundPadding(Rect bgPadding) {
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mShadow.getLayoutParams();
+ lp.leftMargin = bgPadding.left;
+ lp.rightMargin = bgPadding.right;
+ mShadow.requestLayout();
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public static class ControllerVL extends HeaderElevationController {
+
+ private final View mHeader;
+ private final float mMaxElevation;
+ private final float mScrollToElevation;
+
+ public ControllerVL(View header) {
+ mHeader = header;
+ mHeader.setOutlineProvider(ViewOutlineProvider.BOUNDS);
+
+ Resources res = header.getContext().getResources();
+ mMaxElevation = res.getDimension(R.dimen.all_apps_header_max_elevation);
+ mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
+ }
+
+ @Override
+ public void onScroll(int scrollY) {
+ float elevationPct = Math.min(scrollY, mScrollToElevation) / mScrollToElevation;
+ float newElevation = mMaxElevation * elevationPct;
+ if (Float.compare(mHeader.getElevation(), newElevation) != 0) {
+ mHeader.setElevation(newElevation);
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index b780f590b..8b9ac1f75 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -65,7 +65,6 @@ public class WidgetsContainerView extends BaseContainerView
private IconCache mIconCache;
/* Recycler view related member variables */
- private View mContent;
private WidgetsRecyclerView mView;
private WidgetsListAdapter mAdapter;
@@ -99,8 +98,7 @@ public class WidgetsContainerView extends BaseContainerView
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mContent = findViewById(R.id.content);
- mView = (WidgetsRecyclerView) findViewById(R.id.widgets_list_view);
+ mView = (WidgetsRecyclerView) getContentView();
mView.setAdapter(mAdapter);
// This extends the layout space so that preloading happen for the {@link RecyclerView}
@@ -120,15 +118,6 @@ public class WidgetsContainerView extends BaseContainerView
// Returns views used for launcher transitions.
//
- public View getContentView() {
- return mView;
- }
-
- public View getRevealView() {
- // TODO(hyunyoungs): temporarily use apps view transition.
- return findViewById(R.id.widgets_reveal_view);
- }
-
public void scrollToTop() {
mView.scrollToPosition(0);
}
@@ -338,21 +327,8 @@ public class WidgetsContainerView extends BaseContainerView
//
// Container rendering related.
//
-
@Override
- protected void onUpdateBackgroundAndPaddings(Rect searchBarBounds, Rect padding) {
- // Apply the top-bottom padding to the content itself so that the launcher transition is
- // clipped correctly
- mContent.setPadding(0, padding.top, 0, padding.bottom);
-
- // TODO: Use quantum_panel_dark instead of quantum_panel_shape_dark.
- InsetDrawable background = new InsetDrawable(
- getResources().getDrawable(R.drawable.quantum_panel_shape_dark), padding.left, 0,
- padding.right, 0);
- Rect bgPadding = new Rect();
- background.getPadding(bgPadding);
- mView.setBackground(background);
- getRevealView().setBackground(background.getConstantState().newDrawable());
+ protected void onUpdateBgPadding(Rect padding, Rect bgPadding) {
mView.updateBackgroundPadding(bgPadding);
}