diff options
author | Tyson Miller <tmiller@cyngn.com> | 2015-11-10 08:59:15 -0800 |
---|---|---|
committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2016-01-28 17:00:28 -0800 |
commit | 7df0227f6a835641a3d41327a65845806ef070fb (patch) | |
tree | 3fcf92a1fba468facc675ad47accb08ec2f9f907 /src/com/android/launcher3/allapps | |
parent | 84dfd2a560442953af78aa77dbd6c909aed63589 (diff) | |
download | android_packages_apps_Trebuchet-7df0227f6a835641a3d41327a65845806ef070fb.tar.gz android_packages_apps_Trebuchet-7df0227f6a835641a3d41327a65845806ef070fb.tar.bz2 android_packages_apps_Trebuchet-7df0227f6a835641a3d41327a65845806ef070fb.zip |
Port Remote Folder from 12.1 to 13.
Change-Id: If8cf9d5f054e8948ead702883b79f28db26c4d8b
Diffstat (limited to 'src/com/android/launcher3/allapps')
4 files changed, 337 insertions, 315 deletions
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 0e3cba83e..f9690f509 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -57,75 +57,6 @@ import java.nio.charset.CharsetEncoder; import java.util.ArrayList; import java.util.List; - - -/** - * A merge algorithm that merges every section indiscriminately. - */ -final class FullMergeAlgorithm implements AlphabeticalAppsList.MergeAlgorithm { - - @Override - 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; - } - // Otherwise, merge every other section - return true; - } -} - -/** - * The logic we use to merge multiple sections. We only merge sections when their final row - * contains less than a certain number of icons, and stop at a specified max number of merges. - * In addition, we will try and not merge sections that identify apps from different scripts. - */ -final class SimpleSectionMergeAlgorithm implements AlphabeticalAppsList.MergeAlgorithm { - - private int mMinAppsPerRow; - private int mMinRowsInMergedSection; - private int mMaxAllowableMerges; - private CharsetEncoder mAsciiEncoder; - - public SimpleSectionMergeAlgorithm(int minAppsPerRow, int minRowsInMergedSection, - int maxNumMerges) { - mMinAppsPerRow = minAppsPerRow; - mMinRowsInMergedSection = minRowsInMergedSection; - mMaxAllowableMerges = maxNumMerges; - mAsciiEncoder = Charset.forName("US-ASCII").newEncoder(); - } - - @Override - 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 - int rows = sectionAppCount / numAppsPerRow; - int cols = sectionAppCount % numAppsPerRow; - - // Ensure that we do not merge across scripts, currently we only allow for english and - // native scripts so we can test if both can just be ascii encoded - boolean isCrossScript = false; - if (section.firstAppItem != null && withSection.firstAppItem != null) { - isCrossScript = mAsciiEncoder.canEncode(section.firstAppItem.sectionName) != - mAsciiEncoder.canEncode(withSection.firstAppItem.sectionName); - } - return (0 < cols && cols < mMinAppsPerRow) && - rows < mMinRowsInMergedSection && - mergeCount < mMaxAllowableMerges && - !isCrossScript; - } -} - /** * The all apps view container. */ @@ -139,9 +70,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc public static final int GRID_THEME_LIGHT = 1; public static final int GRID_THEME_DARK = 2; - private static final int MIN_ROWS_IN_MERGED_SECTION_PHONE = 3; - private static final int MAX_NUM_MERGES_PHONE = 1; - @Thunk Launcher mLauncher; @Thunk AlphabeticalAppsList mApps; private AllAppsGridAdapter mAdapter; @@ -204,15 +132,36 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc Selection.setSelection(mSearchQueryBuilder, 0); } + public int getNumPredictedAppsPerRow() { + return mNumPredictedAppsPerRow; + } + + /** + * Sets the current set of predicted apps by component. + * Only usable when custom predicted apps are disabled. + */ + public void setPredictedAppComponents(List<ComponentKey> apps) { + mApps.setPredictedAppComponents(apps); + updateScrubber(); + } + /** - * Sets the current set of predicted apps. + * Sets the current set of predicted apps by info. + * Only usable when custom predicated apps are enabled. */ - public void setPredictedApps(List<ComponentKey> apps) { + public void setPredictedApps(List<AppInfo> apps) { mApps.setPredictedApps(apps); updateScrubber(); } /** + * Set whether the predicted apps row will have a customized selection of apps. + */ + public void setCustomPredictedAppsEnabled(boolean enabled) { + mApps.mCustomPredictedAppsEnabled = enabled; + } + + /** * Sets the current set of apps. */ public void setApps(List<AppInfo> apps) { @@ -262,6 +211,10 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc return mApps.getApps(); } + public int getSectionStrategy() { + return mSectionStrategy; + } + private void updateSectionStrategy() { Context context = getContext(); Resources res = context.getResources(); @@ -415,17 +368,13 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc mNumAppsPerRow = grid.allAppsNumCols; mNumPredictedAppsPerRow = grid.allAppsNumPredictiveCols; - // If there is a start margin to draw section names, determine how we are going to merge - // app sections - boolean mergeSectionsFully = mSectionStrategy == SECTION_STRATEGY_GRID; - AlphabeticalAppsList.MergeAlgorithm mergeAlgorithm = mergeSectionsFully ? - new FullMergeAlgorithm() : - new SimpleSectionMergeAlgorithm((int) Math.ceil(mNumAppsPerRow / 2f), - MIN_ROWS_IN_MERGED_SECTION_PHONE, MAX_NUM_MERGES_PHONE); - mAppsRecyclerView.setNumAppsPerRow(grid, mNumAppsPerRow); mAdapter.setNumAppsPerRow(mNumAppsPerRow); - mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, mergeAlgorithm); + + boolean mergeSections = mSectionStrategy == SECTION_STRATEGY_GRID; + mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, mergeSections); + + mLauncher.getRemoteFolderManager().onMeasureDrawer(mNumPredictedAppsPerRow); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index a736f7770..3065fb428 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -37,9 +37,12 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.widget.TextView; import com.android.launcher3.AppInfo; +import com.android.launcher3.BaseRecyclerViewFastScrollBar.FastScrollFocusApplicator; +import com.android.launcher3.BaseRecyclerViewFastScrollBar.FastScrollFocusable; import com.android.launcher3.BubbleTextView; import com.android.launcher3.Launcher; import com.android.launcher3.R; +import com.android.launcher3.RemoteFolderManager; import com.android.launcher3.Utilities; import com.android.launcher3.settings.SettingsProvider; import com.android.launcher3.util.Thunk; @@ -68,6 +71,10 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. public static final int SEARCH_MARKET_DIVIDER_VIEW_TYPE = 4; // The message to continue to a market search when there are no filtered results public static final int SEARCH_MARKET_VIEW_TYPE = 5; + // Section header for customized predicated apps. + public static final int CUSTOM_PREDICTED_APPS_HEADER_VIEW_TYPE = 6; + // Additional spacing between predicted apps and regular apps. + public static final int CUSTOM_PREDICTED_APPS_FOOTER_VIEW_TYPE = 7; private boolean mIconsDimmed = false; @@ -185,36 +192,34 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. mPredictedAppsDividerPaint); hasDrawnPredictedAppsDivider = true; - } else if (showSectionNames && shouldDrawItemSection(holder, i, items)) { - // At this point, we only draw sections for each section break; + // Only customized predicted apps will draw a section name. + if (!mApps.mCustomPredictedAppsEnabled) continue; + } + + if (showSectionNames && shouldDrawItemSection(holder, items)) { + // Draw the section name for the first visible item int viewTopOffset = (2 * child.getPaddingTop()); int pos = holder.getPosition(); AlphabeticalAppsList.AdapterItem item = items.get(pos); AlphabeticalAppsList.SectionInfo sectionInfo = item.sectionInfo; - - // Draw all the sections for this index String lastSectionName = item.sectionName; - for (int j = item.sectionAppIndex; j < sectionInfo.numApps; j++, pos++) { - AlphabeticalAppsList.AdapterItem nextItem = items.get(pos); - String sectionName = nextItem.sectionName; - if (nextItem.sectionInfo != sectionInfo) { - break; - } - if (j > item.sectionAppIndex && sectionName.equals(lastSectionName)) { - continue; - } + // Find the section name bounds + PointF sectionBounds = getAndCacheSectionBounds(lastSectionName); - // Find the section name bounds - PointF sectionBounds = getAndCacheSectionBounds(sectionName); + // Calculate where to draw the section + int sectionBaseline = (int) (viewTopOffset + sectionBounds.y); + int x = mIsRtl ? + parent.getWidth() - mBackgroundPadding.left - mSectionNamesMargin : + mBackgroundPadding.left; + x += (int) ((mSectionNamesMargin - sectionBounds.x) / 2f); - // Calculate where to draw the section - int sectionBaseline = (int) (viewTopOffset + sectionBounds.y); - int x = mIsRtl ? - parent.getWidth() - mBackgroundPadding.left - mSectionNamesMargin : - mBackgroundPadding.left; - x += (int) ((mSectionNamesMargin - sectionBounds.x) / 2f); - int y = child.getTop() + sectionBaseline; + int y; + boolean fixedToRow = false; + if (item.viewType == PREDICTION_ICON_VIEW_TYPE) { + y = child.getTop() - (int) mSectionTextPaint.getTextSize() / 2; + } else { + y = child.getTop() + sectionBaseline; // Determine whether this is the last row with apps in that section, if // so, then fix the section to the row allowing it to scroll past the @@ -223,7 +228,7 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. int nextRowPos = Math.min(items.size() - 1, pos + mAppsPerRow - (appIndexInSection % mAppsPerRow)); AlphabeticalAppsList.AdapterItem nextRowItem = items.get(nextRowPos); - boolean fixedToRow = !sectionName.equals(nextRowItem.sectionName); + fixedToRow = !lastSectionName.equals(nextRowItem.sectionName); if (!fixedToRow) { y = Math.max(sectionBaseline, y); } @@ -233,22 +238,21 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. if (lastSectionHeight > 0 && y <= (lastSectionTop + lastSectionHeight)) { y += lastSectionTop - y + lastSectionHeight; } + } - // Draw the section header - if (FADE_OUT_SECTIONS) { - int alpha = 255; - if (fixedToRow) { - alpha = Math.min(255, - (int) (255 * (Math.max(0, y) / (float) sectionBaseline))); - } - mSectionTextPaint.setAlpha(alpha); + // Draw the section header + if (FADE_OUT_SECTIONS) { + int alpha = 255; + if (fixedToRow) { + alpha = Math.min(255, + (int) (255 * (Math.max(0, y) / (float) sectionBaseline))); } - c.drawText(sectionName, x, y, mSectionTextPaint); - - lastSectionTop = y; - lastSectionHeight = (int) (sectionBounds.y + mSectionHeaderOffset); - lastSectionName = sectionName; + mSectionTextPaint.setAlpha(alpha); } + c.drawText(lastSectionName, x, y, mSectionTextPaint); + + lastSectionTop = y; + lastSectionHeight = (int) (sectionBounds.y + mSectionHeaderOffset); i += (sectionInfo.numApps - item.sectionAppIndex); } } @@ -308,21 +312,22 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. /** * Returns whether to draw the section for the given child. */ - private boolean shouldDrawItemSection(ViewHolder holder, int childIndex, + private boolean shouldDrawItemSection(ViewHolder holder, List<AlphabeticalAppsList.AdapterItem> items) { int pos = holder.getPosition(); AlphabeticalAppsList.AdapterItem item = items.get(pos); // Ensure it's an icon - if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE) { + if (item.viewType != ICON_VIEW_TYPE && item.viewType != PREDICTION_ICON_VIEW_TYPE) { return false; } - // Draw the section header for the first item in each section - return (childIndex == 0) || - (items.get(pos - 1).viewType == AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE); + + return true; } } + private final RemoteFolderManager mRemoteFolderManager; + private Launcher mLauncher; private LayoutInflater mLayoutInflater; @Thunk AlphabeticalAppsList mApps; @@ -359,6 +364,9 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. private int mAllAppsTextColor; + private int mCustomPredictedAppsHeaderHeight; + private int mCustomPredictedAppsFooterHeight; + public AllAppsGridAdapter(Launcher launcher, AlphabeticalAppsList apps, View.OnTouchListener touchListener, View.OnClickListener iconClickListener, View.OnLongClickListener iconLongClickListener) { @@ -399,8 +407,7 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. mPredictedAppsDividerPaint.setColor(0x1E000000); mPredictedAppsDividerPaint.setAntiAlias(true); mPredictionBarDividerOffset = - (-res.getDimensionPixelSize(R.dimen.all_apps_prediction_icon_bottom_padding) + - res.getDimensionPixelSize(R.dimen.all_apps_icon_top_bottom_padding)) / 2; + res.getDimensionPixelSize(R.dimen.all_apps_prediction_bar_divider_offset); // Resolve the market app handling additional searches PackageManager pm = launcher.getPackageManager(); @@ -409,6 +416,8 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. if (marketInfo != null) { mMarketAppName = marketInfo.loadLabel(pm).toString(); } + + mRemoteFolderManager = launcher.getRemoteFolderManager(); } /** @@ -494,6 +503,10 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. icon.setLongPressTimeout(ViewConfiguration.get(parent.getContext()) .getLongPressTimeout()); icon.setFocusable(true); + FastScrollFocusApplicator.createApplicator(icon, + FastScrollFocusable.FAST_SCROLL_FOCUS_DIMMABLE | + FastScrollFocusable.FAST_SCROLL_FOCUS_SCALABLE); + return new ViewHolder(icon); } case PREDICTION_ICON_VIEW_TYPE: { @@ -508,7 +521,14 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. icon.setLongPressTimeout(ViewConfiguration.get(parent.getContext()) .getLongPressTimeout()); icon.setFocusable(true); - return new ViewHolder(icon); + FastScrollFocusApplicator.createApplicator(icon, + FastScrollFocusable.FAST_SCROLL_FOCUS_DIMMABLE | + FastScrollFocusable.FAST_SCROLL_FOCUS_SCALABLE); + + ViewHolder holder = new ViewHolder(icon); + mRemoteFolderManager.onCreateViewHolder(holder, viewType); + + return holder; } case EMPTY_SEARCH_VIEW_TYPE: return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search, @@ -526,6 +546,22 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. } }); return new ViewHolder(searchMarketView); + case CUSTOM_PREDICTED_APPS_HEADER_VIEW_TYPE: { + View v = mLayoutInflater.inflate( + R.layout.custom_predicted_apps_header, parent, false); + FastScrollFocusApplicator.createApplicator(v, + FastScrollFocusable.FAST_SCROLL_FOCUS_DIMMABLE); + ViewHolder holder = new ViewHolder(v); + mRemoteFolderManager.onCreateViewHolder(holder, viewType); + return holder; + } + case CUSTOM_PREDICTED_APPS_FOOTER_VIEW_TYPE: { + View v = mLayoutInflater.inflate(R.layout.custom_predicted_apps_footer, + parent, false); + ViewHolder holder = new ViewHolder(v); + mRemoteFolderManager.onCreateViewHolder(holder, viewType); + return holder; + } default: throw new RuntimeException("Unexpected view type"); } @@ -545,7 +581,8 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. icon.setTextVisibility(!hideIconLabels); } icon.applyFromApplicationInfo(info); - icon.setFastScrollDimmed(mIconsDimmed, !mIconsDimmed); + FastScrollFocusApplicator.setFastScrollDimmed(icon, mIconsDimmed, !mIconsDimmed); + FastScrollFocusApplicator.setFastScrollFocused(icon, false, !mIconsDimmed); break; } case PREDICTION_ICON_VIEW_TYPE: { @@ -556,6 +593,10 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. icon.setTextVisibility(!hideIconLabels); } icon.applyFromApplicationInfo(info); + FastScrollFocusApplicator.setFastScrollDimmed(icon, mIconsDimmed, !mIconsDimmed); + FastScrollFocusApplicator.setFastScrollFocused(icon, false, !mIconsDimmed); + + mRemoteFolderManager.onBindViewHolder(holder, info); break; } case EMPTY_SEARCH_VIEW_TYPE: @@ -576,9 +617,32 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. searchView.setVisibility(View.GONE); } break; + case CUSTOM_PREDICTED_APPS_HEADER_VIEW_TYPE: { + TextView title = (TextView) holder.mContent.findViewById(R.id.title); + title.setTextColor(mAllAppsTextColor); + FastScrollFocusApplicator.setFastScrollDimmed(holder.mContent, mIconsDimmed, !mIconsDimmed); + FastScrollFocusApplicator.setFastScrollFocused(holder.mContent, false, !mIconsDimmed); + + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) holder.mContent.getLayoutParams(); + mCustomPredictedAppsHeaderHeight = holder.mContent.getHeight() + + lp.topMargin + lp.bottomMargin; + break; + } + case CUSTOM_PREDICTED_APPS_FOOTER_VIEW_TYPE: + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) holder.mContent.getLayoutParams(); + mCustomPredictedAppsFooterHeight = holder.mContent.getHeight() + + lp.topMargin + lp.bottomMargin; } } + public int getCustomPredictedAppsOffset(int rowIndex) { + int offset = mCustomPredictedAppsHeaderHeight; + if (rowIndex > 0) offset += mCustomPredictedAppsFooterHeight; + return offset; + } + @Override public int getItemCount() { return mApps.getAdapterItems().size(); @@ -602,11 +666,15 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. int sectionTextColorId = mGridTheme == AllAppsContainerView.GRID_THEME_DARK ? R.color.all_apps_grid_section_text_color_dark : R.color.all_apps_grid_section_text_color; - mSectionTextPaint.setColor(mLauncher.getResources().getColor(sectionTextColorId)); - Resources res = mLauncher.getResources(); + mSectionTextPaint.setColor(mLauncher.getColor(sectionTextColorId)); + mAllAppsTextColor = mGridTheme == AllAppsContainerView.GRID_THEME_DARK ? - res.getColor(R.color.quantum_panel_text_color_dark) : - res.getColor(R.color.quantum_panel_text_color); + mLauncher.getColor(R.color.quantum_panel_text_color_dark) : + mLauncher.getColor(R.color.quantum_panel_text_color); + + int mPredictedAppsDividerColorId = mGridTheme == AllAppsContainerView.GRID_THEME_DARK ? + R.color.drawer_divider_dark : R.color.drawer_divider_light; + mPredictedAppsDividerPaint.setColor(mLauncher.getColor(mPredictedAppsDividerColorId)); } /** diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index 6c853a037..aaecf7a60 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -26,8 +26,8 @@ import android.util.AttributeSet; import android.view.View; import com.android.launcher3.BaseRecyclerView; -import com.android.launcher3.BaseRecyclerViewFastScrollBar; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.BaseRecyclerViewFastScrollBar.FastScrollFocusApplicator; import com.android.launcher3.R; import com.android.launcher3.Stats; import com.android.launcher3.Utilities; @@ -52,11 +52,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView private int mNumAppsPerRow; private int mSectionStrategy = AllAppsContainerView.SECTION_STRATEGY_RAGGED; - private boolean mFocusSection = false; - - @Thunk BaseRecyclerViewFastScrollBar.FastScrollFocusableView mLastFastScrollFocusedView; - @Thunk ArrayList<BaseRecyclerViewFastScrollBar.FastScrollFocusableView> - mLastFastScrollFocusedViews = new ArrayList(); + @Thunk ArrayList<View> mLastFastScrollFocusedViews = new ArrayList(); @Thunk int mPrevFastScrollFocusedPosition; @Thunk AlphabeticalAppsList.SectionInfo mPrevFastScrollFocusedSection; @Thunk int mFastScrollFrameIndex; @@ -66,6 +62,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView private final int mScrollBarMode = FAST_SCROLL_BAR_MODE_DISTRIBUTE_BY_ROW; private ScrollPositionState mScrollPosState = new ScrollPositionState(); + private boolean mFastScrollDragging; private AllAppsBackgroundDrawable mEmptySearchBackground; private int mEmptySearchBackgroundTopOffset; @@ -92,6 +89,25 @@ public class AllAppsRecyclerView extends BaseRecyclerView } mEmptySearchBackgroundTopOffset = res.getDimensionPixelSize( R.dimen.all_apps_empty_search_bg_top_offset); + + addOnScrollListener(new FocusScrollListener()); + } + + private class FocusScrollListener extends OnScrollListener { + public FocusScrollListener() { } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + switch (newState) { + case SCROLL_STATE_IDLE: + // Don't change anything if we've stopped touching the scroll bar. + if (mFastScrollDragging) { + // Animation completed, set the fast scroll state on the target views + setSectionFastScrollFocused(mPrevFastScrollFocusedPosition); + setSectionFastScrollDimmed(mPrevFastScrollFocusedPosition, false, true); + } + } + } } /** @@ -115,11 +131,12 @@ public class AllAppsRecyclerView extends BaseRecyclerView pool.setMaxRecycledViews(AllAppsGridAdapter.ICON_VIEW_TYPE, approxRows * mNumAppsPerRow); pool.setMaxRecycledViews(AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE, mNumAppsPerRow); pool.setMaxRecycledViews(AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE, approxRows); + pool.setMaxRecycledViews(AllAppsGridAdapter.CUSTOM_PREDICTED_APPS_HEADER_VIEW_TYPE, 1); + pool.setMaxRecycledViews(AllAppsGridAdapter.CUSTOM_PREDICTED_APPS_FOOTER_VIEW_TYPE, 1); } public void setSectionStrategy(int sectionStrategy) { mSectionStrategy = sectionStrategy; - mFocusSection = mSectionStrategy == AllAppsContainerView.SECTION_STRATEGY_RAGGED; } /** @@ -241,49 +258,30 @@ public class AllAppsRecyclerView extends BaseRecyclerView throw new RuntimeException("Unexpected scroll bar mode"); } - // Map the touch position back to the scroll of the recycler view - getCurScrollState(mScrollPosState); - int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight); - LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager(); - if (mFastScrollMode == FAST_SCROLL_MODE_FREE_SCROLL) { - layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction)); + // Reset the last focused section + if (mPrevFastScrollFocusedSection != lastInfo.sectionInfo) { + setSectionFastScrollDimmed(mPrevFastScrollFocusedPosition, true, true); + clearSectionFocusedItems(); } - if (mPrevFastScrollFocusedPosition != lastInfo.fastScrollToItem.position) { - if (mFocusSection) { - setSectionFastScrollDimmed(mPrevFastScrollFocusedPosition, true, true); - } else if (mLastFastScrollFocusedView != null){ - mLastFastScrollFocusedView.setFastScrollDimmed(true, true); - } - mPrevFastScrollFocusedPosition = lastInfo.fastScrollToItem.position; - mPrevFastScrollFocusedSection = - getSectionInfoForPosition(lastInfo.fastScrollToItem.position); - // Reset the last focused section - if (mFocusSection) { - clearSectionFocusedItems(); - } else if (mLastFastScrollFocusedView != null) { - mLastFastScrollFocusedView.setFastScrollFocused(false, true); - mLastFastScrollFocusedView = null; - } + mPrevFastScrollFocusedPosition = lastInfo.fastScrollToItem.position; + mPrevFastScrollFocusedSection = lastInfo.sectionInfo; - if (mFastScrollMode == FAST_SCROLL_MODE_JUMP_TO_FIRST_ICON) { - smoothSnapToPosition(mPrevFastScrollFocusedPosition, mScrollPosState); - } else if (mFastScrollMode == FAST_SCROLL_MODE_FREE_SCROLL) { - if (mFocusSection) { - setSectionFastScrollFocused(mPrevFastScrollFocusedPosition); - } else { - final ViewHolder vh = findViewHolderForPosition(mPrevFastScrollFocusedPosition); - if (vh != null && - vh.itemView instanceof - BaseRecyclerViewFastScrollBar.FastScrollFocusableView) { - mLastFastScrollFocusedView = - (BaseRecyclerViewFastScrollBar.FastScrollFocusableView) vh.itemView; - mLastFastScrollFocusedView.setFastScrollFocused(true, true); - } - } - } else { - throw new RuntimeException("Unexpected fast scroll mode"); - } + getCurScrollState(mScrollPosState); + if (mFastScrollMode == FAST_SCROLL_MODE_JUMP_TO_FIRST_ICON) { + smoothSnapToPosition(mPrevFastScrollFocusedPosition, mScrollPosState); + + setSectionFastScrollDimmed(mPrevFastScrollFocusedPosition, false, true); + setSectionFastScrollFocused(mPrevFastScrollFocusedPosition); + } else if (mFastScrollMode == FAST_SCROLL_MODE_FREE_SCROLL) { + // Map the touch position back to the scroll of the recycler view + int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight); + LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager(); + layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction)); + + setSectionFastScrollFocused(mPrevFastScrollFocusedPosition); + } else { + throw new RuntimeException("Unexpected fast scroll mode"); } return lastInfo.sectionName; } @@ -291,13 +289,9 @@ public class AllAppsRecyclerView extends BaseRecyclerView @Override public void onFastScrollCompleted() { super.onFastScrollCompleted(); - // Reset and clean up the last focused view - if (mFocusSection) { - clearSectionFocusedItems(); - } else if (mLastFastScrollFocusedView != null) { - mLastFastScrollFocusedView.setFastScrollFocused(false, true); - mLastFastScrollFocusedView = null; - } + + // Reset and clean up the last focused views + clearSectionFocusedItems(); mPrevFastScrollFocusedPosition = -1; mPrevFastScrollFocusedSection = null; } @@ -338,8 +332,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView // Calculate the current scroll position, the scrollY of the recycler view accounts for the // view padding, while the scrollBarY is drawn right up to the background padding (ignoring // padding) - int scrollY = getPaddingTop() + - (mScrollPosState.rowIndex * mScrollPosState.rowHeight) - mScrollPosState.rowTopOffset; + int scrollY = getCurrentScroll(mScrollPosState); int scrollBarY = mBackgroundPadding.top + (int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight); @@ -421,29 +414,16 @@ public class AllAppsRecyclerView extends BaseRecyclerView return new String[0]; } - private AlphabeticalAppsList.SectionInfo getSectionInfoForPosition(int position) { - List<AlphabeticalAppsList.SectionInfo> sections = - mApps.getSections(); - for (AlphabeticalAppsList.SectionInfo section : sections) { - if (section.firstAppItem.position == position) { - return section; - } - } - return null; - } - private void setSectionFastScrollFocused(int position) { if (mPrevFastScrollFocusedSection != null) { - for (int i = 0; i < mPrevFastScrollFocusedSection.numApps; i++) { + int size = mPrevFastScrollFocusedSection.numApps + + mPrevFastScrollFocusedSection.numOtherViews; + for (int i = 0; i < size; i++) { int sectionPosition = position+i; final ViewHolder vh = findViewHolderForAdapterPosition(sectionPosition); - if (vh != null && - vh.itemView instanceof - BaseRecyclerViewFastScrollBar.FastScrollFocusableView) { - final BaseRecyclerViewFastScrollBar.FastScrollFocusableView view = - (BaseRecyclerViewFastScrollBar.FastScrollFocusableView) vh.itemView; - view.setFastScrollFocused(true, true); - mLastFastScrollFocusedViews.add(view); + if (vh != null) { + FastScrollFocusApplicator.setFastScrollFocused(vh.itemView, true, true); + mLastFastScrollFocusedViews.add(vh.itemView); } } } @@ -451,15 +431,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView private void setSectionFastScrollDimmed(int position, boolean dimmed, boolean animate) { if (mPrevFastScrollFocusedSection != null) { - for (int i = 0; i < mPrevFastScrollFocusedSection.numApps; i++) { + int size = mPrevFastScrollFocusedSection.numApps + + mPrevFastScrollFocusedSection.numOtherViews; + for (int i = 0; i < size; i++) { int sectionPosition = position+i; final ViewHolder vh = findViewHolderForAdapterPosition(sectionPosition); - if (vh != null && - vh.itemView instanceof - BaseRecyclerViewFastScrollBar.FastScrollFocusableView) { - final BaseRecyclerViewFastScrollBar.FastScrollFocusableView view = - (BaseRecyclerViewFastScrollBar.FastScrollFocusableView) vh.itemView; - view.setFastScrollDimmed(dimmed, animate); + if (vh != null) { + FastScrollFocusApplicator.setFastScrollDimmed(vh.itemView, dimmed, animate); } } } @@ -468,9 +446,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView private void clearSectionFocusedItems() { final int N = mLastFastScrollFocusedViews.size(); for (int i = 0; i < N; i++) { - BaseRecyclerViewFastScrollBar.FastScrollFocusableView view = - mLastFastScrollFocusedViews.get(i); - view.setFastScrollFocused(false, true); + View view = mLastFastScrollFocusedViews.get(i); + FastScrollFocusApplicator.setFastScrollFocused(view, false, true); } mLastFastScrollFocusedViews.clear(); } @@ -478,6 +455,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView @Override public void setFastScrollDragging(boolean dragging) { ((AllAppsGridAdapter) getAdapter()).setIconsDimmed(dragging); + mFastScrollDragging = dragging; } /** @@ -488,28 +466,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView @Override public void run() { if (mFastScrollFrameIndex < mFastScrollFrames.length) { - if (mFocusSection) { - setSectionFastScrollDimmed(mPrevFastScrollFocusedPosition, false, true); - } + setSectionFastScrollDimmed(mPrevFastScrollFocusedPosition, false, true); scrollBy(0, mFastScrollFrames[mFastScrollFrameIndex]); mFastScrollFrameIndex++; postOnAnimation(mSmoothSnapNextFrameRunnable); } else { - if (mFocusSection) { - setSectionFastScrollFocused(mPrevFastScrollFocusedPosition); - } else { - // Animation completed, set the fast scroll state on the target view - final ViewHolder vh = findViewHolderForPosition(mPrevFastScrollFocusedPosition); - if (vh != null && - vh.itemView instanceof - BaseRecyclerViewFastScrollBar.FastScrollFocusableView && - mLastFastScrollFocusedView != vh.itemView) { - mLastFastScrollFocusedView = - (BaseRecyclerViewFastScrollBar.FastScrollFocusableView) vh.itemView; - mLastFastScrollFocusedView.setFastScrollFocused(true, true); - mLastFastScrollFocusedView.setFastScrollDimmed(false, true); - } - } + setSectionFastScrollDimmed(mPrevFastScrollFocusedPosition, false, false); + setSectionFastScrollFocused(mPrevFastScrollFocusedPosition); } } }; @@ -523,8 +486,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 curScrollY = getPaddingTop() + - (scrollPosState.rowIndex * scrollPosState.rowHeight) - scrollPosState.rowTopOffset; + int curScrollY = getCurrentScroll(scrollPosState); int newScrollY = getScrollAtPosition(position, scrollPosState.rowHeight); int numFrames = mFastScrollFrames.length; for (int i = 0; i < numFrames; i++) { @@ -558,7 +520,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE || item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) { stateOut.rowIndex = item.rowIndex; - stateOut.rowTopOffset = getLayoutManager().getDecoratedTop(child); + stateOut.rowTopOffset = getLayoutManager().getDecoratedTop(child) - + getAdditionalScrollHeight(stateOut.rowIndex); stateOut.rowHeight = child.getHeight(); break; } @@ -566,6 +529,16 @@ public class AllAppsRecyclerView extends BaseRecyclerView } } + @Override + protected int getAvailableScrollHeight(int rowCount, int rowHeight) { + return super.getAvailableScrollHeight(rowCount, rowHeight) + + getAdditionalScrollHeight(mApps.getAdapterItems().size()); + } + + private int getAdditionalScrollHeight(int rowIndex) { + return ((AllAppsGridAdapter) getAdapter()).getCustomPredictedAppsOffset(rowIndex); + } + /** * Returns the scrollY for the given position in the adapter. */ @@ -574,6 +547,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE || item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) { int offset = item.rowIndex > 0 ? getPaddingTop() : 0; + offset += ((AllAppsGridAdapter) getAdapter()). + getCustomPredictedAppsOffset(item.rowIndex); return offset + item.rowIndex * rowHeight; } else { return 0; diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 98d747936..9d30f81ee 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.allapps; -import android.content.ComponentName; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.Log; @@ -32,6 +31,7 @@ import cyanogenmod.providers.CMSettings; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; @@ -49,6 +49,9 @@ public class AlphabeticalAppsList { private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION = 0; private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS = 1; + private static final String CUSTOM_PREDICTIONS_SCRUBBER = "★"; + private static final String CUSTOM_PREDICTIONS_HEADER = "☆"; + private final int mFastScrollDistributionMode = FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS; /** @@ -57,6 +60,8 @@ public class AlphabeticalAppsList { public static class SectionInfo { // The number of applications in this section public int numApps; + // The number of drawn (non-app) adapter items in this section. + public int numOtherViews; // The section break AdapterItem for this section public AdapterItem sectionBreakItem; // The first app AdapterItem for this section @@ -64,19 +69,21 @@ public class AlphabeticalAppsList { } /** - * Info about a fast scroller section, depending if sections are merged, the fast scroller - * sections will not be the same set as the section headers. + * Info about a fast scroller section. */ public static class FastScrollSectionInfo { // The section name public String sectionName; + // Info for this section + public SectionInfo sectionInfo; // The AdapterItem to scroll to for this section public AdapterItem fastScrollToItem; // The touch fraction that should map to this fast scroll section info public float touchFraction; - public FastScrollSectionInfo(String sectionName) { + public FastScrollSectionInfo(String sectionName, SectionInfo sectionInfo) { this.sectionName = sectionName; + this.sectionInfo = sectionInfo; } } @@ -158,14 +165,20 @@ public class AlphabeticalAppsList { item.position = pos; return item; } - } - /** - * Common interface for different merging strategies. - */ - public interface MergeAlgorithm { - boolean continueMerging(SectionInfo section, SectionInfo withSection, - int sectionAppCount, int numAppsPerRow, int mergeCount); + public static AdapterItem asCustomPredictedAppsHeader(int pos) { + AdapterItem item = new AdapterItem(); + item.viewType = AllAppsGridAdapter.CUSTOM_PREDICTED_APPS_HEADER_VIEW_TYPE; + item.position = pos; + return item; + } + + public static AdapterItem asPredictedAppsSpacer(int pos) { + AdapterItem item = new AdapterItem(); + item.viewType = AllAppsGridAdapter.CUSTOM_PREDICTED_APPS_FOOTER_VIEW_TYPE; + item.position = pos; + return item; + } } private Launcher mLauncher; @@ -180,7 +193,7 @@ public class AlphabeticalAppsList { private List<AdapterItem> mAdapterItems = new ArrayList<>(); // The set of sections for the apps with the current filter private List<SectionInfo> mSections = new ArrayList<>(); - // The set of sections that we allow fast-scrolling to (includes non-merged sections) + // The set of sections that we allow fast-scrolling to private List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>(); // The set of predicted app component names private List<ComponentKey> mPredictedAppComponents = new ArrayList<>(); @@ -192,11 +205,13 @@ public class AlphabeticalAppsList { private RecyclerView.Adapter mAdapter; private AlphabeticIndexCompat mIndexer; private AppNameComparator mAppNameComparator; - private MergeAlgorithm mMergeAlgorithm; + private boolean mMergeSections; private int mNumAppsPerRow; private int mNumPredictedAppsPerRow; private int mNumAppRowsInAdapter; + boolean mCustomPredictedAppsEnabled; + public AlphabeticalAppsList(Context context) { mLauncher = (Launcher) context; mIndexer = new AlphabeticIndexCompat(context); @@ -207,10 +222,10 @@ public class AlphabeticalAppsList { * Sets the number of apps per row. */ public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow, - MergeAlgorithm mergeAlgorithm) { + boolean mergeSections) { mNumAppsPerRow = numAppsPerRow; mNumPredictedAppsPerRow = numPredictedAppsPerRow; - mMergeAlgorithm = mergeAlgorithm; + mMergeSections = mergeSections; updateAdapterItems(); } @@ -292,13 +307,33 @@ public class AlphabeticalAppsList { * Sets the current set of predicted apps. Since this can be called before we get the full set * of applications, we should merge the results only in onAppsUpdated() which is idempotent. */ - public void setPredictedApps(List<ComponentKey> apps) { + public void setPredictedAppComponents(List<ComponentKey> apps) { + if (!mCustomPredictedAppsEnabled) { + throw new IllegalStateException("Unable to set predicted app components when adapter " + + "is set to accept a custom predicted apps list."); + } + mPredictedAppComponents.clear(); mPredictedAppComponents.addAll(apps); onAppsUpdated(); } /** + * Sets the current set of predicted apps. This uses the info directly, so we do not + * merge data in {@link #onAppsUpdated()}, but go directly to {@link #updateAdapterItems()}. + */ + public void setPredictedApps(List<AppInfo> apps) { + if (!mCustomPredictedAppsEnabled) { + throw new IllegalStateException("Unable to set predicted apps directly when adapter " + + "is not set to accept a custom predicted apps list."); + } + + mPredictedApps.clear(); + mPredictedApps.addAll(apps); + updateAdapterItems(); + } + + /** * Sets the current set of apps. */ public void setApps(List<AppInfo> apps) { @@ -415,27 +450,48 @@ public class AlphabeticalAppsList { } // Process the predicted app components - mPredictedApps.clear(); - if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) { - for (ComponentKey ck : mPredictedAppComponents) { - AppInfo info = mComponentToAppMap.get(ck); - if (info != null) { - mPredictedApps.add(info); - } else { - if (LauncherAppState.isDogfoodBuild()) { - Log.e(TAG, "Predicted app not found: " + ck.flattenToString(mLauncher)); + boolean hasPredictedApps; + + // We haven't measured yet. Skip this for now. We will set properly after measure. + if (mNumPredictedAppsPerRow == 0) { + hasPredictedApps = false; + } else if (mCustomPredictedAppsEnabled) { + hasPredictedApps = !mPredictedApps.isEmpty(); + } else { + mPredictedApps.clear(); + hasPredictedApps = mPredictedAppComponents != null && + !mPredictedAppComponents.isEmpty(); + } + + if (hasPredictedApps && !hasFilter()) { + if (!mCustomPredictedAppsEnabled) { + for (ComponentKey ck : mPredictedAppComponents) { + AppInfo info = mComponentToAppMap.get(ck); + if (info != null) { + mPredictedApps.add(info); + } else { + if (LauncherAppState.isDogfoodBuild()) { + Log.e(TAG, "Predicted app not found: " + ck.flattenToString(mLauncher)); + } + } + // Stop at the number of predicted apps + if (mPredictedApps.size() == mNumPredictedAppsPerRow) { + break; } } - // Stop at the number of predicted apps - if (mPredictedApps.size() == mNumPredictedAppsPerRow) { - break; + } else { + // Shrink to column count. + if (mPredictedApps.size() > mNumPredictedAppsPerRow) { + mPredictedApps.subList(mNumAppsPerRow, mPredictedApps.size()).clear(); } } if (!mPredictedApps.isEmpty()) { // Add a section for the predictions lastSectionInfo = new SectionInfo(); - lastFastScrollerSectionInfo = new FastScrollSectionInfo(""); + String text = mCustomPredictedAppsEnabled ? CUSTOM_PREDICTIONS_SCRUBBER : " "; + lastFastScrollerSectionInfo = + new FastScrollSectionInfo(text, lastSectionInfo); AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo); mSections.add(lastSectionInfo); mFastScrollerSections.add(lastFastScrollerSectionInfo); @@ -443,8 +499,9 @@ public class AlphabeticalAppsList { // Add the predicted app items for (AppInfo info : mPredictedApps) { + text = mCustomPredictedAppsEnabled ? CUSTOM_PREDICTIONS_HEADER : " "; AdapterItem appItem = AdapterItem.asPredictedApp(position++, lastSectionInfo, - "", lastSectionInfo.numApps++, info, appIndex++); + text, lastSectionInfo.numApps++, info, appIndex++); if (lastSectionInfo.firstAppItem == null) { lastSectionInfo.firstAppItem = appItem; lastFastScrollerSectionInfo.fastScrollToItem = appItem; @@ -452,6 +509,11 @@ public class AlphabeticalAppsList { mAdapterItems.add(appItem); mFilteredApps.add(info); } + + if (mCustomPredictedAppsEnabled) { + position = mLauncher.getRemoteFolderManager().onUpdateAdapterItems( + mAdapterItems, lastFastScrollerSectionInfo, lastSectionInfo, position); + } } } @@ -470,7 +532,7 @@ public class AlphabeticalAppsList { if (lastSectionInfo == null || !sectionName.equals(lastSectionName)) { lastSectionName = sectionName; lastSectionInfo = new SectionInfo(); - lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName); + lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName, lastSectionInfo); mSections.add(lastSectionInfo); mFastScrollerSections.add(lastFastScrollerSectionInfo); @@ -502,7 +564,7 @@ public class AlphabeticalAppsList { mAdapterItems.add(AdapterItem.asMarketSearch(position++)); } - // Merge multiple sections together as requested by the merge strategy for this device + // Merge multiple sections together as needed. mergeSections(); if (mNumAppsPerRow != 0) { @@ -536,7 +598,8 @@ public class AlphabeticalAppsList { for (FastScrollSectionInfo info : mFastScrollerSections) { AdapterItem item = info.fastScrollToItem; if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE && - item.viewType != AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) { + item.viewType != AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE && + item.viewType != AllAppsGridAdapter.CUSTOM_PREDICTED_APPS_HEADER_VIEW_TYPE) { info.touchFraction = 0f; continue; } @@ -551,7 +614,8 @@ public class AlphabeticalAppsList { for (FastScrollSectionInfo info : mFastScrollerSections) { AdapterItem item = info.fastScrollToItem; if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE && - item.viewType != AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) { + item.viewType != AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE && + item.viewType != AllAppsGridAdapter.CUSTOM_PREDICTED_APPS_HEADER_VIEW_TYPE) { info.touchFraction = 0f; continue; } @@ -588,52 +652,18 @@ public class AlphabeticalAppsList { */ private void mergeSections() { // Ignore merging until we have an algorithm and a valid row size - if (mMergeAlgorithm == null || mNumAppsPerRow == 0) { + if (!mMergeSections || mNumAppsPerRow == 0 || hasFilter()) { return; } - // Go through each section and try and merge some of the sections - if (!hasFilter()) { - int sectionAppCount = 0; - for (int i = 0; i < mSections.size() - 1; i++) { - SectionInfo section = mSections.get(i); - sectionAppCount = section.numApps; - int mergeCount = 1; - - // Merge rows based on the current strategy - while (i < (mSections.size() - 1) && - mMergeAlgorithm.continueMerging(section, mSections.get(i + 1), - sectionAppCount, mNumAppsPerRow, mergeCount)) { - SectionInfo nextSection = mSections.remove(i + 1); - - // Remove the next section break - mAdapterItems.remove(nextSection.sectionBreakItem); - int pos = mAdapterItems.indexOf(section.firstAppItem); - - // Point the section for these new apps to the merged section - int nextPos = pos + section.numApps; - for (int j = nextPos; j < (nextPos + nextSection.numApps); j++) { - AdapterItem item = mAdapterItems.get(j); - item.sectionInfo = section; - item.sectionAppIndex += section.numApps; - } - - // Update the following adapter items of the removed section item - pos = mAdapterItems.indexOf(nextSection.firstAppItem); - for (int j = pos; j < mAdapterItems.size(); j++) { - AdapterItem item = mAdapterItems.get(j); - item.position--; - } - section.numApps += nextSection.numApps; - sectionAppCount += nextSection.numApps; - - if (DEBUG) { - Log.d(TAG, "Merging: " + nextSection.firstAppItem.sectionName + - " to " + section.firstAppItem.sectionName + - " mergedNumRows: " + (sectionAppCount / mNumAppsPerRow)); - } - mergeCount++; - } + Iterator<AdapterItem> iter = mAdapterItems.iterator(); + int positionShift = 0; + while (iter.hasNext()) { + AdapterItem item = iter.next(); + item.position -= positionShift; + if (item.viewType == AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE) { + iter.remove(); + positionShift++; } } } |