summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWinson Chung <winsonc@google.com>2015-05-08 12:04:45 -0700
committerWinson Chung <winsonc@google.com>2015-05-09 00:39:01 +0000
commit99d96ba6c8e3258f7d99a33d49da2aeb0da5d862 (patch)
tree854d21073eee42e75ceac873413af1ba897cefc1 /src
parent3253bf40881c648fbd84fd125752e084a7c6ce91 (diff)
downloadandroid_packages_apps_Trebuchet-99d96ba6c8e3258f7d99a33d49da2aeb0da5d862.tar.gz
android_packages_apps_Trebuchet-99d96ba6c8e3258f7d99a33d49da2aeb0da5d862.tar.bz2
android_packages_apps_Trebuchet-99d96ba6c8e3258f7d99a33d49da2aeb0da5d862.zip
Fixing issue with fast scroller not showing sub-section headers.
- Removed some old logic to draw merged section headers Change-Id: I2a7ff9948a3dce253d6bdcda89cc9f222faab309
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/AlphabeticalAppsList.java112
-rw-r--r--src/com/android/launcher3/AppsContainerRecyclerView.java44
-rw-r--r--src/com/android/launcher3/AppsContainerView.java1
-rw-r--r--src/com/android/launcher3/AppsGridAdapter.java69
4 files changed, 99 insertions, 127 deletions
diff --git a/src/com/android/launcher3/AlphabeticalAppsList.java b/src/com/android/launcher3/AlphabeticalAppsList.java
index 824ccde64..70e36a744 100644
--- a/src/com/android/launcher3/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/AlphabeticalAppsList.java
@@ -82,17 +82,30 @@ public class AlphabeticalAppsList {
* Info about a section in the alphabetic list
*/
public static class SectionInfo {
- // The name of this section
- public String sectionName;
// The number of applications in this section
- public int numAppsInSection;
- // The section AdapterItem for this section
- public AdapterItem sectionItem;
+ public int numApps;
+ // The section break AdapterItem for this section
+ public AdapterItem sectionBreakItem;
// The first app AdapterItem for this section
public AdapterItem firstAppItem;
+ }
- public SectionInfo(String name) {
- sectionName = name;
+ /**
+ * 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.
+ */
+ public static class FastScrollSectionInfo {
+ // The section name
+ public String sectionName;
+ // To map the touch (from 0..1) to the index in the app list to jump to in the fast
+ // scroller, we use the fraction in range (0..1) of the app index / total app count.
+ public float appRangeFraction;
+ // The AdapterItem to scroll to for this section
+ public AdapterItem appItem;
+
+ public FastScrollSectionInfo(String sectionName, float appRangeFraction) {
+ this.sectionName = sectionName;
+ this.appRangeFraction = appRangeFraction;
}
}
@@ -100,31 +113,30 @@ public class AlphabeticalAppsList {
* Info about a particular adapter item (can be either section or app)
*/
public static class AdapterItem {
+ /** Section & App properties */
// The index of this adapter item in the list
public int position;
// Whether or not the item at this adapter position is a section or not
public boolean isSectionHeader;
- // The name of this section, or the section section name of the app. Note that if this
- // app was merged into another section, then this may be a different name than the
- // sectionInfo's sectionName
- public String sectionName;
- // The section to which this app belongs
+ // The section for this item
public SectionInfo sectionInfo;
+
+ /** App-only properties */
+ // The section name of this app. Note that there can be multiple items with different
+ // sectionNames in the same section
+ public String sectionName = null;
// The index of this app in the section
- public int sectionAppIndex;
- // The associated AppInfo, or null if this adapter item is a section
- public AppInfo appInfo;
- // The index of this app (not including sections), or -1 if this adapter item is a section
- public int appIndex;
+ public int sectionAppIndex = -1;
+ // The associated AppInfo for the app
+ public AppInfo appInfo = null;
+ // The index of this app not including sections
+ public int appIndex = -1;
- public static AdapterItem asSection(int pos, SectionInfo section) {
+ public static AdapterItem asSectionBreak(int pos, SectionInfo section) {
AdapterItem item = new AdapterItem();
item.position = pos;
item.isSectionHeader = true;
item.sectionInfo = section;
- item.sectionName = section.sectionName;
- item.appInfo = null;
- item.appIndex = -1;
return item;
}
@@ -156,6 +168,7 @@ public class AlphabeticalAppsList {
private List<AppInfo> mFilteredApps = new ArrayList<>();
private List<AdapterItem> mSectionedFilteredApps = new ArrayList<>();
private List<SectionInfo> mSections = new ArrayList<>();
+ private List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
private RecyclerView.Adapter mAdapter;
private Filter mFilter;
private AlphabeticIndexCompat mIndexer;
@@ -194,6 +207,13 @@ public class AlphabeticalAppsList {
}
/**
+ * Returns fast scroller sections of all the current filtered applications.
+ */
+ public List<FastScrollSectionInfo> getFastScrollerSections() {
+ return mFastScrollerSections;
+ }
+
+ /**
* Returns the current filtered list of applications broken down into their sections.
*/
public List<AdapterItem> getAdapterItems() {
@@ -321,10 +341,13 @@ public class AlphabeticalAppsList {
mFilteredApps.clear();
mSections.clear();
mSectionedFilteredApps.clear();
+ mFastScrollerSections.clear();
SectionInfo lastSectionInfo = null;
+ String lastSectionName = null;
+ FastScrollSectionInfo lastFastScrollerSectionInfo = null;
int position = 0;
int appIndex = 0;
- int sectionAppIndex = 0;
+ int numApps = mApps.size();
for (AppInfo info : mApps) {
String sectionName = mIndexer.computeSectionName(info.title.toString().trim());
@@ -334,26 +357,29 @@ public class AlphabeticalAppsList {
}
// Create a new section if necessary
- if (lastSectionInfo == null || !lastSectionInfo.sectionName.equals(sectionName)) {
- lastSectionInfo = new SectionInfo(sectionName);
- sectionAppIndex = 0;
+ if (lastSectionInfo == null || !sectionName.equals(lastSectionName)) {
+ lastSectionName = sectionName;
+ lastSectionInfo = new SectionInfo();
mSections.add(lastSectionInfo);
+ lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName,
+ (float) appIndex / numApps);
+ mFastScrollerSections.add(lastFastScrollerSectionInfo);
// Create a new section item, this item is used to break the flow of items in the
// list
- AdapterItem sectionItem = AdapterItem.asSection(position++, lastSectionInfo);
+ AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
if (!AppsContainerView.GRID_HIDE_SECTION_HEADERS && !hasFilter()) {
- lastSectionInfo.sectionItem = sectionItem;
+ lastSectionInfo.sectionBreakItem = sectionItem;
mSectionedFilteredApps.add(sectionItem);
}
}
// Create an app item
AdapterItem appItem = AdapterItem.asApp(position++, lastSectionInfo, sectionName,
- sectionAppIndex++, info, appIndex++);
- lastSectionInfo.numAppsInSection++;
+ lastSectionInfo.numApps++, info, appIndex++);
if (lastSectionInfo.firstAppItem == null) {
lastSectionInfo.firstAppItem = appItem;
+ lastFastScrollerSectionInfo.appItem = appItem;
}
mSectionedFilteredApps.add(appItem);
mFilteredApps.add(info);
@@ -365,9 +391,9 @@ public class AlphabeticalAppsList {
int sectionAppCount = 0;
for (int i = 0; i < mSections.size(); i++) {
SectionInfo section = mSections.get(i);
- String mergedSectionName = section.sectionName;
- sectionAppCount = section.numAppsInSection;
+ sectionAppCount = section.numApps;
int mergeCount = 1;
+
// Merge rows if the last app in this section is in a column that is greater than
// 0, but less than the min number of apps per row. In addition, apply the
// constraint to stop merging if the number of rows in the section is greater than
@@ -378,35 +404,25 @@ public class AlphabeticalAppsList {
(i + 1) < mSections.size()) {
SectionInfo nextSection = mSections.remove(i + 1);
- // Merge the section names
- if (AppsContainerView.GRID_MERGE_SECTION_HEADERS) {
- mergedSectionName += nextSection.sectionName;
- }
// Remove the next section break
- mSectionedFilteredApps.remove(nextSection.sectionItem);
+ mSectionedFilteredApps.remove(nextSection.sectionBreakItem);
int pos = mSectionedFilteredApps.indexOf(section.firstAppItem);
- if (AppsContainerView.GRID_MERGE_SECTION_HEADERS) {
- // Update the section names for the two sections
- for (int j = pos; j < (pos + section.numAppsInSection + nextSection.numAppsInSection); j++) {
- AdapterItem item = mSectionedFilteredApps.get(j);
- item.sectionName = mergedSectionName;
- item.sectionInfo = section;
- }
- }
// Point the section for these new apps to the merged section
- for (int j = pos + section.numAppsInSection; j < (pos + section.numAppsInSection + nextSection.numAppsInSection); j++) {
+ int nextPos = pos + section.numApps;
+ for (int j = nextPos; j < (nextPos + nextSection.numApps); j++) {
AdapterItem item = mSectionedFilteredApps.get(j);
item.sectionInfo = section;
- item.sectionAppIndex += section.numAppsInSection;
+ item.sectionAppIndex += section.numApps;
}
+
// Update the following adapter items of the removed section item
pos = mSectionedFilteredApps.indexOf(nextSection.firstAppItem);
for (int j = pos; j < mSectionedFilteredApps.size(); j++) {
AdapterItem item = mSectionedFilteredApps.get(j);
item.position--;
}
- section.numAppsInSection += nextSection.numAppsInSection;
- sectionAppCount += nextSection.numAppsInSection;
+ section.numApps += nextSection.numApps;
+ sectionAppCount += nextSection.numApps;
mergeCount++;
if (mergeCount >= mMaxAllowableMerges) {
break;
diff --git a/src/com/android/launcher3/AppsContainerRecyclerView.java b/src/com/android/launcher3/AppsContainerRecyclerView.java
index fb5f6d436..6556cf920 100644
--- a/src/com/android/launcher3/AppsContainerRecyclerView.java
+++ b/src/com/android/launcher3/AppsContainerRecyclerView.java
@@ -254,8 +254,9 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
mFastScrollTextPaint.setAlpha((int) (mFastScrollAlpha * 255));
mFastScrollTextPaint.getTextBounds(mFastScrollSectionName, 0,
mFastScrollSectionName.length(), mFastScrollTextBounds);
+ float textWidth = mFastScrollTextPaint.measureText(mFastScrollSectionName);
canvas.drawText(mFastScrollSectionName,
- (bgBounds.width() - mFastScrollTextBounds.width()) / 2,
+ (bgBounds.width() - textWidth) / 2,
bgBounds.height() - (bgBounds.height() - mFastScrollTextBounds.height()) / 2,
mFastScrollTextPaint);
canvas.restoreToCount(restoreCount);
@@ -285,38 +286,33 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
}
/**
- * Maps the progress (from 0..1) to the position that should be visible
+ * Maps the touch (from 0..1) to the adapter position that should be visible.
*/
- private String scrollToPositionAtProgress(float progress) {
- List<AlphabeticalAppsList.SectionInfo> sections = mApps.getSections();
- if (sections.isEmpty()) {
+ private String scrollToPositionAtProgress(float touchFraction) {
+ // Ensure that we have any sections
+ List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
+ mApps.getFastScrollerSections();
+ if (fastScrollSections.isEmpty()) {
return "";
}
- // Find the position of the first application in the section that contains the row at the
- // current progress
- List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
- int rowAtProgress = (int) (progress * getNumRows());
- int rowCount = 0;
- AlphabeticalAppsList.SectionInfo lastSectionInfo = null;
- for (AlphabeticalAppsList.SectionInfo section : sections) {
- int numRowsInSection = (int) Math.ceil((float) section.numAppsInSection / mNumAppsPerRow);
- if (rowCount + numRowsInSection >= rowAtProgress) {
- lastSectionInfo = section;
+ AlphabeticalAppsList.FastScrollSectionInfo lastScrollSection = fastScrollSections.get(0);
+ for (int i = 1; i < fastScrollSections.size(); i++) {
+ AlphabeticalAppsList.FastScrollSectionInfo scrollSection = fastScrollSections.get(i);
+ if (lastScrollSection.appRangeFraction <= touchFraction &&
+ touchFraction < scrollSection.appRangeFraction) {
break;
}
- rowCount += numRowsInSection;
+ lastScrollSection = scrollSection;
}
- int position = items.indexOf(lastSectionInfo.firstAppItem);
// Scroll the position into view, anchored at the top of the screen if possible. We call the
// scroll method on the LayoutManager directly since it is not exposed by RecyclerView.
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
stopScroll();
- layoutManager.scrollToPositionWithOffset(position, 0);
+ layoutManager.scrollToPositionWithOffset(lastScrollSection.appItem.position, 0);
- // Return the section name of the row
- return lastSectionInfo.sectionName;
+ return lastScrollSection.sectionName;
}
/**
@@ -392,11 +388,11 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
int appIndex = 0;
int rowCount = 0;
for (AlphabeticalAppsList.SectionInfo info : sections) {
- int numRowsInSection = (int) Math.ceil((float) info.numAppsInSection / mNumAppsPerRow);
- if (appIndex + info.numAppsInSection > position) {
+ int numRowsInSection = (int) Math.ceil((float) info.numApps / mNumAppsPerRow);
+ if (appIndex + info.numApps > position) {
return rowCount + ((position - appIndex) / mNumAppsPerRow);
}
- appIndex += info.numAppsInSection;
+ appIndex += info.numApps;
rowCount += numRowsInSection;
}
return appIndex;
@@ -409,7 +405,7 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
List<AlphabeticalAppsList.SectionInfo> sections = mApps.getSections();
int rowCount = 0;
for (AlphabeticalAppsList.SectionInfo info : sections) {
- int numRowsInSection = (int) Math.ceil((float) info.numAppsInSection / mNumAppsPerRow);
+ int numRowsInSection = (int) Math.ceil((float) info.numApps / mNumAppsPerRow);
rowCount += numRowsInSection;
}
return rowCount;
diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java
index 9c05d0d10..993f9c857 100644
--- a/src/com/android/launcher3/AppsContainerView.java
+++ b/src/com/android/launcher3/AppsContainerView.java
@@ -46,7 +46,6 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
View.OnClickListener, View.OnLongClickListener {
public static final boolean GRID_MERGE_SECTIONS = true;
- public static final boolean GRID_MERGE_SECTION_HEADERS = false;
public static final boolean GRID_HIDE_SECTION_HEADERS = false;
private static final boolean ALLOW_SINGLE_APP_LAUNCH = true;
diff --git a/src/com/android/launcher3/AppsGridAdapter.java b/src/com/android/launcher3/AppsGridAdapter.java
index d83d6c97c..259740c60 100644
--- a/src/com/android/launcher3/AppsGridAdapter.java
+++ b/src/com/android/launcher3/AppsGridAdapter.java
@@ -4,7 +4,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
-import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
@@ -86,8 +85,6 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
private HashMap<String, PointF> mCachedSectionBounds = new HashMap<>();
private Rect mTmpBounds = new Rect();
- private String[] mTmpSections = new String[2];
- private PointF[] mTmpSectionBounds = new PointF[2];
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
@@ -111,26 +108,24 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
// Draw all the sections for this index
String lastSectionName = item.sectionName;
- for (int j = item.sectionAppIndex; j < sectionInfo.numAppsInSection;j++, pos++) {
+ 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 && nextItem.sectionName.equals(lastSectionName)) {
+ if (j > item.sectionAppIndex && sectionName.equals(lastSectionName)) {
continue;
}
// Find the section code points
- getSectionLetters(nextItem.sectionName, mTmpSections, mTmpSectionBounds);
- String sectionBegin = mTmpSections[0];
- String sectionEnd = mTmpSections[1];
- PointF sectionBeginBounds = mTmpSectionBounds[0];
- PointF sectionEndBounds = mTmpSectionBounds[1];
+ PointF sectionBounds = getAndCacheSectionBounds(sectionName);
// Calculate where to draw the section
- int sectionBaseline = (int) (viewTopOffset + sectionBeginBounds.y);
+ int sectionBaseline = (int) (viewTopOffset + sectionBounds.y);
int x = mIsRtl ? parent.getWidth() - mPaddingStart - mStartMargin :
mPaddingStart;
+ x += (int) ((mStartMargin - sectionBounds.x) / 2f);
int y = child.getTop() + sectionBaseline;
// Determine whether this is the last row with apps in that section, if
@@ -139,7 +134,8 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
int appIndexInSection = items.get(pos).sectionAppIndex;
int nextRowPos = Math.min(items.size() - 1,
pos + mAppsPerRow - (appIndexInSection % mAppsPerRow));
- boolean fixedToRow = !items.get(nextRowPos).sectionName.equals(nextItem.sectionName);
+ AlphabeticalAppsList.AdapterItem nextRowItem = items.get(nextRowPos);
+ boolean fixedToRow = !sectionName.equals(nextRowItem.sectionName);
if (!fixedToRow) {
y = Math.max(sectionBaseline, y);
}
@@ -154,25 +150,18 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
if (FADE_OUT_SECTIONS) {
int alpha = 255;
if (fixedToRow) {
- alpha = Math.min(255, (int) (255 * (Math.max(0, y) / (float) sectionBaseline)));
+ alpha = Math.min(255,
+ (int) (255 * (Math.max(0, y) / (float) sectionBaseline)));
}
mSectionTextPaint.setAlpha(alpha);
}
- if (sectionEnd != null) {
- // If there is a range, draw the range
- c.drawText(sectionBegin + "/" + sectionEnd,
- x + (mStartMargin - sectionBeginBounds.x - sectionEndBounds.x) / 2, y,
- mSectionTextPaint);
- } else {
- c.drawText(sectionBegin, (int) (x + (mStartMargin / 2f) - (sectionBeginBounds.x / 2f)), y,
- mSectionTextPaint);
- }
+ c.drawText(sectionName, x, y, mSectionTextPaint);
lastSectionTop = y;
- lastSectionHeight = (int) (sectionBeginBounds.y + mSectionHeaderOffset);
- lastSectionName = nextItem.sectionName;
+ lastSectionHeight = (int) (sectionBounds.y + mSectionHeaderOffset);
+ lastSectionName = sectionName;
}
- i += (sectionInfo.numAppsInSection - item.sectionAppIndex);
+ i += (sectionInfo.numApps - item.sectionAppIndex);
}
}
}
@@ -184,35 +173,7 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
}
/**
- * Given a section name, return the first and last section letters.
- */
- private void getSectionLetters(String sectionName, String[] lettersOut, PointF[] boundsOut) {
- lettersOut[0] = lettersOut[1] = null;
- boundsOut[0] = boundsOut[1] = null;
- if (AppsContainerView.GRID_MERGE_SECTION_HEADERS) {
- int charOffset = 0;
- while (charOffset < sectionName.length()) {
- int codePoint = sectionName.codePointAt(charOffset);
- int codePointSize = Character.charCount(codePoint);
- if (charOffset == 0) {
- // The first code point
- lettersOut[0] = sectionName.substring(charOffset, charOffset + codePointSize);
- boundsOut[0] = getAndCacheSectionBounds(lettersOut[0]);
- } else if ((charOffset + codePointSize) >= sectionName.length()) {
- // The last code point
- lettersOut[1] = sectionName.substring(charOffset, charOffset + codePointSize);
- boundsOut[0] = getAndCacheSectionBounds(lettersOut[1]);
- }
- charOffset += codePointSize;
- }
- } else {
- lettersOut[0] = sectionName;
- boundsOut[0] = getAndCacheSectionBounds(lettersOut[0]);
- }
- }
-
- /**
- * Given a section name, return the first and last section letters.
+ * Given a section name, return the bounds of the given section name.
*/
private PointF getAndCacheSectionBounds(String sectionName) {
PointF bounds = mCachedSectionBounds.get(sectionName);