Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 99d96ba6 authored by Winson Chung's avatar Winson Chung
Browse files

Fixing issue with fast scroller not showing sub-section headers.

- Removed some old logic to draw merged section headers

Change-Id: I2a7ff9948a3dce253d6bdcda89cc9f222faab309
parent 3253bf40
Loading
Loading
Loading
Loading
+64 −48
Original line number Original line Diff line number Diff line
@@ -82,17 +82,30 @@ public class AlphabeticalAppsList {
     * Info about a section in the alphabetic list
     * Info about a section in the alphabetic list
     */
     */
    public static class SectionInfo {
    public static class SectionInfo {
        // The name of this section
        public String sectionName;
        // The number of applications in this section
        // The number of applications in this section
        public int numAppsInSection;
        public int numApps;
        // The section AdapterItem for this section
        // The section break AdapterItem for this section
        public AdapterItem sectionItem;
        public AdapterItem sectionBreakItem;
        // The first app AdapterItem for this section
        // The first app AdapterItem for this section
        public AdapterItem firstAppItem;
        public AdapterItem firstAppItem;
    }

    /**
     * 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 SectionInfo(String name) {
        public FastScrollSectionInfo(String sectionName, float appRangeFraction) {
            sectionName = name;
            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)
     * Info about a particular adapter item (can be either section or app)
     */
     */
    public static class AdapterItem {
    public static class AdapterItem {
        /** Section & App properties */
        // The index of this adapter item in the list
        // The index of this adapter item in the list
        public int position;
        public int position;
        // Whether or not the item at this adapter position is a section or not
        // Whether or not the item at this adapter position is a section or not
        public boolean isSectionHeader;
        public boolean isSectionHeader;
        // The name of this section, or the section section name of the app.  Note that if this
        // The section for this item
        // 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
        public SectionInfo sectionInfo;
        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
        // The index of this app in the section
        public int sectionAppIndex;
        public int sectionAppIndex = -1;
        // The associated AppInfo, or null if this adapter item is a section
        // The associated AppInfo for the app
        public AppInfo appInfo;
        public AppInfo appInfo = null;
        // The index of this app (not including sections), or -1 if this adapter item is a section
        // The index of this app not including sections
        public int appIndex;
        public int appIndex = -1;


        public static AdapterItem asSection(int pos, SectionInfo section) {
        public static AdapterItem asSectionBreak(int pos, SectionInfo section) {
            AdapterItem item = new AdapterItem();
            AdapterItem item = new AdapterItem();
            item.position = pos;
            item.position = pos;
            item.isSectionHeader = true;
            item.isSectionHeader = true;
            item.sectionInfo = section;
            item.sectionInfo = section;
            item.sectionName = section.sectionName;
            item.appInfo = null;
            item.appIndex = -1;
            return item;
            return item;
        }
        }


@@ -156,6 +168,7 @@ public class AlphabeticalAppsList {
    private List<AppInfo> mFilteredApps = new ArrayList<>();
    private List<AppInfo> mFilteredApps = new ArrayList<>();
    private List<AdapterItem> mSectionedFilteredApps = new ArrayList<>();
    private List<AdapterItem> mSectionedFilteredApps = new ArrayList<>();
    private List<SectionInfo> mSections = new ArrayList<>();
    private List<SectionInfo> mSections = new ArrayList<>();
    private List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.Adapter mAdapter;
    private Filter mFilter;
    private Filter mFilter;
    private AlphabeticIndexCompat mIndexer;
    private AlphabeticIndexCompat mIndexer;
@@ -193,6 +206,13 @@ public class AlphabeticalAppsList {
        return mSections;
        return mSections;
    }
    }


    /**
     * 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.
     * Returns the current filtered list of applications broken down into their sections.
     */
     */
@@ -321,10 +341,13 @@ public class AlphabeticalAppsList {
        mFilteredApps.clear();
        mFilteredApps.clear();
        mSections.clear();
        mSections.clear();
        mSectionedFilteredApps.clear();
        mSectionedFilteredApps.clear();
        mFastScrollerSections.clear();
        SectionInfo lastSectionInfo = null;
        SectionInfo lastSectionInfo = null;
        String lastSectionName = null;
        FastScrollSectionInfo lastFastScrollerSectionInfo = null;
        int position = 0;
        int position = 0;
        int appIndex = 0;
        int appIndex = 0;
        int sectionAppIndex = 0;
        int numApps = mApps.size();
        for (AppInfo info : mApps) {
        for (AppInfo info : mApps) {
            String sectionName = mIndexer.computeSectionName(info.title.toString().trim());
            String sectionName = mIndexer.computeSectionName(info.title.toString().trim());


@@ -334,26 +357,29 @@ public class AlphabeticalAppsList {
            }
            }


            // Create a new section if necessary
            // Create a new section if necessary
            if (lastSectionInfo == null || !lastSectionInfo.sectionName.equals(sectionName)) {
            if (lastSectionInfo == null || !sectionName.equals(lastSectionName)) {
                lastSectionInfo = new SectionInfo(sectionName);
                lastSectionName = sectionName;
                sectionAppIndex = 0;
                lastSectionInfo = new SectionInfo();
                mSections.add(lastSectionInfo);
                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
                // Create a new section item, this item is used to break the flow of items in the
                // list
                // list
                AdapterItem sectionItem = AdapterItem.asSection(position++, lastSectionInfo);
                AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
                if (!AppsContainerView.GRID_HIDE_SECTION_HEADERS && !hasFilter()) {
                if (!AppsContainerView.GRID_HIDE_SECTION_HEADERS && !hasFilter()) {
                    lastSectionInfo.sectionItem = sectionItem;
                    lastSectionInfo.sectionBreakItem = sectionItem;
                    mSectionedFilteredApps.add(sectionItem);
                    mSectionedFilteredApps.add(sectionItem);
                }
                }
            }
            }


            // Create an app item
            // Create an app item
            AdapterItem appItem = AdapterItem.asApp(position++, lastSectionInfo, sectionName,
            AdapterItem appItem = AdapterItem.asApp(position++, lastSectionInfo, sectionName,
                    sectionAppIndex++, info, appIndex++);
                    lastSectionInfo.numApps++, info, appIndex++);
            lastSectionInfo.numAppsInSection++;
            if (lastSectionInfo.firstAppItem == null) {
            if (lastSectionInfo.firstAppItem == null) {
                lastSectionInfo.firstAppItem = appItem;
                lastSectionInfo.firstAppItem = appItem;
                lastFastScrollerSectionInfo.appItem = appItem;
            }
            }
            mSectionedFilteredApps.add(appItem);
            mSectionedFilteredApps.add(appItem);
            mFilteredApps.add(info);
            mFilteredApps.add(info);
@@ -365,9 +391,9 @@ public class AlphabeticalAppsList {
            int sectionAppCount = 0;
            int sectionAppCount = 0;
            for (int i = 0; i < mSections.size(); i++) {
            for (int i = 0; i < mSections.size(); i++) {
                SectionInfo section = mSections.get(i);
                SectionInfo section = mSections.get(i);
                String mergedSectionName = section.sectionName;
                sectionAppCount = section.numApps;
                sectionAppCount = section.numAppsInSection;
                int mergeCount = 1;
                int mergeCount = 1;

                // Merge rows if the last app in this section is in a column that is greater than
                // 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
                // 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
                // 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()) {
                        (i + 1) < mSections.size()) {
                    SectionInfo nextSection = mSections.remove(i + 1);
                    SectionInfo nextSection = mSections.remove(i + 1);


                    // Merge the section names
                    if (AppsContainerView.GRID_MERGE_SECTION_HEADERS) {
                        mergedSectionName += nextSection.sectionName;
                    }
                    // Remove the next section break
                    // Remove the next section break
                    mSectionedFilteredApps.remove(nextSection.sectionItem);
                    mSectionedFilteredApps.remove(nextSection.sectionBreakItem);
                    int pos = mSectionedFilteredApps.indexOf(section.firstAppItem);
                    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
                    // 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);
                        AdapterItem item = mSectionedFilteredApps.get(j);
                        item.sectionInfo = section;
                        item.sectionInfo = section;
                        item.sectionAppIndex += section.numAppsInSection;
                        item.sectionAppIndex += section.numApps;
                    }
                    }

                    // Update the following adapter items of the removed section item
                    // Update the following adapter items of the removed section item
                    pos = mSectionedFilteredApps.indexOf(nextSection.firstAppItem);
                    pos = mSectionedFilteredApps.indexOf(nextSection.firstAppItem);
                    for (int j = pos; j < mSectionedFilteredApps.size(); j++) {
                    for (int j = pos; j < mSectionedFilteredApps.size(); j++) {
                        AdapterItem item = mSectionedFilteredApps.get(j);
                        AdapterItem item = mSectionedFilteredApps.get(j);
                        item.position--;
                        item.position--;
                    }
                    }
                    section.numAppsInSection += nextSection.numAppsInSection;
                    section.numApps += nextSection.numApps;
                    sectionAppCount += nextSection.numAppsInSection;
                    sectionAppCount += nextSection.numApps;
                    mergeCount++;
                    mergeCount++;
                    if (mergeCount >= mMaxAllowableMerges) {
                    if (mergeCount >= mMaxAllowableMerges) {
                        break;
                        break;
+20 −24
Original line number Original line Diff line number Diff line
@@ -254,8 +254,9 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
            mFastScrollTextPaint.setAlpha((int) (mFastScrollAlpha * 255));
            mFastScrollTextPaint.setAlpha((int) (mFastScrollAlpha * 255));
            mFastScrollTextPaint.getTextBounds(mFastScrollSectionName, 0,
            mFastScrollTextPaint.getTextBounds(mFastScrollSectionName, 0,
                    mFastScrollSectionName.length(), mFastScrollTextBounds);
                    mFastScrollSectionName.length(), mFastScrollTextBounds);
            float textWidth = mFastScrollTextPaint.measureText(mFastScrollSectionName);
            canvas.drawText(mFastScrollSectionName,
            canvas.drawText(mFastScrollSectionName,
                    (bgBounds.width() - mFastScrollTextBounds.width()) / 2,
                    (bgBounds.width() - textWidth) / 2,
                    bgBounds.height() - (bgBounds.height() - mFastScrollTextBounds.height()) / 2,
                    bgBounds.height() - (bgBounds.height() - mFastScrollTextBounds.height()) / 2,
                    mFastScrollTextPaint);
                    mFastScrollTextPaint);
            canvas.restoreToCount(restoreCount);
            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) {
    private String scrollToPositionAtProgress(float touchFraction) {
        List<AlphabeticalAppsList.SectionInfo> sections = mApps.getSections();
        // Ensure that we have any sections
        if (sections.isEmpty()) {
        List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
                mApps.getFastScrollerSections();
        if (fastScrollSections.isEmpty()) {
            return "";
            return "";
        }
        }


        // Find the position of the first application in the section that contains the row at the
        AlphabeticalAppsList.FastScrollSectionInfo lastScrollSection = fastScrollSections.get(0);
        // current progress
        for (int i = 1; i < fastScrollSections.size(); i++) {
        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
            AlphabeticalAppsList.FastScrollSectionInfo scrollSection = fastScrollSections.get(i);
        int rowAtProgress = (int) (progress * getNumRows());
            if (lastScrollSection.appRangeFraction <= touchFraction &&
        int rowCount = 0;
                    touchFraction < scrollSection.appRangeFraction) {
        AlphabeticalAppsList.SectionInfo lastSectionInfo = null;
        for (AlphabeticalAppsList.SectionInfo section : sections) {
            int numRowsInSection = (int) Math.ceil((float) section.numAppsInSection / mNumAppsPerRow);
            if (rowCount + numRowsInSection >= rowAtProgress) {
                lastSectionInfo = section;
                break;
                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 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.
        // scroll method on the LayoutManager directly since it is not exposed by RecyclerView.
        LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
        LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
        stopScroll();
        stopScroll();
        layoutManager.scrollToPositionWithOffset(position, 0);
        layoutManager.scrollToPositionWithOffset(lastScrollSection.appItem.position, 0);


        // Return the section name of the row
        return lastScrollSection.sectionName;
        return lastSectionInfo.sectionName;
    }
    }


    /**
    /**
@@ -392,11 +388,11 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
        int appIndex = 0;
        int appIndex = 0;
        int rowCount = 0;
        int rowCount = 0;
        for (AlphabeticalAppsList.SectionInfo info : sections) {
        for (AlphabeticalAppsList.SectionInfo info : sections) {
            int numRowsInSection = (int) Math.ceil((float) info.numAppsInSection / mNumAppsPerRow);
            int numRowsInSection = (int) Math.ceil((float) info.numApps / mNumAppsPerRow);
            if (appIndex + info.numAppsInSection > position) {
            if (appIndex + info.numApps > position) {
                return rowCount + ((position - appIndex) / mNumAppsPerRow);
                return rowCount + ((position - appIndex) / mNumAppsPerRow);
            }
            }
            appIndex += info.numAppsInSection;
            appIndex += info.numApps;
            rowCount += numRowsInSection;
            rowCount += numRowsInSection;
        }
        }
        return appIndex;
        return appIndex;
@@ -409,7 +405,7 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
        List<AlphabeticalAppsList.SectionInfo> sections = mApps.getSections();
        List<AlphabeticalAppsList.SectionInfo> sections = mApps.getSections();
        int rowCount = 0;
        int rowCount = 0;
        for (AlphabeticalAppsList.SectionInfo info : sections) {
        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;
            rowCount += numRowsInSection;
        }
        }
        return rowCount;
        return rowCount;
+0 −1
Original line number Original line Diff line number Diff line
@@ -46,7 +46,6 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
        View.OnClickListener, View.OnLongClickListener {
        View.OnClickListener, View.OnLongClickListener {


    public static final boolean GRID_MERGE_SECTIONS = true;
    public static final boolean GRID_MERGE_SECTIONS = true;
    public static final boolean GRID_MERGE_SECTION_HEADERS = false;
    public static final boolean GRID_HIDE_SECTION_HEADERS = false;
    public static final boolean GRID_HIDE_SECTION_HEADERS = false;


    private static final boolean ALLOW_SINGLE_APP_LAUNCH = true;
    private static final boolean ALLOW_SINGLE_APP_LAUNCH = true;
+15 −54
Original line number Original line Diff line number Diff line
@@ -4,7 +4,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
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 HashMap<String, PointF> mCachedSectionBounds = new HashMap<>();
        private Rect mTmpBounds = new Rect();
        private Rect mTmpBounds = new Rect();
        private String[] mTmpSections = new String[2];
        private PointF[] mTmpSectionBounds = new PointF[2];


        @Override
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        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
                    // Draw all the sections for this index
                    String lastSectionName = item.sectionName;
                    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);
                        AlphabeticalAppsList.AdapterItem nextItem = items.get(pos);
                        String sectionName = nextItem.sectionName;
                        if (nextItem.sectionInfo != sectionInfo) {
                        if (nextItem.sectionInfo != sectionInfo) {
                            break;
                            break;
                        }
                        }
                        if (j > item.sectionAppIndex && nextItem.sectionName.equals(lastSectionName)) {
                        if (j > item.sectionAppIndex && sectionName.equals(lastSectionName)) {
                            continue;
                            continue;
                        }
                        }


                        // Find the section code points
                        // Find the section code points
                        getSectionLetters(nextItem.sectionName, mTmpSections, mTmpSectionBounds);
                        PointF sectionBounds = getAndCacheSectionBounds(sectionName);
                        String sectionBegin = mTmpSections[0];
                        String sectionEnd = mTmpSections[1];
                        PointF sectionBeginBounds = mTmpSectionBounds[0];
                        PointF sectionEndBounds = mTmpSectionBounds[1];


                        // Calculate where to draw the section
                        // 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 :
                        int x = mIsRtl ? parent.getWidth() - mPaddingStart - mStartMargin :
                                mPaddingStart;
                                mPaddingStart;
                        x += (int) ((mStartMargin - sectionBounds.x) / 2f);
                        int y = child.getTop() + sectionBaseline;
                        int y = child.getTop() + sectionBaseline;


                        // Determine whether this is the last row with apps in that section, if
                        // 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 appIndexInSection = items.get(pos).sectionAppIndex;
                        int nextRowPos = Math.min(items.size() - 1,
                        int nextRowPos = Math.min(items.size() - 1,
                                pos + mAppsPerRow - (appIndexInSection % mAppsPerRow));
                                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) {
                        if (!fixedToRow) {
                            y = Math.max(sectionBaseline, y);
                            y = Math.max(sectionBaseline, y);
                        }
                        }
@@ -154,25 +150,18 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
                        if (FADE_OUT_SECTIONS) {
                        if (FADE_OUT_SECTIONS) {
                            int alpha = 255;
                            int alpha = 255;
                            if (fixedToRow) {
                            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);
                            mSectionTextPaint.setAlpha(alpha);
                        }
                        }
                        if (sectionEnd != null) {
                        c.drawText(sectionName, x, y, mSectionTextPaint);
                            // 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);
                        }


                        lastSectionTop = y;
                        lastSectionTop = y;
                        lastSectionHeight = (int) (sectionBeginBounds.y + mSectionHeaderOffset);
                        lastSectionHeight = (int) (sectionBounds.y + mSectionHeaderOffset);
                        lastSectionName = nextItem.sectionName;
                        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.
         * Given a section name, return the bounds of the given section name.
         */
        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.
         */
         */
        private PointF getAndCacheSectionBounds(String sectionName) {
        private PointF getAndCacheSectionBounds(String sectionName) {
            PointF bounds = mCachedSectionBounds.get(sectionName);
            PointF bounds = mCachedSectionBounds.get(sectionName);