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

Commit b4212030 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Refactored section names to only draw when there is space." into ub-launcher3-burnaby

parents ed717bcd fbc5b186
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@
    <!-- Notes: container_bounds_inset - quantum_panel_outer_padding -->
    <dimen name="container_bounds_minus_quantum_panel_padding_inset">4dp</dimen>

    <dimen name="all_apps_grid_view_start_margin">56dp</dimen>
    <dimen name="all_apps_grid_view_start_margin">0dp</dimen>
    <dimen name="all_apps_grid_section_y_offset">8dp</dimen>
    <dimen name="all_apps_grid_section_text_size">24sp</dimen>
    <dimen name="all_apps_search_bar_height">48dp</dimen>
@@ -65,7 +65,7 @@
    <dimen name="all_apps_prediction_bar_top_bottom_padding">16dp</dimen>

    <dimen name="all_apps_fast_scroll_bar_width">4dp</dimen>
    <dimen name="all_apps_fast_scroll_scrubber_touch_inset">-16dp</dimen>
    <dimen name="all_apps_fast_scroll_scrubber_touch_inset">-24dp</dimen>
    <dimen name="all_apps_fast_scroll_popup_size">72dp</dimen>
    <dimen name="all_apps_fast_scroll_text_size">48dp</dimen>

+28 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.launcher3;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
@@ -315,12 +317,37 @@ public class BaseRecyclerView extends RecyclerView
    /**
     * Animates the visibility of the fast scroller popup.
     */
    private void animateFastScrollerVisibility(boolean visible) {
    private void animateFastScrollerVisibility(final boolean visible) {
        ObjectAnimator anim = ObjectAnimator.ofFloat(this, "fastScrollerAlpha", visible ? 1f : 0f);
        anim.setDuration(visible ? 200 : 150);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                if (visible) {
                    onFastScrollingStart();
                }
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (!visible) {
                    onFastScrollingEnd();
                }
            }
        });
        anim.start();
    }

    /**
     * To be overridden by subclasses.
     */
    protected void onFastScrollingStart() {}

    /**
     * To be overridden by subclasses.
     */
    protected void onFastScrollingEnd() {}

    /**
     * Invalidates the fast scroller popup.
     */
+76 −8
Original line number Diff line number Diff line
@@ -58,11 +58,70 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.util.Thunk;

