summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/allapps
diff options
context:
space:
mode:
authorWinson Chung <winsonc@google.com>2015-06-16 18:24:23 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-06-16 18:24:24 +0000
commitb42120300ec622804af2de9c29ce849f96e4de23 (patch)
tree3999340255a9bc082b5fdb8f4487bf0a8d4c46b1 /src/com/android/launcher3/allapps
parented717bcd611628ff961e0e9a7e7e11015fca4a33 (diff)
parentfbc5b18626ae2e158e39c59606455124cfa8127d (diff)
downloadandroid_packages_apps_Trebuchet-b42120300ec622804af2de9c29ce849f96e4de23.tar.gz
android_packages_apps_Trebuchet-b42120300ec622804af2de9c29ce849f96e4de23.tar.bz2
android_packages_apps_Trebuchet-b42120300ec622804af2de9c29ce849f96e4de23.zip
Merge "Refactored section names to only draw when there is space." into ub-launcher3-burnaby
Diffstat (limited to 'src/com/android/launcher3/allapps')
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java84
-rw-r--r--src/com/android/launcher3/allapps/AllAppsGridAdapter.java26
-rw-r--r--src/com/android/launcher3/allapps/AllAppsRecyclerView.java12
-rw-r--r--src/com/android/launcher3/allapps/AlphabeticalAppsList.java87
4 files changed, 104 insertions, 105 deletions
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index b300cae62..083e3c19e 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -58,12 +58,71 @@ 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.
*/
public class AllAppsContainerView extends BaseContainerView implements DragSource,
@@ -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);
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index dc0d27cd2..68407bdd5 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -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 :
- mBackgroundPadding.left;
- x += (int) ((mStartMargin - sectionBounds.x) / 2f);
+ int x = mIsRtl ?
+ parent.getWidth() - mBackgroundPadding.left - mSectionNamesMargin :
+ mBackgroundPadding.left;
+ 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();
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 25918ce31..ff327dae3 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -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.
- layoutManager.scrollToPositionWithOffset(lastScrollSection.appItem.position, 0);
+ 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.
*/
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index a0cf5b6dc..4f29e0c7a 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -19,18 +19,13 @@ import android.content.ComponentName;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
-
import com.android.launcher3.AppInfo;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.model.AbstractUserComparator;
import com.android.launcher3.model.AppNameComparator;
-import com.android.launcher3.util.Thunk;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -144,70 +139,11 @@ public class AlphabeticalAppsList {
/**
* Common interface for different merging strategies.
*/
- private interface MergeAlgorithm {
+ public interface MergeAlgorithm {
boolean continueMerging(SectionInfo section, SectionInfo withSection,
int sectionAppCount, int numAppsPerRow, int mergeCount);
}
- /**
- * The logic we use to merge sections on tablets. Currently, we don't show section names on
- * tablet layouts, so just merge all the sections indiscriminately.
- */
- @Thunk static class TabletMergeAlgorithm implements MergeAlgorithm {
-
- @Override
- public boolean continueMerging(SectionInfo section, SectionInfo withSection,
- int sectionAppCount, int numAppsPerRow, int mergeCount) {
- // Merge EVERYTHING
- return true;
- }
- }
-
- /**
- * The logic we use to merge sections on phones. 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.
- */
- private static class PhoneMergeAlgorithm implements MergeAlgorithm {
-
- private int mMinAppsPerRow;
- private int mMinRowsInMergedSection;
- private int mMaxAllowableMerges;
- private CharsetEncoder mAsciiEncoder;
-
- public PhoneMergeAlgorithm(int minAppsPerRow, int minRowsInMergedSection, int maxNumMerges) {
- mMinAppsPerRow = minAppsPerRow;
- mMinRowsInMergedSection = minRowsInMergedSection;
- mMaxAllowableMerges = maxNumMerges;
- mAsciiEncoder = Charset.forName("US-ASCII").newEncoder();
- }
-
- @Override
- public boolean continueMerging(SectionInfo section, 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;
- }
- }
-
- private static final int MIN_ROWS_IN_MERGED_SECTION_PHONE = 3;
- private static final int MAX_NUM_MERGES_PHONE = 2;
-
private Launcher mLauncher;
// The set of apps from the system not including predictions
@@ -249,20 +185,13 @@ public class AlphabeticalAppsList {
}
/**
- * Sets the number of apps per row. Used only for AppsContainerView.SECTIONED_GRID_COALESCED.
+ * Sets the number of apps per row.
*/
- public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow) {
- // Update the merge algorithm
- DeviceProfile grid = mLauncher.getDeviceProfile();
- if (grid.isPhone) {
- mMergeAlgorithm = new PhoneMergeAlgorithm((int) Math.ceil(numAppsPerRow / 2f),
- MIN_ROWS_IN_MERGED_SECTION_PHONE, MAX_NUM_MERGES_PHONE);
- } else {
- mMergeAlgorithm = new TabletMergeAlgorithm();
- }
-
+ public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow,
+ MergeAlgorithm mergeAlgorithm) {
mNumAppsPerRow = numAppsPerRow;
mNumPredictedAppsPerRow = numPredictedAppsPerRow;
+ mMergeAlgorithm = mergeAlgorithm;
updateAdapterItems();
}
@@ -599,13 +528,13 @@ public class AlphabeticalAppsList {
* Merges multiple sections to reduce visual raggedness.
*/
private void mergeSections() {
- // Ignore merging until we have a valid row size
- if (mNumAppsPerRow == 0) {
+ // Ignore merging until we have an algorithm and a valid row size
+ if (mMergeAlgorithm == null || mNumAppsPerRow == 0) {
return;
}
// Go through each section and try and merge some of the sections
- if (AllAppsContainerView.GRID_MERGE_SECTIONS && !hasFilter()) {
+ if (!hasFilter()) {
int sectionAppCount = 0;
for (int i = 0; i < mSections.size() - 1; i++) {
SectionInfo section = mSections.get(i);