summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/allapps
diff options
context:
space:
mode:
authorTyson Miller <tmiller@cyngn.com>2015-11-10 08:59:15 -0800
committerGerrit Code Review <gerrit@cyanogenmod.org>2016-01-28 17:00:28 -0800
commit7df0227f6a835641a3d41327a65845806ef070fb (patch)
tree3fcf92a1fba468facc675ad47accb08ec2f9f907 /src/com/android/launcher3/allapps
parent84dfd2a560442953af78aa77dbd6c909aed63589 (diff)
downloadandroid_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')
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java115
-rw-r--r--src/com/android/launcher3/allapps/AllAppsGridAdapter.java166
-rw-r--r--src/com/android/launcher3/allapps/AllAppsRecyclerView.java187
-rw-r--r--src/com/android/launcher3/allapps/AlphabeticalAppsList.java184
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++;
}
}
}