summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/allapps
diff options
context:
space:
mode:
authorWinson Chung <winsonc@google.com>2015-07-06 17:14:51 -0700
committerWinson Chung <winsonc@google.com>2015-07-06 17:46:32 -0700
commit1ae7a5018b48dba562bc18821f0f1e778192ee85 (patch)
tree8f1cf80dccd6fd709141fa0d8027f2d897ff306f /src/com/android/launcher3/allapps
parent1406fd80d59351e13b7be7f0997494761ffe7508 (diff)
downloadandroid_packages_apps_Trebuchet-1ae7a5018b48dba562bc18821f0f1e778192ee85.tar.gz
android_packages_apps_Trebuchet-1ae7a5018b48dba562bc18821f0f1e778192ee85.tar.bz2
android_packages_apps_Trebuchet-1ae7a5018b48dba562bc18821f0f1e778192ee85.zip
Moving prediction icons back into recycler view.
- Fixes two accessibility issues with the prediction bar being separate from the rest of the list of icons related to scrolling and switch access. Bug: 21725276 Change-Id: Ibc48e5028cace9a77000e6646b951f021910465d
Diffstat (limited to 'src/com/android/launcher3/allapps')
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java251
-rw-r--r--src/com/android/launcher3/allapps/AllAppsGridAdapter.java91
-rw-r--r--src/com/android/launcher3/allapps/AllAppsRecyclerView.java49
-rw-r--r--src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java37
-rw-r--r--src/com/android/launcher3/allapps/AllAppsSearchBarController.java1
-rw-r--r--src/com/android/launcher3/allapps/AlphabeticalAppsList.java70
-rw-r--r--src/com/android/launcher3/allapps/DefaultAppSearchController.java3
7 files changed, 95 insertions, 407 deletions
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 0651fb02e..47bbf1513 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -75,7 +75,11 @@ final class FullMergeAlgorithm implements AlphabeticalAppsList.MergeAlgorithm {
public boolean continueMerging(AlphabeticalAppsList.SectionInfo section,
AlphabeticalAppsList.SectionInfo withSection,
int sectionAppCount, int numAppsPerRow, int mergeCount) {
- // Merge EVERYTHING
+ // Don't merge the predicted apps
+ if (section.firstAppItem.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ return false;
+ }
+ // Otherwise, merge every other section
return true;
}
}
@@ -103,6 +107,11 @@ final class SimpleSectionMergeAlgorithm implements AlphabeticalAppsList.MergeAlg
public boolean continueMerging(AlphabeticalAppsList.SectionInfo section,
AlphabeticalAppsList.SectionInfo withSection,
int sectionAppCount, int numAppsPerRow, int mergeCount) {
+ // Don't merge the predicted apps
+ if (section.firstAppItem.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ return false;
+ }
+
// Continue merging if the number of hanging apps on the final row is less than some
// fixed number (ragged), the merged rows has yet to exceed some minimum row count,
// and while the number of merged sections is less than some fixed number of merges
@@ -127,17 +136,14 @@ final class SimpleSectionMergeAlgorithm implements AlphabeticalAppsList.MergeAlg
* The all apps view container.
*/
public class AllAppsContainerView extends BaseContainerView implements DragSource,
- LauncherTransitionable, AlphabeticalAppsList.AdapterChangedCallback,
- AllAppsGridAdapter.PredictionBarSpacerCallbacks, View.OnTouchListener,
- View.OnLongClickListener, ViewTreeObserver.OnPreDrawListener,
- AllAppsSearchBarController.Callbacks, Stats.LaunchSourceProvider {
+ LauncherTransitionable, View.OnTouchListener, View.OnLongClickListener,
+ AllAppsSearchBarController.Callbacks {
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 LayoutInflater mLayoutInflater;
private AllAppsGridAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private RecyclerView.ItemDecoration mItemDecoration;
@@ -146,7 +152,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
@Thunk View mContainerView;
@Thunk View mRevealView;
@Thunk AllAppsRecyclerView mAppsRecyclerView;
- @Thunk ViewGroup mPredictionBarView;
@Thunk AllAppsSearchBarController mSearchBarController;
private ViewGroup mSearchBarContainerView;
private View mSearchBarView;
@@ -159,18 +164,9 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
private final Point mBoundsCheckLastTouchDownPos = new Point(-1, -1);
// This coordinate is relative to its parent
private final Point mIconLastTouchPos = new Point();
- // This coordinate is used to proxy click and long-click events to the prediction bar icons
- private final Point mPredictionIconTouchDownPos = new Point();
- // Normal container insets
- private int mPredictionBarHeight;
- private int mLastRecyclerViewScrollPos = -1;
- @Thunk boolean mFocusPredictionBarOnFirstBind;
private SpannableStringBuilder mSearchQueryBuilder = null;
- private CheckLongPressHelper mPredictionIconCheckForLongPress;
- private View mPredictionIconUnderTouch;
-
public AllAppsContainerView(Context context) {
this(context, null);
}
@@ -184,19 +180,10 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
Resources res = context.getResources();
mLauncher = (Launcher) context;
- mLayoutInflater = LayoutInflater.from(context);
- DeviceProfile grid = mLauncher.getDeviceProfile();
- mPredictionBarHeight = (int) (grid.allAppsIconSizePx + grid.iconDrawablePaddingOriginalPx +
- Utilities.calculateTextHeight(grid.allAppsIconTextSizePx) +
- 2 * res.getDimensionPixelSize(R.dimen.all_apps_icon_top_bottom_padding) +
- res.getDimensionPixelSize(R.dimen.all_apps_prediction_bar_top_padding) +
- res.getDimensionPixelSize(R.dimen.all_apps_prediction_bar_bottom_padding));
mSectionNamesMargin = res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
mApps = new AlphabeticalAppsList(context);
- mApps.setAdapterChangedCallback(this);
- mAdapter = new AllAppsGridAdapter(context, mApps, this, this, mLauncher, this);
+ mAdapter = new AllAppsGridAdapter(context, mApps, this, mLauncher, this);
mAdapter.setEmptySearchText(res.getString(R.string.all_apps_loading_message));
- mAdapter.setPredictionRowHeight(mPredictionBarHeight);
mApps.setAdapter(mAdapter);
mLayoutManager = mAdapter.getLayoutManager();
mItemDecoration = mAdapter.getItemDecoration();
@@ -310,17 +297,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
- if (!mApps.getPredictedApps().isEmpty()) {
- // If the prediction bar is going to be bound, then defer focusing until
- // it is first bound
- if (mPredictionBarView.getChildCount() == 0) {
- mFocusPredictionBarOnFirstBind = true;
- } else {
- mPredictionBarView.requestFocus();
- }
- } else {
- mAppsRecyclerView.requestFocus();
- }
+ mAppsRecyclerView.requestFocus();
}
}
};
@@ -333,7 +310,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
// Load the all apps recycler view
mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view);
mAppsRecyclerView.setApps(mApps);
- mAppsRecyclerView.setPredictionBarHeight(mPredictionBarHeight);
mAppsRecyclerView.setLayoutManager(mLayoutManager);
mAppsRecyclerView.setAdapter(mAdapter);
mAppsRecyclerView.setHasFixedSize(true);
@@ -341,11 +317,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
mAppsRecyclerView.addItemDecoration(mItemDecoration);
}
- // Fix the prediction bar height
- mPredictionBarView = (ViewGroup) findViewById(R.id.prediction_bar);
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mPredictionBarView.getLayoutParams();
- lp.height = mPredictionBarHeight;
-
updateBackgroundAndPaddings();
}
@@ -355,49 +326,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
}
@Override
- public void onBindPredictionBar() {
- updatePredictionBarVisibility();
-
- List<AppInfo> predictedApps = mApps.getPredictedApps();
-
- // Remove extra prediction icons
- while (mPredictionBarView.getChildCount() > mNumPredictedAppsPerRow) {
- mPredictionBarView.removeViewAt(mPredictionBarView.getChildCount() - 1);
- }
-
- int childCount = mPredictionBarView.getChildCount();
- for (int i = 0; i < mNumPredictedAppsPerRow; i++) {
- BubbleTextView icon;
- if (i < childCount) {
- // If a child at that index exists, then get that child
- icon = (BubbleTextView) mPredictionBarView.getChildAt(i);
- } else {
- // Otherwise, inflate a new icon
- icon = (BubbleTextView) mLayoutInflater.inflate(
- R.layout.all_apps_prediction_bar_icon, mPredictionBarView, false);
- icon.setFocusable(true);
- icon.setLongPressTimeout(ViewConfiguration.get(getContext()).getLongPressTimeout());
- mPredictionBarView.addView(icon);
- }
-
- // Either apply the app info to the child, or hide the view
- if (i < predictedApps.size()) {
- if (icon.getVisibility() != View.VISIBLE) {
- icon.setVisibility(View.VISIBLE);
- }
- icon.applyFromApplicationInfo(predictedApps.get(i));
- } else {
- icon.setVisibility(View.INVISIBLE);
- }
- }
-
- if (mFocusPredictionBarOnFirstBind) {
- mFocusPredictionBarOnFirstBind = false;
- mPredictionBarView.requestFocus();
- }
- }
-
- @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() :
@@ -476,22 +404,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
lp.rightMargin = (getMeasuredWidth() - searchBarBounds.right) - backgroundPadding.right;
mSearchBarContainerView.requestLayout();
}
-
- // Update the prediction bar insets as well
- mPredictionBarView = (ViewGroup) findViewById(R.id.prediction_bar);
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mPredictionBarView.getLayoutParams();
- lp.leftMargin = padding.left + mAppsRecyclerView.getMaxScrollbarWidth();
- lp.rightMargin = padding.right + mAppsRecyclerView.getMaxScrollbarWidth();
- mPredictionBarView.requestLayout();
- }
-
- @Override
- public boolean onPreDraw() {
- if (mNumAppsPerRow > 0) {
- // Update the position of the prediction bar to match the scroll of the all apps list
- synchronizeToRecyclerViewScrollPosition(mAppsRecyclerView.getScrollPosition());
- }
- return true;
}
@Override
@@ -621,17 +533,8 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
}
@Override
- public void onAdapterItemsChanged() {
- updatePredictionBarVisibility();
- }
-
- @Override
public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
- // Register for a pre-draw listener to synchronize the recycler view scroll to other views
- // in this container
- if (!toWorkspace) {
- getViewTreeObserver().addOnPreDrawListener(this);
- }
+ // Do nothing
}
@Override
@@ -647,38 +550,12 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
@Override
public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
if (toWorkspace) {
- getViewTreeObserver().removeOnPreDrawListener(this);
- mLastRecyclerViewScrollPos = -1;
-
// Reset the search bar after transitioning home
mSearchBarController.reset();
}
}
/**
- * Updates the container when the recycler view is scrolled.
- */
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void synchronizeToRecyclerViewScrollPosition(int scrollY) {
- if (mLastRecyclerViewScrollPos != scrollY) {
- mLastRecyclerViewScrollPos = scrollY;
-
- // Scroll the prediction bar with the contents of the recycler view
- mPredictionBarView.setTranslationY(-scrollY + mAppsRecyclerView.getPaddingTop());
- }
- }
-
- @Override
- public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
- // If we were waiting for long-click, cancel the request once a child has started handling
- // the scrolling
- if (mPredictionIconCheckForLongPress != null) {
- mPredictionIconCheckForLongPress.cancelLongPress();
- }
- super.requestDisallowInterceptTouchEvent(disallowIntercept);
- }
-
- /**
* Handles the touch events to dismiss all apps when clicking outside the bounds of the
* recycler view.
*/
@@ -689,19 +566,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
- // We workaround the fact that the recycler view needs the touches for the scroll
- // and we want to intercept it for clicks in the prediction bar by handling clicks
- // and long clicks in the prediction bar ourselves.
- if (mPredictionBarView != null && mPredictionBarView.getVisibility() == View.VISIBLE) {
- mPredictionIconTouchDownPos.set(x, y);
- mPredictionIconUnderTouch = findPredictedAppAtCoordinate(x, y);
- if (mPredictionIconUnderTouch != null) {
- mPredictionIconCheckForLongPress =
- new CheckLongPressHelper(mPredictionIconUnderTouch, this);
- mPredictionIconCheckForLongPress.postCheckForLongPress();
- }
- }
-
if (!mContentBounds.isEmpty()) {
// Outset the fixed bounds and check if the touch is outside all apps
Rect tmpRect = new Rect(mContentBounds);
@@ -719,19 +583,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
}
}
break;
- case MotionEvent.ACTION_MOVE:
- if (mPredictionIconUnderTouch != null) {
- float dist = (float) Math.hypot(x - mPredictionIconTouchDownPos.x,
- y - mPredictionIconTouchDownPos.y);
- if (dist > ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
- if (mPredictionIconCheckForLongPress != null) {
- mPredictionIconCheckForLongPress.cancelLongPress();
- }
- mPredictionIconCheckForLongPress = null;
- mPredictionIconUnderTouch = null;
- }
- }
- break;
case MotionEvent.ACTION_UP:
if (mBoundsCheckLastTouchDownPos.x > -1) {
ViewConfiguration viewConfig = ViewConfiguration.get(getContext());
@@ -745,26 +596,9 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
return true;
}
}
-
- // Trigger the click on the prediction bar icon if that's where we touched
- if (mPredictionIconUnderTouch != null &&
- !mPredictionIconCheckForLongPress.hasPerformedLongPress()) {
- mLauncher.onClick(mPredictionIconUnderTouch);
- }
-
// Fall through
case MotionEvent.ACTION_CANCEL:
mBoundsCheckLastTouchDownPos.set(-1, -1);
- mPredictionIconTouchDownPos.set(-1, -1);
-
- // On touch up/cancel, cancel the long press on the prediction bar icon if it has
- // not yet been performed
- if (mPredictionIconCheckForLongPress != null) {
- mPredictionIconCheckForLongPress.cancelLongPress();
- mPredictionIconCheckForLongPress = null;
- }
- mPredictionIconUnderTouch = null;
-
break;
}
return false;
@@ -792,59 +626,4 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
mSearchQueryBuilder.clearSpans();
Selection.setSelection(mSearchQueryBuilder, 0);
}
-
- @Override
- public void fillInLaunchSourceData(Bundle sourceData) {
- // Since the other cases are caught by the AllAppsRecyclerView LaunchSourceProvider, we just
- // handle the prediction bar icons here
- sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_ALL_APPS);
- sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER,
- Stats.SUB_CONTAINER_ALL_APPS_PREDICTION);
- }
-
- /**
- * Returns the predicted app in the prediction bar given a set of local coordinates.
- */
- private View findPredictedAppAtCoordinate(int x, int y) {
- Rect hitRect = new Rect();
-
- // Ensure that are touching in the recycler view
- int[] coord = {x, y};
- Utilities.mapCoordInSelfToDescendent(mAppsRecyclerView, this, coord);
- mAppsRecyclerView.getHitRect(hitRect);
- if (!hitRect.contains(coord[0], coord[1])) {
- return null;
- }
-
- // Check against the children of the prediction bar
- coord[0] = x;
- coord[1] = y;
- Utilities.mapCoordInSelfToDescendent(mPredictionBarView, this, coord);
- for (int i = 0; i < mPredictionBarView.getChildCount(); i++) {
- View child = mPredictionBarView.getChildAt(i);
- if (child.getVisibility() != View.VISIBLE) {
- continue;
- }
- child.getHitRect(hitRect);
- if (hitRect.contains(coord[0], coord[1])) {
- return child;
- }
- }
- return null;
- }
-
- /**
- * Updates the visibility of the prediction bar.
- * @return whether the prediction bar is visible
- */
- private boolean updatePredictionBarVisibility() {
- boolean showPredictionBar = !mApps.getPredictedApps().isEmpty() &&
- (!mApps.hasFilter() || mSearchBarController.shouldShowPredictionBar());
- if (showPredictionBar) {
- mPredictionBarView.setVisibility(View.VISIBLE);
- } else if (!showPredictionBar) {
- mPredictionBarView.setVisibility(View.INVISIBLE);
- }
- return showPredictionBar;
- }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 19e2757f9..057883cab 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -31,7 +31,6 @@ import android.view.ViewGroup;
import android.widget.TextView;
import com.android.launcher3.AppInfo;
import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Thunk;
@@ -52,17 +51,10 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
public static final int SECTION_BREAK_VIEW_TYPE = 0;
// A normal icon
public static final int ICON_VIEW_TYPE = 1;
+ // A prediction icon
+ public static final int PREDICTION_ICON_VIEW_TYPE = 2;
// The message shown when there are no filtered results
- public static final int EMPTY_SEARCH_VIEW_TYPE = 2;
- // The spacer used for the prediction bar
- public static final int PREDICTION_BAR_SPACER_TYPE = 3;
-
- /**
- * Callback for when the prediction bar spacer is bound.
- */
- public interface PredictionBarSpacerCallbacks {
- void onBindPredictionBar();
- }
+ public static final int EMPTY_SEARCH_VIEW_TYPE = 3;
/**
* ViewHolder for each icon.
@@ -93,11 +85,13 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
return mAppsPerRow;
}
- if (mApps.getAdapterItems().get(position).viewType != AllAppsGridAdapter.ICON_VIEW_TYPE) {
- // Both the section breaks and predictive bar span the full width
- return mAppsPerRow;
- } else {
- return 1;
+ switch (mApps.getAdapterItems().get(position).viewType) {
+ case AllAppsGridAdapter.ICON_VIEW_TYPE:
+ case AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE:
+ return 1;
+ default:
+ // Section breaks span the full width
+ return mAppsPerRow;
}
}
}
@@ -141,7 +135,7 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
if (shouldDrawItemDivider(holder, items) && !hasDrawnPredictedAppsDivider) {
// Draw the divider under the predicted apps
- int top = child.getTop() + child.getHeight() - mPredictionBarBottomPadding / 2;
+ int top = child.getTop() + child.getHeight() + mPredictionBarDividerOffset;
c.drawLine(mBackgroundPadding.left, top,
parent.getWidth() - mBackgroundPadding.right, top,
mPredictedAppsDividerPaint);
@@ -264,7 +258,7 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
private boolean shouldDrawItemDivider(ViewHolder holder,
List<AlphabeticalAppsList.AdapterItem> items) {
int pos = holder.getPosition();
- return items.get(pos).viewType == AllAppsGridAdapter.PREDICTION_BAR_SPACER_TYPE;
+ return items.get(pos).viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE;
}
/**
@@ -285,19 +279,16 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
}
}
- private Handler mHandler;
private LayoutInflater mLayoutInflater;
@Thunk AlphabeticalAppsList mApps;
private GridLayoutManager mGridLayoutMgr;
private GridSpanSizer mGridSizer;
private GridItemDecoration mItemDecoration;
- @Thunk PredictionBarSpacerCallbacks mPredictionBarCb;
private View.OnTouchListener mTouchListener;
private View.OnClickListener mIconClickListener;
private View.OnLongClickListener mIconLongClickListener;
@Thunk final Rect mBackgroundPadding = new Rect();
- @Thunk int mPredictionBarHeight;
- @Thunk int mPredictionBarBottomPadding;
+ @Thunk int mPredictionBarDividerOffset;
@Thunk int mAppsPerRow;
@Thunk boolean mIsRtl;
private String mEmptySearchText;
@@ -309,12 +300,10 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
@Thunk Paint mPredictedAppsDividerPaint;
public AllAppsGridAdapter(Context context, AlphabeticalAppsList apps,
- PredictionBarSpacerCallbacks pbCb, View.OnTouchListener touchListener,
- View.OnClickListener iconClickListener, View.OnLongClickListener iconLongClickListener) {
+ View.OnTouchListener touchListener, View.OnClickListener iconClickListener,
+ View.OnLongClickListener iconLongClickListener) {
Resources res = context.getResources();
- mHandler = new Handler();
mApps = apps;
- mPredictionBarCb = pbCb;
mGridSizer = new GridSpanSizer();
mGridLayoutMgr = new GridLayoutManager(context, 1, GridLayoutManager.VERTICAL, false);
mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
@@ -336,8 +325,9 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
mPredictedAppsDividerPaint.setStrokeWidth(Utilities.pxFromDp(1f, res.getDisplayMetrics()));
mPredictedAppsDividerPaint.setColor(0x1E000000);
mPredictedAppsDividerPaint.setAntiAlias(true);
- mPredictionBarBottomPadding =
- res.getDimensionPixelSize(R.dimen.all_apps_prediction_bar_bottom_padding);
+ mPredictionBarDividerOffset =
+ (-res.getDimensionPixelSize(R.dimen.all_apps_prediction_icon_bottom_padding) +
+ res.getDimensionPixelSize(R.dimen.all_apps_icon_top_bottom_padding)) / 2;
}
/**
@@ -349,13 +339,6 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
}
/**
- * Sets the prediction row height.
- */
- public void setPredictionRowHeight(int height) {
- mPredictionBarHeight = height;
- }
-
- /**
* Sets whether we are in RTL mode.
*/
public void setRtl(boolean rtl) {
@@ -400,14 +383,7 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
false));
case SECTION_BREAK_VIEW_TYPE:
return new ViewHolder(new View(parent.getContext()));
- case PREDICTION_BAR_SPACER_TYPE:
- // Create a view of a specific height to match the floating prediction bar
- View v = new View(parent.getContext());
- ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, mPredictionBarHeight);
- v.setLayoutParams(lp);
- return new ViewHolder(v);
- case ICON_VIEW_TYPE:
+ case ICON_VIEW_TYPE: {
BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
R.layout.all_apps_icon, parent, false);
icon.setOnTouchListener(mTouchListener);
@@ -417,6 +393,18 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
.getLongPressTimeout());
icon.setFocusable(true);
return new ViewHolder(icon);
+ }
+ case PREDICTION_ICON_VIEW_TYPE: {
+ BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
+ R.layout.all_apps_prediction_bar_icon, parent, false);
+ icon.setOnTouchListener(mTouchListener);
+ icon.setOnClickListener(mIconClickListener);
+ icon.setOnLongClickListener(mIconLongClickListener);
+ icon.setLongPressTimeout(ViewConfiguration.get(parent.getContext())
+ .getLongPressTimeout());
+ icon.setFocusable(true);
+ return new ViewHolder(icon);
+ }
default:
throw new RuntimeException("Unexpected view type");
}
@@ -425,21 +413,18 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
- case ICON_VIEW_TYPE:
+ case ICON_VIEW_TYPE: {
AppInfo info = mApps.getAdapterItems().get(position).appInfo;
BubbleTextView icon = (BubbleTextView) holder.mContent;
icon.applyFromApplicationInfo(info);
break;
- case PREDICTION_BAR_SPACER_TYPE:
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (mPredictionBarCb != null) {
- mPredictionBarCb.onBindPredictionBar();
- }
- }
- });
+ }
+ case PREDICTION_ICON_VIEW_TYPE: {
+ AppInfo info = mApps.getAdapterItems().get(position).appInfo;
+ BubbleTextView icon = (BubbleTextView) holder.mContent;
+ icon.applyFromApplicationInfo(info);
break;
+ }
case EMPTY_SEARCH_VIEW_TYPE:
TextView emptyViewText = (TextView) holder.mContent.findViewById(R.id.empty_text);
emptyViewText.setText(mEmptySearchText);
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 988ecdda3..730c8d15a 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -27,6 +27,7 @@ import com.android.launcher3.BaseRecyclerView;
import com.android.launcher3.BaseRecyclerViewFastScrollBar;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Stats;
+import com.android.launcher3.Utilities;
import com.android.launcher3.util.Thunk;
import java.util.List;
@@ -45,7 +46,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView
private AlphabeticalAppsList mApps;
private int mNumAppsPerRow;
- private int mPredictionBarHeight;
@Thunk BaseRecyclerViewFastScrollBar.FastScrollFocusableView mLastFastScrollFocusedView;
@Thunk int mPrevFastScrollFocusedPosition;
@@ -89,20 +89,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView
RecyclerView.RecycledViewPool pool = getRecycledViewPool();
int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
- pool.setMaxRecycledViews(AllAppsGridAdapter.PREDICTION_BAR_SPACER_TYPE, 1);
pool.setMaxRecycledViews(AllAppsGridAdapter.EMPTY_SEARCH_VIEW_TYPE, 1);
pool.setMaxRecycledViews(AllAppsGridAdapter.ICON_VIEW_TYPE, approxRows * mNumAppsPerRow);
+ pool.setMaxRecycledViews(AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE, mNumAppsPerRow);
pool.setMaxRecycledViews(AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE, approxRows);
}
/**
- * Sets the prediction bar height.
- */
- public void setPredictionBarHeight(int height) {
- mPredictionBarHeight = height;
- }
-
- /**
* Scrolls this recycler view to the top.
*/
public void scrollToTop() {
@@ -110,21 +103,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView
}
/**
- * Returns the current scroll position.
- */
- public int getScrollPosition() {
- List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
- getCurScrollState(mScrollPosState, items);
- if (mScrollPosState.rowIndex != -1) {
- int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- return getPaddingTop() + predictionBarHeight +
- (mScrollPosState.rowIndex * mScrollPosState.rowHeight) -
- mScrollPosState.rowTopOffset;
- }
- return 0;
- }
-
- /**
* We need to override the draw to ensure that we don't draw the overscroll effect beyond the
* background bounds.
*/
@@ -189,9 +167,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView
// Map the touch position back to the scroll of the recycler view
getCurScrollState(mScrollPosState, mApps.getAdapterItems());
- int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight,
- predictionBarHeight);
+ int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight, 0);
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
if (mFastScrollMode == FAST_SCROLL_MODE_FREE_SCROLL) {
layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction));
@@ -255,8 +231,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView
return;
}
- int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- synchronizeScrollBarThumbOffsetToViewScroll(mScrollPosState, rowCount, predictionBarHeight);
+ synchronizeScrollBarThumbOffsetToViewScroll(mScrollPosState, rowCount, 0);
}
/**
@@ -293,8 +268,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView
// Calculate the full animation from the current scroll position to the final scroll
// position, and then run the animation for the duration.
- int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- int curScrollY = getPaddingTop() + predictionBarHeight +
+ int curScrollY = getPaddingTop() +
(scrollPosState.rowIndex * scrollPosState.rowHeight) - scrollPosState.rowTopOffset;
int newScrollY = getScrollAtPosition(position, scrollPosState.rowHeight);
int numFrames = mFastScrollFrames.length;
@@ -307,8 +281,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView
}
/**
- * Returns the current scroll state of the apps rows, not including the prediction
- * bar.
+ * Returns the current scroll state of the apps rows.
*/
private void getCurScrollState(ScrollPositionState stateOut,
List<AlphabeticalAppsList.AdapterItem> items) {
@@ -327,7 +300,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView
int position = getChildPosition(child);
if (position != NO_POSITION) {
AlphabeticalAppsList.AdapterItem item = items.get(position);
- if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE ||
+ item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
stateOut.rowIndex = item.rowIndex;
stateOut.rowTopOffset = getLayoutManager().getDecoratedTop(child);
stateOut.rowHeight = child.getHeight();
@@ -342,9 +316,10 @@ public class AllAppsRecyclerView extends BaseRecyclerView
*/
private int getScrollAtPosition(int position, int rowHeight) {
AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position);
- if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE) {
- int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- return getPaddingTop() + predictionBarHeight + item.rowIndex * rowHeight;
+ if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE ||
+ item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
+ int offset = item.rowIndex > 0 ? getPaddingTop() : 0;
+ return offset + item.rowIndex * rowHeight;
} else {
return 0;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java
index 1c51ab763..14e2a1863 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java
@@ -37,7 +37,6 @@ public class AllAppsRecyclerViewContainerView extends FrameLayout
implements BubbleTextShadowHandler {
private final ClickShadowView mTouchFeedbackView;
- private View mPredictionBarView;
public AllAppsRecyclerViewContainerView(Context context) {
this(context, null);
@@ -61,13 +60,6 @@ public class AllAppsRecyclerViewContainerView extends FrameLayout
}
@Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mPredictionBarView = findViewById(R.id.prediction_bar);
- }
-
- @Override
public void setPressedIcon(BubbleTextView icon, Bitmap background) {
if (icon == null || background == null) {
mTouchFeedbackView.setBitmap(null);
@@ -77,33 +69,4 @@ public class AllAppsRecyclerViewContainerView extends FrameLayout
mTouchFeedbackView.animateShadow();
}
}
-
- /**
- * This allows us to have custom drawing order, while keeping touch handling in correct z-order.
- */
- @Override
- protected void dispatchDraw(Canvas canvas) {
- final long drawingTime = getDrawingTime();
-
- // Draw the click feedback first (since it is always on the bottom)
- if (mTouchFeedbackView != null && mTouchFeedbackView.getVisibility() == View.VISIBLE) {
- drawChild(canvas, mTouchFeedbackView, drawingTime);
- }
-
- // Then draw the prediction bar, since it needs to be "under" the recycler view to get the
- // right edge effect to be drawn over it
- if (mPredictionBarView != null && mPredictionBarView.getVisibility() == View.VISIBLE) {
- drawChild(canvas, mPredictionBarView, drawingTime);
- }
-
- // Draw the remaining views
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View v = getChildAt(i);
- if (v != mTouchFeedbackView && v != mPredictionBarView &&
- v.getVisibility() == View.VISIBLE) {
- drawChild(canvas, v, drawingTime);
- }
- }
- }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
index 341539cdd..2b363c0cb 100644
--- a/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
@@ -72,6 +72,7 @@ public abstract class AllAppsSearchBarController {
* Returns whether the prediction bar should currently be visible depending on the state of
* the search bar.
*/
+ @Deprecated
public abstract boolean shouldShowPredictionBar();
/**
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index ea99872ed..47241ce5d 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -110,10 +110,10 @@ public class AlphabeticalAppsList {
return item;
}
- public static AdapterItem asPredictionBarSpacer(int pos) {
- AdapterItem item = new AdapterItem();
- item.viewType = AllAppsGridAdapter.PREDICTION_BAR_SPACER_TYPE;
- item.position = pos;
+ public static AdapterItem asPredictedApp(int pos, SectionInfo section, String sectionName,
+ int sectionAppIndex, AppInfo appInfo, int appIndex) {
+ AdapterItem item = asApp(pos, section, sectionName, sectionAppIndex, appInfo, appIndex);
+ item.viewType = AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE;
return item;
}
@@ -132,13 +132,6 @@ public class AlphabeticalAppsList {
}
/**
- * Callback to notify when the set of adapter items have changed.
- */
- public interface AdapterChangedCallback {
- void onAdapterItemsChanged();
- }
-
- /**
* Common interface for different merging strategies.
*/
public interface MergeAlgorithm {
@@ -171,7 +164,6 @@ public class AlphabeticalAppsList {
private AlphabeticIndexCompat mIndexer;
private AppNameComparator mAppNameComparator;
private MergeAlgorithm mMergeAlgorithm;
- private AdapterChangedCallback mAdapterChangedCallback;
private int mNumAppsPerRow;
private int mNumPredictedAppsPerRow;
private int mNumAppRowsInAdapter;
@@ -183,13 +175,6 @@ public class AlphabeticalAppsList {
}
/**
- * Sets the apps updated callback.
- */
- public void setAdapterChangedCallback(AdapterChangedCallback cb) {
- mAdapterChangedCallback = cb;
- }
-
- /**
* Sets the number of apps per row.
*/
public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow,
@@ -285,13 +270,6 @@ public class AlphabeticalAppsList {
}
/**
- * Returns the current set of predicted apps.
- */
- public List<AppInfo> getPredictedApps() {
- return mPredictedApps;
- }
-
- /**
* Sets the current set of apps.
*/
public void setApps(List<AppInfo> apps) {
@@ -426,13 +404,25 @@ public class AlphabeticalAppsList {
}
if (!mPredictedApps.isEmpty()) {
- // Create a new spacer for the prediction bar
- AdapterItem sectionItem = AdapterItem.asPredictionBarSpacer(position++);
- mAdapterItems.add(sectionItem);
- // Add a fastscroller section for the prediction bar
+ // Add a section for the predictions
+ lastSectionInfo = new SectionInfo();
lastFastScrollerSectionInfo = new FastScrollSectionInfo("");
- lastFastScrollerSectionInfo.fastScrollToItem = sectionItem;
+ AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
+ mSections.add(lastSectionInfo);
mFastScrollerSections.add(lastFastScrollerSectionInfo);
+ mAdapterItems.add(sectionItem);
+
+ // Add the predicted app items
+ for (AppInfo info : mPredictedApps) {
+ AdapterItem appItem = AdapterItem.asPredictedApp(position++, lastSectionInfo,
+ "", lastSectionInfo.numApps++, info, appIndex++);
+ if (lastSectionInfo.firstAppItem == null) {
+ lastSectionInfo.firstAppItem = appItem;
+ lastFastScrollerSectionInfo.fastScrollToItem = appItem;
+ }
+ mAdapterItems.add(appItem);
+ mFilteredApps.add(info);
+ }
}
}
@@ -480,7 +470,8 @@ public class AlphabeticalAppsList {
item.rowIndex = 0;
if (item.viewType == AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE) {
numAppsInSection = 0;
- } else if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ } else if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE ||
+ item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
if (numAppsInSection % mNumAppsPerRow == 0) {
numAppsInRow = 0;
rowIndex++;
@@ -493,19 +484,18 @@ public class AlphabeticalAppsList {
}
mNumAppRowsInAdapter = rowIndex + 1;
- // Pre-calculate all the fast scroller fractions based on the number of rows, if we have
- // predicted apps, then we should account for that as a row in the touchFraction
- float rowFraction = 1f / (mNumAppRowsInAdapter + (mPredictedApps.isEmpty() ? 0 : 1));
- float initialOffset = mPredictedApps.isEmpty() ? 0 : rowFraction;
+ // Pre-calculate all the fast scroller fractions based on the number of rows
+ float rowFraction = 1f / mNumAppRowsInAdapter;
for (FastScrollSectionInfo info : mFastScrollerSections) {
AdapterItem item = info.fastScrollToItem;
- if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE &&
+ item.viewType != AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
info.touchFraction = 0f;
continue;
}
float subRowFraction = item.rowAppIndex * (rowFraction / mNumAppsPerRow);
- info.touchFraction = initialOffset + item.rowIndex * rowFraction + subRowFraction;
+ info.touchFraction = item.rowIndex * rowFraction + subRowFraction;
}
}
@@ -513,10 +503,6 @@ public class AlphabeticalAppsList {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
-
- if (mAdapterChangedCallback != null) {
- mAdapterChangedCallback.onAdapterItemsChanged();
- }
}
private List<AppInfo> getFiltersAppInfos() {
diff --git a/src/com/android/launcher3/allapps/DefaultAppSearchController.java b/src/com/android/launcher3/allapps/DefaultAppSearchController.java
index 20924af94..83b920589 100644
--- a/src/com/android/launcher3/allapps/DefaultAppSearchController.java
+++ b/src/com/android/launcher3/allapps/DefaultAppSearchController.java
@@ -125,8 +125,7 @@ final class DefaultAppSearchController extends AllAppsSearchBarController
@Override
public boolean shouldShowPredictionBar() {
- // Keep showing the prediction bar if the input query is empty
- return mSearchBarEditView.getEditableText().toString().isEmpty();
+ return false;
}
@Override