import java.nio.charset.Charset;
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) {
        // Merge EVERYTHING
        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) {
        // 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.
 */
@@ -72,7 +131,8 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
        View.OnLongClickListener, ViewTreeObserver.OnPreDrawListener,
        AllAppsSearchBarController.Callbacks, Stats.LaunchSourceProvider {

    public static final boolean GRID_MERGE_SECTIONS = true;
    private static final int MIN_ROWS_IN_MERGED_SECTION_PHONE = 3;
    private static final int MAX_NUM_MERGES_PHONE = 2;

    @Thunk Launcher mLauncher;
    @Thunk AlphabeticalAppsList mApps;
@@ -90,6 +150,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
    private ViewGroup mSearchBarContainerView;
    private View mSearchBarView;

    private int mSectionNamesMargin;
    private int mNumAppsPerRow;
    private int mNumPredictedAppsPerRow;
    // This coordinate is relative to this container view
@@ -127,7 +188,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
                Utilities.calculateTextHeight(grid.allAppsIconTextSizePx) +
                2 * res.getDimensionPixelSize(R.dimen.all_apps_icon_top_bottom_padding) +
                2 * res.getDimensionPixelSize(R.dimen.all_apps_prediction_bar_top_bottom_padding));

        mSectionNamesMargin = res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
        mApps = new AlphabeticalAppsList(context);
        mApps.setAdapterChangedCallback(this);
        mAdapter = new AllAppsGridAdapter(context, mApps, this, this, mLauncher, this);
@@ -342,9 +403,18 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
                mNumPredictedAppsPerRow != grid.allAppsNumPredictiveCols) {
            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 = mSectionNamesMargin == 0 || !grid.isPhone;
            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(mNumAppsPerRow, mNumPredictedAppsPerRow);
            mAdapter.setNumAppsPerRow(mNumAppsPerRow);
            mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow);
            mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, mergeAlgorithm);
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -376,14 +446,12 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc

        // Pad the recycler view by the background padding plus the start margin (for the section
        // names)
        DeviceProfile grid = mLauncher.getDeviceProfile();
        int startMargin = grid.isPhone ? getResources().getDimensionPixelSize(
                R.dimen.all_apps_grid_view_start_margin) : mAppsRecyclerView.getScrollbarWidth();
        int startInset = Math.max(mSectionNamesMargin, mAppsRecyclerView.getScrollbarWidth());
        if (isRtl) {
            mAppsRecyclerView.setPadding(padding.left + mAppsRecyclerView.getScrollbarWidth(), 0,
                    padding.right + startMargin, 0);
                    padding.right + startInset, 0);
        } else {
            mAppsRecyclerView.setPadding(padding.left + startMargin, 0,
            mAppsRecyclerView.setPadding(padding.left + startInset, 0,
                    padding.right + mAppsRecyclerView.getScrollbarWidth(), 0);
        }

+10 −16
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
@@ -32,7 +31,6 @@ import android.view.ViewGroup;
import android.widget.TextView;
import com.android.launcher3.AppInfo;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -114,11 +112,6 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol

        private HashMap<String, PointF> mCachedSectionBounds = new HashMap<>();
        private Rect mTmpBounds = new Rect();
        private Launcher mLauncher;

        public GridItemDecoration(Context context) {
            mLauncher = (Launcher) context;
        }

        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
@@ -129,13 +122,13 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
            if (DEBUG_SECTION_MARGIN) {
                Paint p = new Paint();
                p.setColor(0x33ff0000);
                c.drawRect(mBackgroundPadding.left, 0, mBackgroundPadding.left + mStartMargin,
                c.drawRect(mBackgroundPadding.left, 0, mBackgroundPadding.left + mSectionNamesMargin,
                        parent.getMeasuredHeight(), p);
            }

            DeviceProfile grid = mLauncher.getDeviceProfile();
            List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
            boolean hasDrawnPredictedAppsDivider = false;
            boolean showSectionNames = mSectionNamesMargin > 0;
            int childCount = parent.getChildCount();
            int lastSectionTop = 0;
            int lastSectionHeight = 0;
@@ -154,7 +147,7 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
                            mPredictedAppsDividerPaint);
                    hasDrawnPredictedAppsDivider = true;

                } else if (grid.isPhone && shouldDrawItemSection(holder, i, items)) {
                } else if (showSectionNames && shouldDrawItemSection(holder, i, items)) {
                    // At this point, we only draw sections for each section break;
                    int viewTopOffset = (2 * child.getPaddingTop());
                    int pos = holder.getPosition();
@@ -179,9 +172,10 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol

                        // Calculate where to draw the section
                        int sectionBaseline = (int) (viewTopOffset + sectionBounds.y);
                        int x = mIsRtl ? parent.getWidth() - mBackgroundPadding.left - mStartMargin :
                        int x = mIsRtl ?
                                parent.getWidth() - mBackgroundPadding.left - mSectionNamesMargin :
                                        mBackgroundPadding.left;
                        x += (int) ((mStartMargin - sectionBounds.x) / 2f);
                        x += (int) ((mSectionNamesMargin - sectionBounds.x) / 2f);
                        int y = child.getTop() + sectionBaseline;

                        // Determine whether this is the last row with apps in that section, if
@@ -309,7 +303,7 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
    private String mEmptySearchText;

    // Section drawing
    @Thunk int mStartMargin;
    @Thunk int mSectionNamesMargin;
    @Thunk int mSectionHeaderOffset;
    @Thunk Paint mSectionTextPaint;
    @Thunk Paint mPredictedAppsDividerPaint;
@@ -324,12 +318,12 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol
        mGridSizer = new GridSpanSizer();
        mGridLayoutMgr = new GridLayoutManager(context, 1, GridLayoutManager.VERTICAL, false);
        mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
        mItemDecoration = new GridItemDecoration(context);
        mItemDecoration = new GridItemDecoration();
        mLayoutInflater = LayoutInflater.from(context);
        mTouchListener = touchListener;
        mIconClickListener = iconClickListener;
        mIconLongClickListener = iconLongClickListener;
        mStartMargin = res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
        mSectionNamesMargin = res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
        mSectionHeaderOffset = res.getDimensionPixelSize(R.dimen.all_apps_grid_section_y_offset);

        mSectionTextPaint = new Paint();
+10 −2
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView
    private int mNumAppsPerRow;
    private int mNumPredictedAppsPerRow;
    private int mPredictionBarHeight;
    private int mLastFastscrollPosition = -1;

    private Launcher mLauncher;

@@ -131,6 +132,11 @@ public class AllAppsRecyclerView extends BaseRecyclerView
        }
    }

    @Override
    protected void onFastScrollingEnd() {
        mLastFastscrollPosition = -1;
    }

    /**
     * Maps the touch (from 0..1) to the adapter position that should be visible.
     */
@@ -174,12 +180,14 @@ public class AllAppsRecyclerView extends BaseRecyclerView

        // Scroll to the view at the position, anchored at the top of the screen. We call the scroll
        // method on the LayoutManager directly since it is not exposed by RecyclerView.
        if (mLastFastscrollPosition != lastScrollSection.appItem.position) {
            mLastFastscrollPosition = lastScrollSection.appItem.position;
            layoutManager.scrollToPositionWithOffset(lastScrollSection.appItem.position, 0);
        }

        return lastScrollSection.sectionName;
    }


    /**
     * Returns the row index for a app index in the list.
     */
Loading