diff options
Diffstat (limited to 'src/com/android')
15 files changed, 216 insertions, 452 deletions
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java index 20c9314c9..99a98ddac 100644 --- a/src/com/android/launcher3/AutoInstallsLayout.java +++ b/src/com/android/launcher3/AutoInstallsLayout.java @@ -580,6 +580,7 @@ public class AutoInstallsLayout { int type; int folderDepth = parser.getDepth(); + int rank = 0; while ((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > folderDepth) { if (type != XmlPullParser.START_TAG) { @@ -587,12 +588,14 @@ public class AutoInstallsLayout { } mValues.clear(); mValues.put(Favorites.CONTAINER, folderId); + mValues.put(Favorites.RANK, rank); TagParser tagParser = mFolderElements.get(parser.getName()); if (tagParser != null) { final long id = tagParser.parseAndAdd(parser); if (id >= 0) { folderItems.add(id); + rank++; } } else { throw new RuntimeException("Invalid folder item " + parser.getName()); diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index 85f58a1b1..f2c5d93f5 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -58,9 +58,11 @@ import com.android.launcher3.UninstallDropTarget.UninstallSource; import com.android.launcher3.Workspace.ItemOperator; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource; import com.android.launcher3.util.Thunk; +import com.android.launcher3.util.UiThreadCircularReveal; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; /** * Represents a set of icons chosen by the user or generated by the system. @@ -362,7 +364,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList void bind(FolderInfo info) { mInfo = info; ArrayList<ShortcutInfo> children = info.contents; - Collections.sort(children, Utilities.RANK_COMPARATOR); + Collections.sort(children, ITEM_POS_COMPARATOR); ArrayList<ShortcutInfo> overflow = mContent.bindItems(children); @@ -467,6 +469,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList prepareReveal(); centerAboutIcon(); + AnimatorSet anim = LauncherAnimUtils.createAnimatorSet(); int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); int height = getFolderHeight(); @@ -477,7 +480,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList PropertyValuesHolder tx = PropertyValuesHolder.ofFloat("translationX", transX, 0); PropertyValuesHolder ty = PropertyValuesHolder.ofFloat("translationY", transY, 0); - Animator drift = LauncherAnimUtils.ofPropertyValuesHolder(this, tx, ty); + Animator drift = ObjectAnimator.ofPropertyValuesHolder(this, tx, ty); drift.setDuration(mMaterialExpandDuration); drift.setStartDelay(mMaterialExpandStagger); drift.setInterpolator(new LogDecelerateInterpolator(100, 0)); @@ -486,20 +489,19 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY()); float radius = (float) Math.hypot(rx, ry); - AnimatorSet anim = LauncherAnimUtils.createAnimatorSet(); - Animator reveal = LauncherAnimUtils.createCircularReveal(this, (int) getPivotX(), + Animator reveal = UiThreadCircularReveal.createCircularReveal(this, (int) getPivotX(), (int) getPivotY(), 0, radius); reveal.setDuration(mMaterialExpandDuration); reveal.setInterpolator(new LogDecelerateInterpolator(100, 0)); mContentWrapper.setAlpha(0f); - Animator iconsAlpha = LauncherAnimUtils.ofFloat(mContentWrapper, "alpha", 0f, 1f); + Animator iconsAlpha = ObjectAnimator.ofFloat(mContentWrapper, "alpha", 0f, 1f); iconsAlpha.setDuration(mMaterialExpandDuration); iconsAlpha.setStartDelay(mMaterialExpandStagger); iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); mFooter.setAlpha(0f); - Animator textAlpha = LauncherAnimUtils.ofFloat(mFooter, "alpha", 0f, 1f); + Animator textAlpha = ObjectAnimator.ofFloat(mFooter, "alpha", 0f, 1f); textAlpha.setDuration(mMaterialExpandDuration); textAlpha.setStartDelay(mMaterialExpandStagger); textAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); @@ -1395,4 +1397,19 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList onDragOver(mDragObject, 1); } } + + // Compares item position based on rank and position giving priority to the rank. + private static final Comparator<ItemInfo> ITEM_POS_COMPARATOR = new Comparator<ItemInfo>() { + + @Override + public int compare(ItemInfo lhs, ItemInfo rhs) { + if (lhs.rank != rhs.rank) { + return lhs.rank - rhs.rank; + } else if (lhs.cellY != rhs.cellY) { + return lhs.cellY - rhs.cellY; + } else { + return lhs.cellX - rhs.cellX; + } + } + }; } diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java index 14ad33799..b9ac2a47a 100644 --- a/src/com/android/launcher3/IconCache.java +++ b/src/com/android/launcher3/IconCache.java @@ -32,6 +32,9 @@ import android.database.sqlite.SQLiteOpenHelper; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.SystemClock; @@ -68,7 +71,7 @@ public class IconCache { private static final boolean DEBUG = false; - private static final int LOW_RES_SCALE_FACTOR = 8; + private static final int LOW_RES_SCALE_FACTOR = 5; @Thunk static final Object ICON_UPDATE_TOKEN = new Object(); @@ -93,6 +96,20 @@ public class IconCache { @Thunk final Handler mWorkerHandler; + // The background color used for activity icons. Since these icons are displayed in all-apps + // and folders, this would be same as the light quantum panel background. This color + // is used to convert icons to RGB_565. + private final int mActivityBgColor; + // The background color used for package icons. These are displayed in widget tray, which + // has a dark quantum panel background. + private final int mPackageBgColor; + private final BitmapFactory.Options mLowResOptions; + + private String mSystemState; + private Bitmap mLowResBitmap; + private Canvas mLowResCanvas; + private Paint mLowResPaint; + public IconCache(Context context, InvariantDeviceProfile inv) { mContext = context; mPackageManager = context.getPackageManager(); @@ -102,6 +119,14 @@ public class IconCache { mIconDb = new IconDB(context); mWorkerHandler = new Handler(LauncherModel.getWorkerLooper()); + + mActivityBgColor = context.getResources().getColor(R.color.quantum_panel_bg_color); + mPackageBgColor = context.getResources().getColor(R.color.quantum_panel_bg_color_dark); + mLowResOptions = new BitmapFactory.Options(); + // Always prefer RGB_565 config for low res. If the bitmap has transparency, it will + // automatically be loaded as ALPHA_8888. + mLowResOptions.inPreferredConfig = Bitmap.Config.RGB_565; + updateSystemStateString(); } private Drawable getFullResDefaultActivityIcon() { @@ -221,7 +246,7 @@ public class IconCache { // Remove all active icon update tasks. mWorkerHandler.removeCallbacksAndMessages(ICON_UPDATE_TOKEN); - mIconDb.updateSystemStateString(); + updateSystemStateString(); for (UserHandleCompat user : mUserManager.getUserProfiles()) { // Query for the set of apps final List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user); @@ -294,7 +319,7 @@ public class IconCache { int version = c.getInt(indexVersion); LauncherActivityInfoCompat app = componentMap.remove(component); if (version == info.versionCode && updateTime == info.lastUpdateTime && - TextUtils.equals(mIconDb.mSystemState, c.getString(systemStateIndex))) { + TextUtils.equals(mSystemState, c.getString(systemStateIndex))) { continue; } if (app == null) { @@ -361,7 +386,7 @@ public class IconCache { entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, app.getUser()); mCache.put(new ComponentKey(app.getComponentName(), app.getUser()), entry); - return mIconDb.newContentValues(entry.icon, entry.title.toString()); + return newContentValues(entry.icon, entry.title.toString(), mActivityBgColor); } /** @@ -596,7 +621,7 @@ public class IconCache { // Add the icon in the DB here, since these do not get written during // package updates. ContentValues values = - mIconDb.newContentValues(entry.icon, entry.title.toString()); + newContentValues(entry.icon, entry.title.toString(), mPackageBgColor); addIconToDB(values, cn, info, mUserManager.getSerialNumberForUser(user)); } catch (NameNotFoundException e) { @@ -635,7 +660,7 @@ public class IconCache { // pass } - ContentValues values = mIconDb.newContentValues(icon, label); + ContentValues values = newContentValues(icon, label, Color.TRANSPARENT); values.put(IconDB.COLUMN_COMPONENT, componentName.flattenToString()); values.put(IconDB.COLUMN_USER, userSerial); mIconDb.getWritableDatabase().insertWithOnConflict(IconDB.TABLE_NAME, null, values, @@ -653,7 +678,7 @@ public class IconCache { null, null, null); try { if (c.moveToNext()) { - entry.icon = loadIconNoResize(c, 0); + entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : null); entry.isLowResIcon = lowRes; entry.title = c.getString(1); if (entry.title == null) { @@ -744,8 +769,12 @@ public class IconCache { } } + private void updateSystemStateString() { + mSystemState = Locale.getDefault().toString(); + } + private static final class IconDB extends SQLiteOpenHelper { - private final static int DB_VERSION = 5; + private final static int DB_VERSION = 6; private final static String TABLE_NAME = "icons"; private final static String COLUMN_ROWID = "rowid"; @@ -758,15 +787,8 @@ public class IconCache { private final static String COLUMN_LABEL = "label"; private final static String COLUMN_SYSTEM_STATE = "system_state"; - public String mSystemState; - public IconDB(Context context) { super(context, LauncherFiles.APP_ICONS_DB, null, DB_VERSION); - updateSystemStateString(); - } - - public void updateSystemStateString() { - mSystemState = Locale.getDefault().toString(); } @Override @@ -802,24 +824,42 @@ public class IconCache { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } + } + + private ContentValues newContentValues(Bitmap icon, String label, int lowResBackgroundColor) { + ContentValues values = new ContentValues(); + values.put(IconDB.COLUMN_ICON, Utilities.flattenBitmap(icon)); + + values.put(IconDB.COLUMN_LABEL, label); + values.put(IconDB.COLUMN_SYSTEM_STATE, mSystemState); - public ContentValues newContentValues(Bitmap icon, String label) { - ContentValues values = new ContentValues(); - values.put(COLUMN_ICON, Utilities.flattenBitmap(icon)); - values.put(COLUMN_ICON_LOW_RES, Utilities.flattenBitmap( - Bitmap.createScaledBitmap(icon, - icon.getWidth() / LOW_RES_SCALE_FACTOR, - icon.getHeight() / LOW_RES_SCALE_FACTOR, true))); - values.put(COLUMN_LABEL, label); - values.put(COLUMN_SYSTEM_STATE, mSystemState); - return values; + if (lowResBackgroundColor == Color.TRANSPARENT) { + values.put(IconDB.COLUMN_ICON_LOW_RES, Utilities.flattenBitmap( + Bitmap.createScaledBitmap(icon, + icon.getWidth() / LOW_RES_SCALE_FACTOR, + icon.getHeight() / LOW_RES_SCALE_FACTOR, true))); + } else { + synchronized (this) { + if (mLowResBitmap == null) { + mLowResBitmap = Bitmap.createBitmap(icon.getWidth() / LOW_RES_SCALE_FACTOR, + icon.getHeight() / LOW_RES_SCALE_FACTOR, Bitmap.Config.RGB_565); + mLowResCanvas = new Canvas(mLowResBitmap); + mLowResPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); + } + mLowResCanvas.drawColor(lowResBackgroundColor); + mLowResCanvas.drawBitmap(icon, new Rect(0, 0, icon.getWidth(), icon.getHeight()), + new Rect(0, 0, mLowResBitmap.getWidth(), mLowResBitmap.getHeight()), + mLowResPaint); + values.put(IconDB.COLUMN_ICON_LOW_RES, Utilities.flattenBitmap(mLowResBitmap)); + } } + return values; } - private static Bitmap loadIconNoResize(Cursor c, int iconIndex) { + private static Bitmap loadIconNoResize(Cursor c, int iconIndex, BitmapFactory.Options options) { byte[] data = c.getBlob(iconIndex); try { - return BitmapFactory.decodeByteArray(data, 0, data.length); + return BitmapFactory.decodeByteArray(data, 0, data.length, options); } catch (Exception e) { return null; } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 4e83a67f3..55b8f0373 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -872,7 +872,7 @@ public class Launcher extends Activity } /** @Override for MNC */ - protected void onRequestPermissionsResult(int requestCode, String[] permissions, + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (mLauncherCallbacks != null) { mLauncherCallbacks.onRequestPermissionsResult(requestCode, permissions, @@ -3507,6 +3507,7 @@ public class Launcher extends Activity .commit(); } + mAppWidgetHost.setQsbWidgetId(widgetId); if (widgetId != -1) { mQsb = mAppWidgetHost.createView(this, widgetId, searchProvider); mQsb.updateAppWidgetOptions(opts); diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java index c274f2ecd..de7c61000 100644 --- a/src/com/android/launcher3/LauncherAppWidgetHost.java +++ b/src/com/android/launcher3/LauncherAppWidgetHost.java @@ -22,6 +22,7 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.os.TransactionTooLargeException; import android.view.LayoutInflater; +import android.view.View; import java.util.ArrayList; @@ -35,16 +36,31 @@ public class LauncherAppWidgetHost extends AppWidgetHost { private final ArrayList<Runnable> mProviderChangeListeners = new ArrayList<Runnable>(); - Launcher mLauncher; + private int mQsbWidgetId = -1; + private Launcher mLauncher; public LauncherAppWidgetHost(Launcher launcher, int hostId) { super(launcher, hostId); mLauncher = launcher; } + public void setQsbWidgetId(int widgetId) { + mQsbWidgetId = widgetId; + } + @Override protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { + if (appWidgetId == mQsbWidgetId) { + return new LauncherAppWidgetHostView(context) { + + @Override + protected View getErrorView() { + // For the QSB, show an empty view instead of an error view. + return new View(getContext()); + } + }; + } return new LauncherAppWidgetHostView(context); } diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index d0c24cd83..8fd298df7 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -59,7 +59,6 @@ import android.widget.Toast; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Comparator; import java.util.Locale; import java.util.Set; import java.util.regex.Matcher; @@ -578,13 +577,6 @@ public final class Utilities { } } - public static final Comparator<ItemInfo> RANK_COMPARATOR = new Comparator<ItemInfo>() { - @Override - public int compare(ItemInfo lhs, ItemInfo rhs) { - return lhs.rank - rhs.rank; - } - }; - /** * Find the first vacant cell, if there is one. * diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index fb0a54d3c..451f1245e 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -1976,7 +1976,7 @@ public class Workspace extends PagedView public Animator setStateWithAnimation(State toState, int toPage, boolean animated, boolean hasOverlaySearchBar, HashMap<View, Integer> layerViews) { // Create the animation to the new state - Animator workspaceAnim = mStateTransitionAnimation.getAnimationToState(getState(), + Animator workspaceAnim = mStateTransitionAnimation.getAnimationToState(mState, toState, toPage, animated, hasOverlaySearchBar, layerViews); // Update the current state @@ -1996,6 +1996,9 @@ public class Workspace extends PagedView for (int i = numCustomPages(); i < total; i++) { updateAccessibilityFlags((CellLayout) getPageAt(i), i); } + setImportantForAccessibility((mState == State.NORMAL || mState == State.OVERVIEW) + ? IMPORTANT_FOR_ACCESSIBILITY_AUTO + : IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } else { int accessible = mState == State.NORMAL ? IMPORTANT_FOR_ACCESSIBILITY_AUTO : 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 diff --git a/src/com/android/launcher3/util/UiThreadCircularReveal.java b/src/com/android/launcher3/util/UiThreadCircularReveal.java index c7324fb1b..c8e1df289 100644 --- a/src/com/android/launcher3/util/UiThreadCircularReveal.java +++ b/src/com/android/launcher3/util/UiThreadCircularReveal.java @@ -15,11 +15,15 @@ import com.android.launcher3.Utilities; public class UiThreadCircularReveal { public static ValueAnimator createCircularReveal(View v, int x, int y, float r0, float r1) { + return createCircularReveal(v, x, y, r0, r1, ViewOutlineProvider.BACKGROUND); + } + + public static ValueAnimator createCircularReveal(View v, int x, int y, float r0, float r1, + final ViewOutlineProvider originalProvider) { ValueAnimator va = ValueAnimator.ofFloat(0f, 1f); final View revealView = v; final RevealOutlineProvider outlineProvider = new RevealOutlineProvider(x, y, r0, r1); - final ViewOutlineProvider originalProvider = revealView.getOutlineProvider(); final float elevation = v.getElevation(); va.addListener(new AnimatorListenerAdapter() { |