diff options
20 files changed, 479 insertions, 279 deletions
diff --git a/res/drawable-hdpi/ic_arrow_back_grey.png b/res/drawable-hdpi/ic_arrow_back_grey.png Binary files differnew file mode 100755 index 000000000..ccd3900dd --- /dev/null +++ b/res/drawable-hdpi/ic_arrow_back_grey.png diff --git a/res/drawable-hdpi/ic_search_grey.png b/res/drawable-hdpi/ic_search_grey.png Binary files differnew file mode 100755 index 000000000..f4c5e27d2 --- /dev/null +++ b/res/drawable-hdpi/ic_search_grey.png diff --git a/res/drawable-mdpi/ic_arrow_back_grey.png b/res/drawable-mdpi/ic_arrow_back_grey.png Binary files differnew file mode 100755 index 000000000..11996efe3 --- /dev/null +++ b/res/drawable-mdpi/ic_arrow_back_grey.png diff --git a/res/drawable-mdpi/ic_search_grey.png b/res/drawable-mdpi/ic_search_grey.png Binary files differnew file mode 100755 index 000000000..e83891c11 --- /dev/null +++ b/res/drawable-mdpi/ic_search_grey.png diff --git a/res/drawable-xhdpi/ic_arrow_back_grey.png b/res/drawable-xhdpi/ic_arrow_back_grey.png Binary files differnew file mode 100755 index 000000000..79b9b486c --- /dev/null +++ b/res/drawable-xhdpi/ic_arrow_back_grey.png diff --git a/res/drawable-xhdpi/ic_search_grey.png b/res/drawable-xhdpi/ic_search_grey.png Binary files differnew file mode 100755 index 000000000..bd5fdf444 --- /dev/null +++ b/res/drawable-xhdpi/ic_search_grey.png diff --git a/res/drawable-xxhdpi/ic_arrow_back_grey.png b/res/drawable-xxhdpi/ic_arrow_back_grey.png Binary files differnew file mode 100755 index 000000000..8e42e091d --- /dev/null +++ b/res/drawable-xxhdpi/ic_arrow_back_grey.png diff --git a/res/drawable-xxhdpi/ic_search_grey.png b/res/drawable-xxhdpi/ic_search_grey.png Binary files differnew file mode 100755 index 000000000..1d5c91361 --- /dev/null +++ b/res/drawable-xxhdpi/ic_search_grey.png diff --git a/res/drawable-xxxhdpi/ic_arrow_back_grey.png b/res/drawable-xxxhdpi/ic_arrow_back_grey.png Binary files differnew file mode 100755 index 000000000..854a9bd1a --- /dev/null +++ b/res/drawable-xxxhdpi/ic_arrow_back_grey.png diff --git a/res/drawable-xxxhdpi/ic_search_grey.png b/res/drawable-xxxhdpi/ic_search_grey.png Binary files differnew file mode 100755 index 000000000..28519fda6 --- /dev/null +++ b/res/drawable-xxxhdpi/ic_search_grey.png diff --git a/res/layout/apps_list_view.xml b/res/layout/apps_list_view.xml index dfb7b588d..e29cac5e1 100644 --- a/res/layout/apps_list_view.xml +++ b/res/layout/apps_list_view.xml @@ -22,22 +22,55 @@ android:elevation="15dp" android:visibility="gone" android:focusableInTouchMode="true"> - <EditText - android:id="@+id/app_search_box" + <FrameLayout + android:id="@+id/header" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:padding="16dp" - android:hint="@string/apps_view_search_bar_hint" - android:maxLines="1" - android:singleLine="true" - android:scrollHorizontally="true" - android:gravity="fill_horizontal" - android:textSize="16sp" - android:textColor="#4c4c4c" - android:textColorHint="#9c9c9c" - android:imeOptions="actionDone|flagNoExtractUi" - android:background="@drawable/apps_search_bg" - android:elevation="4dp" /> + android:layout_height="52dp" + android:orientation="horizontal" + android:background="@drawable/apps_search_bg"> + <LinearLayout + android:id="@+id/app_search_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:visibility="invisible"> + <ImageView + android:id="@+id/dismiss_search_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="start|center_vertical" + android:paddingTop="12dp" + android:paddingBottom="12dp" + android:contentDescription="@string/all_apps_button_label" + android:src="@drawable/ic_arrow_back_grey" /> + <EditText + android:id="@+id/app_search_box" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingTop="16dp" + android:paddingBottom="16dp" + android:paddingLeft="8dp" + android:hint="@string/apps_view_search_bar_hint" + android:maxLines="1" + android:singleLine="true" + android:scrollHorizontally="true" + android:gravity="fill_horizontal" + android:textSize="16sp" + android:textColor="#4c4c4c" + android:textColorHint="#9c9c9c" + android:imeOptions="actionDone|flagNoExtractUi" + android:background="@android:color/transparent" /> + </LinearLayout> + <ImageView + android:id="@+id/search_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end|center_vertical" + android:paddingTop="12dp" + android:paddingBottom="12dp" + android:contentDescription="@string/apps_view_search_bar_hint" + android:src="@drawable/ic_search_grey" /> + </FrameLayout> <com.android.launcher3.AppsContainerRecyclerView android:id="@+id/apps_list_view" android:layout_width="match_parent" diff --git a/res/values/dimens.xml b/res/values/dimens.xml index a57ae89d0..4fbe87e09 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -53,6 +53,7 @@ <!-- Note: This needs to match the fixed insets for the search box --> <dimen name="apps_container_fixed_bounds_inset">8dp</dimen> <dimen name="apps_grid_view_start_margin">52dp</dimen> + <dimen name="apps_grid_section_y_offset">8dp</dimen> <dimen name="apps_view_row_height">64dp</dimen> <dimen name="apps_view_section_text_size">24sp</dimen> <dimen name="apps_view_fast_scroll_bar_width">6dp</dimen> diff --git a/src/com/android/launcher3/AlphabeticalAppsList.java b/src/com/android/launcher3/AlphabeticalAppsList.java index c7ee2e99a..477c00fe8 100644 --- a/src/com/android/launcher3/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/AlphabeticalAppsList.java @@ -86,6 +86,8 @@ public class AlphabeticalAppsList { public String sectionName; // The number of applications in this section public int numAppsInSection; + // The section AdapterItem for this section + public AdapterItem sectionItem; // The first app AdapterItem for this section public AdapterItem firstAppItem; @@ -137,6 +139,9 @@ public class AlphabeticalAppsList { public boolean retainApp(AppInfo info, String sectionName); } + // The maximum number of rows allowed in a merged section before we stop merging + private static final int MAX_ROWS_IN_MERGED_SECTION = Integer.MAX_VALUE; + private List<AppInfo> mApps = new ArrayList<>(); private List<AppInfo> mFilteredApps = new ArrayList<>(); private List<AdapterItem> mSectionedFilteredApps = new ArrayList<>(); @@ -145,10 +150,23 @@ public class AlphabeticalAppsList { private Filter mFilter; private AlphabeticIndexCompat mIndexer; private AppNameComparator mAppNameComparator; + private int mNumAppsPerRow; + // The maximum number of section merges we allow at a given time before we stop merging + private int mMaxAllowableMerges = Integer.MAX_VALUE; - public AlphabeticalAppsList(Context context) { + public AlphabeticalAppsList(Context context, int numAppsPerRow) { mIndexer = new AlphabeticIndexCompat(context); mAppNameComparator = new AppNameComparator(context); + setNumAppsPerRow(numAppsPerRow); + } + + /** + * Sets the number of apps per row. Used only for AppsContainerView.SECTIONED_GRID_COALESCED. + */ + public void setNumAppsPerRow(int numAppsPerRow) { + mNumAppsPerRow = numAppsPerRow; + mMaxAllowableMerges = (int) Math.ceil(numAppsPerRow / 2f); + onAppsUpdated(); } /** @@ -180,6 +198,13 @@ public class AlphabeticalAppsList { } /** + * Returns whether there are is a filter set. + */ + public boolean hasFilter() { + return (mFilter != null); + } + + /** * Returns whether there are no filtered results. */ public boolean hasNoFilteredResults() { @@ -190,9 +215,11 @@ public class AlphabeticalAppsList { * Sets the current filter for this list of apps. */ public void setFilter(Filter f) { - mFilter = f; - onAppsUpdated(); - mAdapter.notifyDataSetChanged(); + if (mFilter != f) { + mFilter = f; + onAppsUpdated(); + mAdapter.notifyDataSetChanged(); + } } /** @@ -298,9 +325,13 @@ public class AlphabeticalAppsList { lastSectionInfo = new SectionInfo(sectionName); mSections.add(lastSectionInfo); - // Create a new section item + // Create a new section item, this item is used to break the flow of items in the + // list AdapterItem sectionItem = AdapterItem.asSection(position++, sectionName); - mSectionedFilteredApps.add(sectionItem); + if (!AppsContainerView.GRID_HIDE_SECTION_HEADERS && !hasFilter()) { + lastSectionInfo.sectionItem = sectionItem; + mSectionedFilteredApps.add(sectionItem); + } } // Create an app item @@ -312,5 +343,53 @@ public class AlphabeticalAppsList { mSectionedFilteredApps.add(appItem); mFilteredApps.add(info); } + + if (AppsContainerView.GRID_MERGE_SECTIONS && !hasFilter()) { + // Go through each section and try and merge some of the sections + int minNumAppsPerRow = (int) Math.ceil(mNumAppsPerRow / 2f); + int sectionAppCount = 0; + for (int i = 0; i < mSections.size(); i++) { + SectionInfo section = mSections.get(i); + String mergedSectionName = section.sectionName; + sectionAppCount = section.numAppsInSection; + int mergeCount = 1; + // Merge rows if the last app in this section is in a column that is greater than + // 0, but less than the min number of apps per row. In addition, apply the + // constraint to stop merging if the number of rows in the section is greater than + // some limit, and also if there are no lessons to merge. + while (0 < (sectionAppCount % mNumAppsPerRow) && + (sectionAppCount % mNumAppsPerRow) < minNumAppsPerRow && + (int) Math.ceil(sectionAppCount / mNumAppsPerRow) < MAX_ROWS_IN_MERGED_SECTION && + (i + 1) < mSections.size()) { + SectionInfo nextSection = mSections.remove(i + 1); + // Merge the section names + if (AppsContainerView.GRID_MERGE_SECTION_HEADERS) { + mergedSectionName += nextSection.sectionName; + } + // Remove the next section break + mSectionedFilteredApps.remove(nextSection.sectionItem); + if (AppsContainerView.GRID_MERGE_SECTION_HEADERS) { + // Update the section names for the two sections + int pos = mSectionedFilteredApps.indexOf(section.firstAppItem); + for (int j = pos; j < (pos + section.numAppsInSection + nextSection.numAppsInSection); j++) { + AdapterItem item = mSectionedFilteredApps.get(j); + item.sectionName = mergedSectionName; + } + } + // Update the following adapter items of the removed section + int pos = mSectionedFilteredApps.indexOf(nextSection.firstAppItem); + for (int j = pos; j < mSectionedFilteredApps.size(); j++) { + AdapterItem item = mSectionedFilteredApps.get(j); + item.position--; + } + section.numAppsInSection += nextSection.numAppsInSection; + sectionAppCount += nextSection.numAppsInSection; + mergeCount++; + if (mergeCount >= mMaxAllowableMerges) { + break; + } + } + } + } } } diff --git a/src/com/android/launcher3/AppsContainerRecyclerView.java b/src/com/android/launcher3/AppsContainerRecyclerView.java index bf478eddd..d91bceac9 100644 --- a/src/com/android/launcher3/AppsContainerRecyclerView.java +++ b/src/com/android/launcher3/AppsContainerRecyclerView.java @@ -66,6 +66,7 @@ public class AppsContainerRecyclerView extends RecyclerView private int mScrollbarWidth; private int mScrollbarMinHeight; private int mScrollbarInset; + private RecyclerView.OnScrollListener mScrollListenerProxy; public AppsContainerRecyclerView(Context context) { this(context, null); @@ -102,7 +103,7 @@ public class AppsContainerRecyclerView extends RecyclerView mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD; ScrollListener listener = new ScrollListener(); - addOnScrollListener(listener); + setOnScrollListener(listener); } private class ScrollListener extends RecyclerView.OnScrollListener { @@ -112,6 +113,7 @@ public class AppsContainerRecyclerView extends RecyclerView @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { mDy = dy; + mScrollListenerProxy.onScrolled(recyclerView, dx, dy); } } @@ -130,6 +132,13 @@ public class AppsContainerRecyclerView extends RecyclerView } /** + * Sets an additional scroll listener, not necessary in master support lib. + */ + public void setOnScrollListenerProxy(RecyclerView.OnScrollListener listener) { + mScrollListenerProxy = listener; + } + + /** * Sets the fast scroller alpha. */ public void setFastScrollerAlpha(float alpha) { @@ -178,10 +187,6 @@ public class AppsContainerRecyclerView extends RecyclerView handleTouchEvent(ev); } - public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { - // Do nothing - } - /** * Handles the touch event and determines whether to show the fast scroller (or updates it if * it is already showing). @@ -322,6 +327,7 @@ public class AppsContainerRecyclerView extends RecyclerView // Find the position of the first application in the section that contains the row at the // current progress + List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems(); int rowAtProgress = (int) (progress * getNumRows()); int rowCount = 0; AlphabeticalAppsList.SectionInfo lastSectionInfo = null; @@ -333,7 +339,7 @@ public class AppsContainerRecyclerView extends RecyclerView } rowCount += numRowsInSection; } - int position = mApps.getAdapterItems().indexOf(lastSectionInfo.firstAppItem); + int position = items.indexOf(lastSectionInfo.firstAppItem); // Scroll the position into view, anchored at the top of the screen if possible. We call the // scroll method on the LayoutManager directly since it is not exposed by RecyclerView. @@ -342,15 +348,17 @@ public class AppsContainerRecyclerView extends RecyclerView layoutManager.scrollToPositionWithOffset(position, 0); // Return the section name of the row - return mApps.getAdapterItems().get(position).sectionName; + return lastSectionInfo.sectionName; } /** * Returns the bounds for the scrollbar. */ private void updateVerticalScrollbarBounds() { + List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems(); + // Skip early if there are no items - if (mApps.getAdapterItems().isEmpty()) { + if (items.isEmpty()) { mVerticalScrollbarBounds.setEmpty(); return; } @@ -369,7 +377,7 @@ public class AppsContainerRecyclerView extends RecyclerView View child = getChildAt(i); int position = getChildPosition(child); if (position != NO_POSITION) { - AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position); + AlphabeticalAppsList.AdapterItem item = items.get(position); if (!item.isSectionHeader) { rowIndex = findRowForAppIndex(item.appIndex); rowTopOffset = getLayoutManager().getDecoratedTop(child); diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java index c3cf629b8..9122427fd 100644 --- a/src/com/android/launcher3/AppsContainerView.java +++ b/src/com/android/launcher3/AppsContainerView.java @@ -34,7 +34,6 @@ import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; - import com.android.launcher3.util.Thunk; import java.util.List; @@ -45,24 +44,32 @@ import java.util.List; */ public class AppsContainerView extends FrameLayout implements DragSource, Insettable, TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable, View.OnTouchListener, - View.OnLongClickListener { + View.OnClickListener, View.OnLongClickListener { - private static final boolean ALLOW_SINGLE_APP_LAUNCH = true; + public static final boolean GRID_MERGE_SECTIONS = true; + public static final boolean GRID_MERGE_SECTION_HEADERS = false; + public static final boolean GRID_HIDE_SECTION_HEADERS = false; - private static final int GRID_LAYOUT = 0; - private static final int LIST_LAYOUT = 1; - private static final int USE_LAYOUT = GRID_LAYOUT; + private static final boolean ALLOW_SINGLE_APP_LAUNCH = true; + private static final boolean DYNAMIC_HEADER_ELEVATION = false; + private static final float HEADER_ELEVATION_DP = 4; + private static final int FADE_IN_DURATION = 175; + private static final int FADE_OUT_DURATION = 125; @Thunk Launcher mLauncher; @Thunk AlphabeticalAppsList mApps; - private RecyclerView.Adapter mAdapter; + private AppsGridAdapter mAdapter; private RecyclerView.LayoutManager mLayoutManager; private RecyclerView.ItemDecoration mItemDecoration; private LinearLayout mContentView; @Thunk AppsContainerRecyclerView mAppsRecyclerView; - private EditText mSearchBarView; - + private View mHeaderView; + private View mSearchBarContainerView; + private View mSearchButtonView; + private View mDismissSearchButtonView; + private EditText mSearchBarEditView; + private int mNumAppsPerRow; private Point mLastTouchDownPos = new Point(-1, -1); private Point mLastTouchPos = new Point(); @@ -73,6 +80,8 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett private int mContainerInset; // Fixed bounds container insets private int mFixedBoundsContainerInset; + // RecyclerView scroll position + @Thunk int mRecyclerViewScrollY; public AppsContainerView(Context context) { this(context, null); @@ -93,23 +102,14 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett mFixedBoundsContainerInset = context.getResources().getDimensionPixelSize( R.dimen.apps_container_fixed_bounds_inset); mLauncher = (Launcher) context; - mApps = new AlphabeticalAppsList(context); - if (USE_LAYOUT == GRID_LAYOUT) { - mNumAppsPerRow = grid.appsViewNumCols; - AppsGridAdapter adapter = new AppsGridAdapter(context, mApps, mNumAppsPerRow, this, - mLauncher, this); - adapter.setEmptySearchText(res.getString(R.string.loading_apps_message)); - mLayoutManager = adapter.getLayoutManager(context); - mItemDecoration = adapter.getItemDecoration(); - mAdapter = adapter; - mContentMarginStart = adapter.getContentMarginStart(); - } else if (USE_LAYOUT == LIST_LAYOUT) { - mNumAppsPerRow = 1; - AppsListAdapter adapter = new AppsListAdapter(context, mApps, this, mLauncher, this); - adapter.setEmptySearchText(res.getString(R.string.loading_apps_message)); - mLayoutManager = adapter.getLayoutManager(context); - mAdapter = adapter; - } + mNumAppsPerRow = grid.appsViewNumCols; + mApps = new AlphabeticalAppsList(context, mNumAppsPerRow); + mAdapter = new AppsGridAdapter(context, mApps, mNumAppsPerRow, this, mLauncher, this); + mAdapter.setEmptySearchText(res.getString(R.string.loading_apps_message)); + mAdapter.setNumAppsPerRow(mNumAppsPerRow); + mLayoutManager = mAdapter.getLayoutManager(); + mItemDecoration = mAdapter.getItemDecoration(); + mContentMarginStart = mAdapter.getContentMarginStart(); mApps.setAdapter(mAdapter); } @@ -142,10 +142,10 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett } /** - * Hides the search bar + * Hides the header bar */ - public void hideSearchBar() { - mSearchBarView.setVisibility(View.GONE); + public void hideHeaderBar() { + mHeaderView.setVisibility(View.GONE); updateBackgrounds(); updatePaddings(); } @@ -155,6 +155,7 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett */ public void scrollToTop() { mAppsRecyclerView.scrollToPosition(0); + mRecyclerViewScrollY = 0; } /** @@ -175,9 +176,7 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett protected void onFinishInflate() { boolean isRtl = (getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL); - if (USE_LAYOUT == GRID_LAYOUT) { - ((AppsGridAdapter) mAdapter).setRtl(isRtl); - } + mAdapter.setRtl(isRtl); // Work around the search box getting first focus and showing the cursor by // proxying the focus from the content view to the recycler view directly @@ -190,10 +189,20 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett } } }); - mSearchBarView = (EditText) findViewById(R.id.app_search_box); - if (mSearchBarView != null) { - mSearchBarView.addTextChangedListener(this); - mSearchBarView.setOnEditorActionListener(this); + mHeaderView = findViewById(R.id.header); + mHeaderView.setOnClickListener(this); + if (Utilities.isLmpOrAbove() && !DYNAMIC_HEADER_ELEVATION) { + mHeaderView.setElevation(DynamicGrid.pxFromDp(HEADER_ELEVATION_DP, + getContext().getResources().getDisplayMetrics())); + } + mSearchButtonView = mHeaderView.findViewById(R.id.search_button); + mSearchBarContainerView = findViewById(R.id.app_search_container); + mDismissSearchButtonView = mSearchBarContainerView.findViewById(R.id.dismiss_search_button); + mDismissSearchButtonView.setOnClickListener(this); + mSearchBarEditView = (EditText) findViewById(R.id.app_search_box); + if (mSearchBarEditView != null) { + mSearchBarEditView.addTextChangedListener(this); + mSearchBarEditView.setOnEditorActionListener(this); } mAppsRecyclerView = (AppsContainerRecyclerView) findViewById(R.id.apps_list_view); mAppsRecyclerView.setApps(mApps); @@ -201,6 +210,18 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett mAppsRecyclerView.setLayoutManager(mLayoutManager); mAppsRecyclerView.setAdapter(mAdapter); mAppsRecyclerView.setHasFixedSize(true); + mAppsRecyclerView.setOnScrollListenerProxy(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + // Do nothing + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + mRecyclerViewScrollY += dy; + onRecyclerViewScrolled(); + } + }); if (mItemDecoration != null) { mAppsRecyclerView.addItemDecoration(mItemDecoration); } @@ -225,12 +246,15 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett if (grid.updateAppsViewNumCols(context.getResources(), fixedBounds.width())) { mNumAppsPerRow = grid.appsViewNumCols; mAppsRecyclerView.setNumAppsPerRow(mNumAppsPerRow); - if (USE_LAYOUT == GRID_LAYOUT) { - ((AppsGridAdapter) mAdapter).setNumAppsPerRow(mNumAppsPerRow); - } + mAdapter.setNumAppsPerRow(mNumAppsPerRow); + mApps.setNumAppsPerRow(mNumAppsPerRow); } mFixedBounds.set(fixedBounds); + if (Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION) { + mFixedBounds.top = mInsets.top; + mFixedBounds.bottom = getMeasuredHeight(); + } } // Post the updates since they can trigger a relayout, and this call can be triggered from // a layout pass itself. @@ -265,6 +289,15 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett } @Override + public void onClick(View v) { + if (v == mHeaderView) { + showSearchField(); + } else if (v == mDismissSearchButtonView) { + hideSearchField(true, true); + } + } + + @Override public boolean onLongClick(View v) { // Return early if this is not initiated from a touch if (!v.isInTouchMode()) return false; @@ -363,24 +396,27 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett mApps.setFilter(null); } else { String formatStr = getResources().getString(R.string.apps_view_no_search_results); - if (USE_LAYOUT == GRID_LAYOUT) { - ((AppsGridAdapter) mAdapter).setEmptySearchText(String.format(formatStr, - s.toString())); - } else { - ((AppsListAdapter) mAdapter).setEmptySearchText(String.format(formatStr, - s.toString())); - } + mAdapter.setEmptySearchText(String.format(formatStr, s.toString())); final String filterText = s.toString().toLowerCase().replaceAll("\\s+", ""); mApps.setFilter(new AlphabeticalAppsList.Filter() { @Override public boolean retainApp(AppInfo info, String sectionName) { String title = info.title.toString(); - return sectionName.toLowerCase().contains(filterText) || - title.toLowerCase().replaceAll("\\s+", "").contains(filterText); + if (sectionName.toLowerCase().contains(filterText)) { + return true; + } + String[] words = title.toLowerCase().split("\\s+"); + for (int i = 0; i < words.length; i++) { + if (words[i].startsWith(filterText)) { + return true; + } + } + return false; } }); } + scrollToTop(); } @Override @@ -396,9 +432,7 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett AlphabeticalAppsList.AdapterItem item = items.get(i); if (!item.isSectionHeader) { mAppsRecyclerView.getChildAt(i).performClick(); - InputMethodManager imm = (InputMethodManager) - getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(getWindowToken(), 0); + getInputMethodManager().hideSoftInputFromWindow(getWindowToken(), 0); return true; } } @@ -428,10 +462,22 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett @Override public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) { - if (mSearchBarView != null) { + if (mSearchBarEditView != null) { if (toWorkspace) { - // Clear the search bar - mSearchBarView.setText(""); + hideSearchField(false, false); + } + } + } + + /** + * Updates the container when the recycler view is scrolled. + */ + private void onRecyclerViewScrolled() { + if (DYNAMIC_HEADER_ELEVATION) { + int elevation = Math.min(mRecyclerViewScrollY, DynamicGrid.pxFromDp(HEADER_ELEVATION_DP, + getContext().getResources().getDisplayMetrics())); + if (Float.compare(mHeaderView.getElevation(), elevation) != 0) { + mHeaderView.setElevation(elevation); } } } @@ -494,8 +540,8 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett private void updatePaddings() { boolean isRtl = (getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL); - boolean hasSearchBar = (mSearchBarView != null) && - (mSearchBarView.getVisibility() == View.VISIBLE); + boolean hasSearchBar = (mSearchBarEditView != null) && + (mSearchBarEditView.getVisibility() == View.VISIBLE); if (mFixedBounds.isEmpty()) { // If there are no fixed bounds, then use the default padding and insets @@ -516,10 +562,10 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett mAppsRecyclerView.setPadding(inset + mContentMarginStart, inset, inset, inset); } - // Update the search bar + // Update the header if (hasSearchBar) { LinearLayout.LayoutParams lp = - (LinearLayout.LayoutParams) mSearchBarView.getLayoutParams(); + (LinearLayout.LayoutParams) mHeaderView.getLayoutParams(); lp.leftMargin = lp.rightMargin = inset; } } @@ -529,8 +575,8 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett */ private void updateBackgrounds() { int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; - boolean hasSearchBar = (mSearchBarView != null) && - (mSearchBarView.getVisibility() == View.VISIBLE); + boolean hasSearchBar = (mSearchBarEditView != null) && + (mSearchBarEditView.getVisibility() == View.VISIBLE); // Update the background of the reveal view and list to be inset with the fixed bound // insets instead of the default insets @@ -542,4 +588,63 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett getContext().getResources().getDrawable(R.drawable.apps_reveal_bg), inset, 0, inset, 0)); } + + /** + * Shows the search field. + */ + private void showSearchField() { + // Show the search bar and focus the search + mSearchBarContainerView.setVisibility(View.VISIBLE); + mSearchBarContainerView.setAlpha(0f); + mSearchBarContainerView.animate().alpha(1f).setDuration(FADE_IN_DURATION).withLayer() + .withEndAction(new Runnable() { + @Override + public void run() { + mSearchBarEditView.requestFocus(); + getInputMethodManager().showSoftInput(mSearchBarEditView, + InputMethodManager.SHOW_IMPLICIT); + } + }); + mSearchButtonView.animate().alpha(0f).setDuration(FADE_OUT_DURATION).withLayer(); + } + + /** + * Hides the search field. + */ + private void hideSearchField(boolean animated, final boolean returnFocusToRecyclerView) { + if (animated) { + // Hide the search bar and focus the recycler view + mSearchBarContainerView.animate().alpha(0f).setDuration(FADE_IN_DURATION).withLayer() + .withEndAction(new Runnable() { + @Override + public void run() { + mSearchBarContainerView.setVisibility(View.INVISIBLE); + mSearchBarEditView.setText(""); + mApps.setFilter(null); + if (returnFocusToRecyclerView) { + mAppsRecyclerView.requestFocus(); + } + scrollToTop(); + } + }); + mSearchButtonView.animate().alpha(1f).setDuration(FADE_OUT_DURATION).withLayer(); + } else { + mSearchBarContainerView.setVisibility(View.INVISIBLE); + mSearchBarEditView.setText(""); + mApps.setFilter(null); + mSearchButtonView.setAlpha(1f); + if (returnFocusToRecyclerView) { + mAppsRecyclerView.requestFocus(); + } + scrollToTop(); + } + getInputMethodManager().hideSoftInputFromWindow(getWindowToken(), 0); + } + + /** + * Returns an input method manager. + */ + private InputMethodManager getInputMethodManager() { + return (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + } } diff --git a/src/com/android/launcher3/AppsGridAdapter.java b/src/com/android/launcher3/AppsGridAdapter.java index 5bc3981df..62d9129c9 100644 --- a/src/com/android/launcher3/AppsGridAdapter.java +++ b/src/com/android/launcher3/AppsGridAdapter.java @@ -4,16 +4,18 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Point; import android.graphics.Rect; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; - import com.android.launcher3.util.Thunk; +import java.util.HashMap; import java.util.List; @@ -23,6 +25,7 @@ import java.util.List; class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { public static final String TAG = "AppsGridAdapter"; + private static final boolean DEBUG = false; private static final int SECTION_BREAK_VIEW_TYPE = 0; private static final int ICON_VIEW_TYPE = 1; @@ -48,6 +51,12 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { * Helper class to size the grid items. */ public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup { + + public GridSpanSizer() { + super(); + setSpanIndexCacheEnabled(true); + } + @Override public int getSpanSize(int position) { if (mApps.hasNoFilteredResults()) { @@ -57,7 +66,11 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { if (mApps.getAdapterItems().get(position).isSectionHeader) { // Section break spans full width - return mAppsPerRow; + if (AppsContainerView.GRID_HIDE_SECTION_HEADERS) { + return 0; + } else { + return mAppsPerRow; + } } else { return 1; } @@ -69,31 +82,88 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { */ public class GridItemDecoration extends RecyclerView.ItemDecoration { + private static final boolean FADE_OUT_SECTIONS = false; + + private HashMap<String, Point> mCachedSectionBounds = new HashMap<>(); + private Rect mTmpBounds = new Rect(); + @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + if (mApps.hasFilter()) { + return; + } + List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems(); + String lastSectionName = null; + int appIndexInSection = 0; + int lastSectionTop = 0; + int lastSectionHeight = 0; for (int i = 0; i < parent.getChildCount(); i++) { View child = parent.getChildAt(i); ViewHolder holder = (ViewHolder) parent.getChildViewHolder(child); - if (shouldDrawItemSection(holder, child, items)) { - // Draw at the parent - AlphabeticalAppsList.AdapterItem item = - items.get(holder.getPosition()); - String section = item.sectionName; - mSectionTextPaint.getTextBounds(section, 0, section.length(), - mTmpBounds); - if (mIsRtl) { - int left = parent.getWidth() - mPaddingStart - mStartMargin; - c.drawText(section, left + (mStartMargin - mTmpBounds.width()) / 2, - child.getTop() + (2 * child.getPaddingTop()) + - mTmpBounds.height(), mSectionTextPaint); - } else { - int left = mPaddingStart; - c.drawText(section, left + (mStartMargin - mTmpBounds.width()) / 2, - child.getTop() + (2 * child.getPaddingTop()) + - mTmpBounds.height(), mSectionTextPaint); + if (shouldDrawItemSection(holder, child, i, items)) { + int cellTopOffset = (2 * child.getPaddingTop()); + int pos = holder.getPosition(); + AlphabeticalAppsList.AdapterItem item = items.get(pos); + if (!item.sectionName.equals(lastSectionName)) { + lastSectionName = item.sectionName; + + // Find the section code points + String sectionBegin = null; + String sectionEnd = null; + int charOffset = 0; + while (charOffset < item.sectionName.length()) { + int codePoint = item.sectionName.codePointAt(charOffset); + int codePointSize = Character.charCount(codePoint); + if (charOffset == 0) { + // The first code point + sectionBegin = item.sectionName.substring(charOffset, charOffset + codePointSize); + } else if ((charOffset + codePointSize) >= item.sectionName.length()) { + // The last code point + sectionEnd = item.sectionName.substring(charOffset, charOffset + codePointSize); + } + charOffset += codePointSize; + } + + Point sectionBeginBounds = getAndCacheSectionBounds(sectionBegin); + int minTop = cellTopOffset + sectionBeginBounds.y; + int top = child.getTop() + cellTopOffset + sectionBeginBounds.y; + int left = mIsRtl ? parent.getWidth() - mPaddingStart - mStartMargin : + mPaddingStart; + int col = appIndexInSection % mAppsPerRow; + int nextRowPos = Math.min(pos - col + mAppsPerRow, items.size() - 1); + int alpha = 255; + boolean fixedToRow = !items.get(nextRowPos).sectionName.equals(item.sectionName); + if (fixedToRow) { + alpha = Math.min(255, (int) (255 * (Math.max(0, top) / (float) minTop))); + } else { + // If we aren't fixed to the current row, then bound into the viewport + top = Math.max(minTop, top); + } + if (lastSectionHeight > 0 && top <= (lastSectionTop + lastSectionHeight)) { + top += lastSectionTop - top + lastSectionHeight; + } + if (FADE_OUT_SECTIONS) { + mSectionTextPaint.setAlpha(alpha); + } + if (sectionEnd != null) { + Point sectionEndBounds = getAndCacheSectionBounds(sectionEnd); + c.drawText(sectionBegin + "/" + sectionEnd, + left + (mStartMargin - sectionBeginBounds.x - sectionEndBounds.x) / 2, top, + mSectionTextPaint); + } else { + c.drawText(sectionBegin, left + (mStartMargin - sectionBeginBounds.x) / 2, top, + mSectionTextPaint); + } + lastSectionTop = top; + lastSectionHeight = sectionBeginBounds.y + mSectionHeaderOffset; } } + if (holder.mIsSectionHeader) { + appIndexInSection = 0; + } else { + appIndexInSection++; + } } } @@ -103,7 +173,17 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { // Do nothing } - private boolean shouldDrawItemSection(ViewHolder holder, View child, + private Point getAndCacheSectionBounds(String sectionName) { + Point bounds = mCachedSectionBounds.get(sectionName); + if (bounds == null) { + mSectionTextPaint.getTextBounds(sectionName, 0, sectionName.length(), mTmpBounds); + bounds = new Point(mTmpBounds.width(), mTmpBounds.height()); + mCachedSectionBounds.put(sectionName, bounds); + } + return bounds; + } + + private boolean shouldDrawItemSection(ViewHolder holder, View child, int childIndex, List<AlphabeticalAppsList.AdapterItem> items) { // Ensure item is not already removed GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) @@ -121,11 +201,19 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { } // Ensure we have a holder position int pos = holder.getPosition(); - if (pos <= 0 || pos >= items.size()) { + if (pos < 0 || pos >= items.size()) { + return false; + } + // Ensure this is not a section header + if (items.get(pos).isSectionHeader) { return false; } - // Only draw the first item in the section (the first one after the section header) - return items.get(pos - 1).isSectionHeader && !items.get(pos).isSectionHeader; + // Only draw the header for the first item in a section, or whenever the sub-sections + // changes (if AppsContainerView.GRID_MERGE_SECTIONS is true, but + // AppsContainerView.GRID_MERGE_SECTION_HEADERS is false) + return (childIndex == 0) || + items.get(pos - 1).isSectionHeader && !items.get(pos).isSectionHeader || + (!items.get(pos - 1).sectionName.equals(items.get(pos).sectionName)); } } @@ -144,8 +232,8 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { // Section drawing @Thunk int mPaddingStart; @Thunk int mStartMargin; + @Thunk int mSectionHeaderOffset; @Thunk Paint mSectionTextPaint; - @Thunk Rect mTmpBounds = new Rect(); public AppsGridAdapter(Context context, AlphabeticalAppsList apps, int appsPerRow, @@ -163,7 +251,10 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { mTouchListener = touchListener; mIconClickListener = iconClickListener; mIconLongClickListener = iconLongClickListener; - mStartMargin = res.getDimensionPixelSize(R.dimen.apps_grid_view_start_margin); + if (!AppsContainerView.GRID_HIDE_SECTION_HEADERS) { + mStartMargin = res.getDimensionPixelSize(R.dimen.apps_grid_view_start_margin); + mSectionHeaderOffset = res.getDimensionPixelSize(R.dimen.apps_grid_section_y_offset); + } mPaddingStart = res.getDimensionPixelSize(R.dimen.apps_container_inset); mSectionTextPaint = new Paint(); mSectionTextPaint.setTextSize(res.getDimensionPixelSize( @@ -197,7 +288,7 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { /** * Returns the grid layout manager. */ - public GridLayoutManager getLayoutManager(Context context) { + public GridLayoutManager getLayoutManager() { return mGridLayoutMgr; } @@ -205,7 +296,11 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> { * Returns the item decoration for the recycler view. */ public RecyclerView.ItemDecoration getItemDecoration() { - return mItemDecoration; + // We don't draw any headers when we are uncomfortably dense + if (!AppsContainerView.GRID_HIDE_SECTION_HEADERS) { + return mItemDecoration; + } + return null; } /** diff --git a/src/com/android/launcher3/AppsListAdapter.java b/src/com/android/launcher3/AppsListAdapter.java deleted file mode 100644 index ffd309261..000000000 --- a/src/com/android/launcher3/AppsListAdapter.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.android.launcher3; - -import android.content.Context; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.TextView; - -/** - * The linear list view adapter for all the apps. - */ -class AppsListAdapter extends RecyclerView.Adapter<AppsListAdapter.ViewHolder> { - - /** - * ViewHolder for each row. - */ - public static class ViewHolder extends RecyclerView.ViewHolder { - public View mContent; - - public ViewHolder(View v) { - super(v); - mContent = v; - } - } - - private static final int SECTION_BREAK_VIEW_TYPE = 0; - private static final int ICON_VIEW_TYPE = 1; - private static final int EMPTY_VIEW_TYPE = 2; - - private LayoutInflater mLayoutInflater; - private AlphabeticalAppsList mApps; - private View.OnTouchListener mTouchListener; - private View.OnClickListener mIconClickListener; - private View.OnLongClickListener mIconLongClickListener; - private String mEmptySearchText; - - public AppsListAdapter(Context context, AlphabeticalAppsList apps, - View.OnTouchListener touchListener, View.OnClickListener iconClickListener, - View.OnLongClickListener iconLongClickListener) { - mApps = apps; - mLayoutInflater = LayoutInflater.from(context); - mTouchListener = touchListener; - mIconClickListener = iconClickListener; - mIconLongClickListener = iconLongClickListener; - } - - public RecyclerView.LayoutManager getLayoutManager(Context context) { - return new LinearLayoutManager(context); - } - - /** - * Sets the text to show when there are no apps. - */ - public void setEmptySearchText(String query) { - mEmptySearchText = query; - } - - @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - switch (viewType) { - case EMPTY_VIEW_TYPE: - return new ViewHolder(mLayoutInflater.inflate(R.layout.apps_empty_view, parent, - false)); - case SECTION_BREAK_VIEW_TYPE: - return new ViewHolder(new View(parent.getContext())); - case ICON_VIEW_TYPE: - // Inflate the row and all the icon children necessary - ViewGroup row = (ViewGroup) mLayoutInflater.inflate(R.layout.apps_list_row_view, - parent, false); - BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate( - R.layout.apps_list_row_icon_view, row, false); - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, - ViewGroup.LayoutParams.WRAP_CONTENT, 1); - lp.gravity = Gravity.CENTER_VERTICAL; - icon.setLayoutParams(lp); - icon.setOnTouchListener(mTouchListener); - icon.setOnClickListener(mIconClickListener); - icon.setOnLongClickListener(mIconLongClickListener); - icon.setFocusable(true); - row.addView(icon); - return new ViewHolder(row); - default: - throw new RuntimeException("Unexpected view type"); - } - } - - @Override - public void onBindViewHolder(ViewHolder holder, int position) { - switch (holder.getItemViewType()) { - case ICON_VIEW_TYPE: - AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position); - ViewGroup content = (ViewGroup) holder.mContent; - String sectionDescription = item.sectionName; - - // Bind the section header - boolean showSectionHeader = true; - if (position > 0) { - AlphabeticalAppsList.AdapterItem prevItem = - mApps.getAdapterItems().get(position - 1); - showSectionHeader = prevItem.isSectionHeader; - } - TextView tv = (TextView) content.findViewById(R.id.section); - if (showSectionHeader) { - tv.setText(sectionDescription); - tv.setVisibility(View.VISIBLE); - } else { - tv.setVisibility(View.INVISIBLE); - } - - // Bind the icon - BubbleTextView icon = (BubbleTextView) content.getChildAt(1); - icon.applyFromApplicationInfo(item.appInfo); - break; - case EMPTY_VIEW_TYPE: - TextView emptyViewText = (TextView) holder.mContent.findViewById(R.id.empty_text); - emptyViewText.setText(mEmptySearchText); - break; - } - } - - @Override - public int getItemCount() { - if (mApps.hasNoFilteredResults()) { - // For the empty view - return 1; - } - return mApps.getAdapterItems().size(); - } - - @Override - public int getItemViewType(int position) { - if (mApps.hasNoFilteredResults()) { - return EMPTY_VIEW_TYPE; - } else if (mApps.getAdapterItems().get(position).isSectionHeader) { - return SECTION_BREAK_VIEW_TYPE; - } - return ICON_VIEW_TYPE; - } -} diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index deb807501..918517ebd 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -428,6 +428,13 @@ public class DeviceProfile { } public boolean updateAppsViewNumCols(Resources res, int containerWidth) { + if (AppsContainerView.GRID_HIDE_SECTION_HEADERS) { + if (appsViewNumCols != allAppsNumCols) { + appsViewNumCols = allAppsNumCols; + return true; + } + return false; + } int appsViewLeftMarginPx = res.getDimensionPixelSize(R.dimen.apps_grid_view_start_margin); int availableAppsWidthPx = (containerWidth > 0) ? containerWidth : availableWidthPx; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 339b4e498..c0f09f486 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -135,6 +135,9 @@ public class Launcher extends Activity static final String TAG = "Launcher"; static final boolean LOGD = true; + // Temporary flag + static final boolean DISABLE_ALL_APPS_SEARCH_INTEGRATION = true; + static final boolean PROFILE_STARTUP = false; static final boolean DEBUG_WIDGETS = true; static final boolean DEBUG_STRICT_MODE = false; @@ -530,10 +533,12 @@ public class Launcher extends Activity @Override public void dismissAllApps() { - // Dismiss All Apps if we aren't already paused/invisible - if (!mPaused) { - showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, true, - null /* onCompleteRunnable */, false /* notifyLauncherCallbacks */); + if (!DISABLE_ALL_APPS_SEARCH_INTEGRATION) { + // Dismiss All Apps if we aren't already paused/invisible + if (!mPaused) { + showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, true, + null /* onCompleteRunnable */, false /* notifyLauncherCallbacks */); + } } } }); @@ -1019,7 +1024,7 @@ public class Launcher extends Activity mOnResumeState = State.NONE; // Restore the apps state if we are in all apps - if (mState == State.APPS) { + if (!Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION && mState == State.APPS) { if (mLauncherCallbacks != null) { mLauncherCallbacks.onAllAppsShown(); } @@ -1453,8 +1458,8 @@ public class Launcher extends Activity // Setup Apps mAppsView = (AppsContainerView) findViewById(R.id.apps_view); - if (mLauncherCallbacks != null && mLauncherCallbacks.overrideAllAppsSearch()) { - mAppsView.hideSearchBar(); + if (isAllAppsSearchOverridden()) { + mAppsView.hideHeaderBar(); } // Setup AppsCustomize @@ -2877,15 +2882,22 @@ public class Launcher extends Activity /** Updates the interaction state. */ public void updateInteraction(Workspace.State fromState, Workspace.State toState) { - // Only update the interacting state if we are transitioning to/from a view without an + // Only update the interacting state if we are transitioning to/from a view with an // overlay - boolean fromStateWithoutOverlay = fromState != Workspace.State.NORMAL && - fromState != Workspace.State.NORMAL_HIDDEN; - boolean toStateWithoutOverlay = toState != Workspace.State.NORMAL && - toState != Workspace.State.NORMAL_HIDDEN; - if (toStateWithoutOverlay) { + boolean fromStateWithOverlay; + boolean toStateWithOverlay; + if (Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION) { + fromStateWithOverlay = fromState != Workspace.State.NORMAL; + toStateWithOverlay = toState != Workspace.State.NORMAL; + } else { + fromStateWithOverlay = fromState != Workspace.State.NORMAL && + fromState != Workspace.State.NORMAL_HIDDEN; + toStateWithOverlay = toState != Workspace.State.NORMAL && + toState != Workspace.State.NORMAL_HIDDEN; + } + if (toStateWithOverlay) { onInteractionBegin(); - } else if (fromStateWithoutOverlay) { + } else if (fromStateWithOverlay) { onInteractionEnd(); } } @@ -3367,7 +3379,7 @@ public class Launcher extends Activity .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); if (notifyLauncherCallbacks) { // Dismiss all apps when the workspace is shown - if (mLauncherCallbacks != null) { + if (!Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION && mLauncherCallbacks != null) { mLauncherCallbacks.onAllAppsHidden(); } } @@ -3419,7 +3431,7 @@ public class Launcher extends Activity if (toState == State.APPS) { mStateTransitionAnimation.startAnimationToAllApps(animated); - if (mLauncherCallbacks != null) { + if (!Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION && mLauncherCallbacks != null) { mLauncherCallbacks.onAllAppsShown(); } } else { @@ -3472,7 +3484,7 @@ public class Launcher extends Activity if (successfulDrop) { // We need to trigger all apps hidden to notify search to update itself before the // delayed call to showWorkspace below - if (mLauncherCallbacks != null) { + if (!Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION && mLauncherCallbacks != null) { mLauncherCallbacks.onAllAppsHidden(); } } @@ -4454,9 +4466,12 @@ public class Launcher extends Activity /** * Returns whether the launcher callbacks overrides search in all apps. - * @return */ @Thunk boolean isAllAppsSearchOverridden() { + if (DISABLE_ALL_APPS_SEARCH_INTEGRATION) { + return false; + } + if (mLauncherCallbacks != null) { return mLauncherCallbacks.overrideAllAppsSearch(); } diff --git a/src/com/android/launcher3/widget/WidgetsContainerRecyclerView.java b/src/com/android/launcher3/widget/WidgetsContainerRecyclerView.java index f70f170ed..80e13bcf2 100644 --- a/src/com/android/launcher3/widget/WidgetsContainerRecyclerView.java +++ b/src/com/android/launcher3/widget/WidgetsContainerRecyclerView.java @@ -51,7 +51,7 @@ public class WidgetsContainerRecyclerView extends RecyclerView mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD; ScrollListener listener = new ScrollListener(); - addOnScrollListener(listener); + setOnScrollListener(listener); } private class ScrollListener extends RecyclerView.OnScrollListener { |