Removing the section break UI support
This was an exploration for an alternative UI in all apps, where we show section headers before every section. This was never released. Change-Id: I2d36f1d078cc9a6f3ba6f0ec9655412182c9b016
This commit is contained in:
parent
7630369904
commit
2a65020da1
|
@ -53,6 +53,7 @@
|
|||
android:clipToPadding="false"
|
||||
android:descendantFocusability="afterDescendants"
|
||||
android:focusable="true"
|
||||
android:paddingEnd="@dimen/container_fastscroll_thumb_max_width"
|
||||
android:theme="@style/CustomOverscroll.Light" />
|
||||
|
||||
<!-- Fast scroller popup -->
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
<resources>
|
||||
<!-- All Apps -->
|
||||
<dimen name="all_apps_grid_view_start_margin">0dp</dimen>
|
||||
<dimen name="all_apps_grid_section_text_size">26sp</dimen>
|
||||
<dimen name="all_apps_background_canvas_width">850dp</dimen>
|
||||
<dimen name="all_apps_background_canvas_height">525dp</dimen>
|
||||
|
||||
|
|
|
@ -62,9 +62,6 @@
|
|||
|
||||
<!-- All Apps -->
|
||||
<dimen name="all_apps_button_scale_down">0dp</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_field_height">48dp</dimen>
|
||||
<dimen name="all_apps_search_bar_height">60dp</dimen>
|
||||
<dimen name="all_apps_search_bar_icon_margin_right">4dp</dimen>
|
||||
|
|
|
@ -172,13 +172,6 @@ public abstract class BaseRecyclerView extends RecyclerView
|
|||
return mBackgroundPadding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scroll bar width when the user is scrolling.
|
||||
*/
|
||||
public int getMaxScrollbarWidth() {
|
||||
return mScrollbar.getThumbMaxWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the visible height of the recycler view:
|
||||
* VisibleHeight = View height - top padding - bottom padding
|
||||
|
|
|
@ -177,10 +177,6 @@ public class BaseRecyclerViewFastScrollBar {
|
|||
return mThumbHeight;
|
||||
}
|
||||
|
||||
public int getThumbMaxWidth() {
|
||||
return mMaxWidth;
|
||||
}
|
||||
|
||||
public boolean isDraggingThumb() {
|
||||
return mIsDragging;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package com.android.launcher3.allapps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Selection;
|
||||
|
@ -56,78 +55,9 @@ import com.android.launcher3.shortcuts.DeepShortcutsContainer;
|
|||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
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) {
|
||||
// Don't merge the predicted apps
|
||||
if (section.firstAppItem.viewType != AllAppsGridAdapter.VIEW_TYPE_ICON) {
|
||||
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.VIEW_TYPE_ICON) {
|
||||
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.
|
||||
*/
|
||||
|
@ -135,14 +65,10 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
LauncherTransitionable, View.OnLongClickListener, AllAppsSearchBarController.Callbacks,
|
||||
Insettable {
|
||||
|
||||
private static final int MIN_ROWS_IN_MERGED_SECTION_PHONE = 3;
|
||||
private static final int MAX_NUM_MERGES_PHONE = 2;
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final AlphabeticalAppsList mApps;
|
||||
private final AllAppsGridAdapter mAdapter;
|
||||
private final RecyclerView.LayoutManager mLayoutManager;
|
||||
private final RecyclerView.ItemDecoration mItemDecoration;
|
||||
|
||||
private AllAppsRecyclerView mAppsRecyclerView;
|
||||
private AllAppsSearchBarController mSearchBarController;
|
||||
|
@ -153,7 +79,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
|
||||
private SpannableStringBuilder mSearchQueryBuilder = null;
|
||||
|
||||
private int mSectionNamesMargin;
|
||||
private int mNumAppsPerRow;
|
||||
private int mNumPredictedAppsPerRow;
|
||||
|
||||
|
@ -167,15 +92,12 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
|
||||
public AllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
Resources res = context.getResources();
|
||||
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
mSectionNamesMargin = res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
|
||||
mApps = new AlphabeticalAppsList(context);
|
||||
mAdapter = new AllAppsGridAdapter(mLauncher, mApps, mLauncher, this);
|
||||
mApps.setAdapter(mAdapter);
|
||||
mLayoutManager = mAdapter.getLayoutManager();
|
||||
mItemDecoration = mAdapter.getItemDecoration();
|
||||
mSearchQueryBuilder = new SpannableStringBuilder();
|
||||
Selection.setSelection(mSearchQueryBuilder, 0);
|
||||
}
|
||||
|
@ -337,10 +259,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
mAppsRecyclerView.addOnScrollListener(mElevationController);
|
||||
mAppsRecyclerView.setElevationController(mElevationController);
|
||||
|
||||
if (mItemDecoration != null) {
|
||||
mAppsRecyclerView.addItemDecoration(mItemDecoration);
|
||||
}
|
||||
|
||||
FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(mAppsRecyclerView);
|
||||
mAppsRecyclerView.addItemDecoration(focusedItemDecorator);
|
||||
mAppsRecyclerView.preMeasureViews(mAdapter);
|
||||
|
@ -351,14 +269,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
getContentView().setVisibility(View.VISIBLE);
|
||||
getContentView().setBackground(null);
|
||||
}
|
||||
|
||||
int maxScrollBarWidth = mAppsRecyclerView.getMaxScrollbarWidth();
|
||||
int startInset = Math.max(mSectionNamesMargin, maxScrollBarWidth);
|
||||
if (Utilities.isRtl(getResources())) {
|
||||
mAppsRecyclerView.setPadding(maxScrollBarWidth, 0, startInset, 0);
|
||||
} else {
|
||||
mAppsRecyclerView.setPadding(startInset, 0, maxScrollBarWidth, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -381,7 +291,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
|
||||
mAppsRecyclerView.setNumAppsPerRow(grid, mNumAppsPerRow);
|
||||
mAdapter.setNumAppsPerRow(mNumAppsPerRow);
|
||||
mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, new FullMergeAlgorithm());
|
||||
mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow);
|
||||
}
|
||||
if (!grid.isVerticalBarLayout()) {
|
||||
MarginLayoutParams searchContainerLp =
|
||||
|
@ -396,25 +306,15 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
// --- remove START when {@code FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP} is enabled. ---
|
||||
|
||||
// Update the number of items in the grid before we measure the view
|
||||
// TODO: mSectionNamesMargin is currently 0, but also account for it,
|
||||
// if it's enabled in the future.
|
||||
grid.updateAppsViewNumCols();
|
||||
if (mNumAppsPerRow != grid.allAppsNumCols ||
|
||||
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(grid, mNumAppsPerRow);
|
||||
mAdapter.setNumAppsPerRow(mNumAppsPerRow);
|
||||
mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, mergeAlgorithm);
|
||||
mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow);
|
||||
}
|
||||
|
||||
// --- remove END when {@code FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP} is enabled. ---
|
||||
|
|
|
@ -29,7 +29,6 @@ public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallb
|
|||
|
||||
private static final int INITIAL_TOUCH_SETTLING_DURATION = 100;
|
||||
private static final int REPEAT_TOUCH_SETTLING_DURATION = 200;
|
||||
private static final float FAST_SCROLL_TOUCH_VELOCITY_BARRIER = 1900f;
|
||||
|
||||
private AllAppsRecyclerView mRv;
|
||||
private AlphabeticalAppsList mApps;
|
||||
|
@ -187,9 +186,9 @@ public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallb
|
|||
public void onBindView(AllAppsGridAdapter.ViewHolder holder) {
|
||||
// Update newly bound views to the current fast scroll state if we are fast scrolling
|
||||
if (mCurrentFastScrollSection != null || mTargetFastScrollSection != null) {
|
||||
if (holder.mContent instanceof BaseRecyclerViewFastScrollBar.FastScrollFocusableView) {
|
||||
if (holder.itemView instanceof BaseRecyclerViewFastScrollBar.FastScrollFocusableView) {
|
||||
BaseRecyclerViewFastScrollBar.FastScrollFocusableView v =
|
||||
(BaseRecyclerViewFastScrollBar.FastScrollFocusableView) holder.mContent;
|
||||
(BaseRecyclerViewFastScrollBar.FastScrollFocusableView) holder.itemView;
|
||||
updateViewFastScrollFocusState(v, holder.getPosition(), false /* animated */);
|
||||
mTrackedFastScrollViews.add(v);
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@ package com.android.launcher3.allapps;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
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.v4.view.accessibility.AccessibilityEventCompat;
|
||||
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
|
||||
|
@ -41,10 +38,6 @@ 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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The grid view adapter of all the apps.
|
||||
|
@ -52,10 +45,7 @@ import java.util.List;
|
|||
public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> {
|
||||
|
||||
public static final String TAG = "AppsGridAdapter";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
// A section break in the grid
|
||||
public static final int VIEW_TYPE_SECTION_BREAK = 1 << 0;
|
||||
// A normal icon
|
||||
public static final int VIEW_TYPE_ICON = 1 << 1;
|
||||
// A prediction icon
|
||||
|
@ -78,25 +68,22 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
|
|||
// Common view type masks
|
||||
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_SEARCH_DIVIDER
|
||||
| VIEW_TYPE_SEARCH_MARKET_DIVIDER
|
||||
| VIEW_TYPE_PREDICTION_DIVIDER
|
||||
| VIEW_TYPE_SECTION_BREAK;
|
||||
| VIEW_TYPE_PREDICTION_DIVIDER;
|
||||
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON
|
||||
| VIEW_TYPE_PREDICTION_ICON;
|
||||
|
||||
|
||||
public interface BindViewCallback {
|
||||
public void onBindView(ViewHolder holder);
|
||||
void onBindView(ViewHolder holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* ViewHolder for each icon.
|
||||
*/
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public View mContent;
|
||||
|
||||
public ViewHolder(View v) {
|
||||
super(v);
|
||||
mContent = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,189 +145,14 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to draw the section headers
|
||||
*/
|
||||
public class GridItemDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private static final boolean DEBUG_SECTION_MARGIN = false;
|
||||
private static final boolean FADE_OUT_SECTIONS = false;
|
||||
|
||||
private HashMap<String, PointF> mCachedSectionBounds = new HashMap<>();
|
||||
private Rect mTmpBounds = new Rect();
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||
if (mApps.hasFilter() || mAppsPerRow == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG_SECTION_MARGIN) {
|
||||
Paint p = new Paint();
|
||||
p.setColor(0x33ff0000);
|
||||
c.drawRect(mBackgroundPadding.left, 0, mBackgroundPadding.left + mSectionNamesMargin,
|
||||
parent.getMeasuredHeight(), p);
|
||||
}
|
||||
|
||||
List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
|
||||
boolean showSectionNames = mSectionNamesMargin > 0;
|
||||
int childCount = parent.getChildCount();
|
||||
int lastSectionTop = 0;
|
||||
int lastSectionHeight = 0;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = parent.getChildAt(i);
|
||||
ViewHolder holder = (ViewHolder) parent.getChildViewHolder(child);
|
||||
if (!isValidHolderAndChild(holder, child, items)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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();
|
||||
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(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);
|
||||
int 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
|
||||
// baseline, otherwise, bound it to the baseline so it's in the viewport
|
||||
int appIndexInSection = items.get(pos).sectionAppIndex;
|
||||
int nextRowPos = Math.min(items.size() - 1,
|
||||
pos + mAppsPerRow - (appIndexInSection % mAppsPerRow));
|
||||
AlphabeticalAppsList.AdapterItem nextRowItem = items.get(nextRowPos);
|
||||
boolean fixedToRow = !sectionName.equals(nextRowItem.sectionName);
|
||||
if (!fixedToRow) {
|
||||
y = Math.max(sectionBaseline, y);
|
||||
}
|
||||
|
||||
// In addition, if it overlaps with the last section that was drawn, then
|
||||
// offset it so that it does not overlap
|
||||
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);
|
||||
}
|
||||
c.drawText(sectionName, x, y, mSectionTextPaint);
|
||||
|
||||
lastSectionTop = y;
|
||||
lastSectionHeight = (int) (sectionBounds.y + mSectionHeaderOffset);
|
||||
lastSectionName = sectionName;
|
||||
}
|
||||
i += (sectionInfo.numApps - item.sectionAppIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
|
||||
RecyclerView.State state) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a section name, return the bounds of the given section name.
|
||||
*/
|
||||
private PointF getAndCacheSectionBounds(String sectionName) {
|
||||
PointF bounds = mCachedSectionBounds.get(sectionName);
|
||||
if (bounds == null) {
|
||||
mSectionTextPaint.getTextBounds(sectionName, 0, sectionName.length(), mTmpBounds);
|
||||
bounds = new PointF(mSectionTextPaint.measureText(sectionName), mTmpBounds.height());
|
||||
mCachedSectionBounds.put(sectionName, bounds);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we consider this a valid view holder for us to draw a divider or section for.
|
||||
*/
|
||||
private boolean isValidHolderAndChild(ViewHolder holder, View child,
|
||||
List<AlphabeticalAppsList.AdapterItem> items) {
|
||||
// Ensure item is not already removed
|
||||
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)
|
||||
child.getLayoutParams();
|
||||
if (lp.isItemRemoved()) {
|
||||
return false;
|
||||
}
|
||||
// Ensure we have a valid holder
|
||||
if (holder == null) {
|
||||
return false;
|
||||
}
|
||||
// Ensure we have a holder position
|
||||
int pos = holder.getPosition();
|
||||
if (pos < 0 || pos >= items.size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to draw the section for the given child.
|
||||
*/
|
||||
private boolean shouldDrawItemSection(ViewHolder holder, int childIndex,
|
||||
List<AlphabeticalAppsList.AdapterItem> items) {
|
||||
int pos = holder.getPosition();
|
||||
AlphabeticalAppsList.AdapterItem item = items.get(pos);
|
||||
|
||||
// Ensure it's an icon
|
||||
if (item.viewType != AllAppsGridAdapter.VIEW_TYPE_ICON) {
|
||||
return false;
|
||||
}
|
||||
// Draw the section header for the first item in each section
|
||||
return (childIndex == 0) ||
|
||||
(items.get(pos - 1).viewType == AllAppsGridAdapter.VIEW_TYPE_SECTION_BREAK);
|
||||
}
|
||||
}
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final AlphabeticalAppsList mApps;
|
||||
private final GridLayoutManager mGridLayoutMgr;
|
||||
private final GridSpanSizer mGridSizer;
|
||||
private final GridItemDecoration mItemDecoration;
|
||||
private final View.OnClickListener mIconClickListener;
|
||||
private final View.OnLongClickListener mIconLongClickListener;
|
||||
|
||||
private final Rect mBackgroundPadding = new Rect();
|
||||
private final boolean mIsRtl;
|
||||
|
||||
// Section drawing
|
||||
@Deprecated
|
||||
private final int mSectionNamesMargin;
|
||||
@Deprecated
|
||||
private final int mSectionHeaderOffset;
|
||||
private final Paint mSectionTextPaint;
|
||||
|
||||
private int mAppsPerRow;
|
||||
|
||||
private BindViewCallback mBindViewCallback;
|
||||
|
@ -361,18 +173,9 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
|
|||
mGridSizer = new GridSpanSizer();
|
||||
mGridLayoutMgr = new AppsGridLayoutManager(launcher);
|
||||
mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
|
||||
mItemDecoration = new GridItemDecoration();
|
||||
mLayoutInflater = LayoutInflater.from(launcher);
|
||||
mIconClickListener = iconClickListener;
|
||||
mIconLongClickListener = iconLongClickListener;
|
||||
mSectionNamesMargin = res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
|
||||
mSectionHeaderOffset = res.getDimensionPixelSize(R.dimen.all_apps_grid_section_y_offset);
|
||||
mIsRtl = Utilities.isRtl(res);
|
||||
|
||||
mSectionTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mSectionTextPaint.setTextSize(res.getDimensionPixelSize(
|
||||
R.dimen.all_apps_grid_section_text_size));
|
||||
mSectionTextPaint.setColor(Utilities.getColorAccent(launcher));
|
||||
}
|
||||
|
||||
public static boolean isDividerViewType(int viewType) {
|
||||
|
@ -420,14 +223,6 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
|
|||
mBindViewCallback = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the adapter of the background padding so that it can draw things correctly in the
|
||||
* item decorator.
|
||||
*/
|
||||
public void updateBackgroundPadding(Rect padding) {
|
||||
mBackgroundPadding.set(padding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the grid layout manager.
|
||||
*/
|
||||
|
@ -435,19 +230,9 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
|
|||
return mGridLayoutMgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item decoration for the recycler view.
|
||||
*/
|
||||
public RecyclerView.ItemDecoration getItemDecoration() {
|
||||
// We don't draw any headers when we are uncomfortably dense
|
||||
return mItemDecoration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
switch (viewType) {
|
||||
case VIEW_TYPE_SECTION_BREAK:
|
||||
return new ViewHolder(new View(parent.getContext()));
|
||||
case VIEW_TYPE_ICON:
|
||||
/* falls through */
|
||||
case VIEW_TYPE_PREDICTION_ICON: {
|
||||
|
@ -499,26 +284,26 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
|
|||
switch (holder.getItemViewType()) {
|
||||
case VIEW_TYPE_ICON: {
|
||||
AppInfo info = mApps.getAdapterItems().get(position).appInfo;
|
||||
BubbleTextView icon = (BubbleTextView) holder.mContent;
|
||||
BubbleTextView icon = (BubbleTextView) holder.itemView;
|
||||
icon.applyFromApplicationInfo(info);
|
||||
icon.setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
|
||||
break;
|
||||
}
|
||||
case VIEW_TYPE_PREDICTION_ICON: {
|
||||
AppInfo info = mApps.getAdapterItems().get(position).appInfo;
|
||||
BubbleTextView icon = (BubbleTextView) holder.mContent;
|
||||
BubbleTextView icon = (BubbleTextView) holder.itemView;
|
||||
icon.applyFromApplicationInfo(info);
|
||||
icon.setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
|
||||
break;
|
||||
}
|
||||
case VIEW_TYPE_EMPTY_SEARCH:
|
||||
TextView emptyViewText = (TextView) holder.mContent;
|
||||
TextView emptyViewText = (TextView) holder.itemView;
|
||||
emptyViewText.setText(mEmptySearchMessage);
|
||||
emptyViewText.setGravity(mApps.hasNoFilteredResults() ? Gravity.CENTER :
|
||||
Gravity.START | Gravity.CENTER_VERTICAL);
|
||||
break;
|
||||
case VIEW_TYPE_SEARCH_MARKET:
|
||||
TextView searchView = (TextView) holder.mContent;
|
||||
TextView searchView = (TextView) holder.itemView;
|
||||
if (mMarketSearchIntent != null) {
|
||||
searchView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
|
|
|
@ -101,7 +101,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
|||
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ICON, approxRows * mNumAppsPerRow);
|
||||
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON, mNumAppsPerRow);
|
||||
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER, 1);
|
||||
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SECTION_BREAK, approxRows);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,21 +115,21 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
|||
|
||||
// Icons
|
||||
BubbleTextView icon = (BubbleTextView) adapter.onCreateViewHolder(this,
|
||||
AllAppsGridAdapter.VIEW_TYPE_ICON).mContent;
|
||||
AllAppsGridAdapter.VIEW_TYPE_ICON).itemView;
|
||||
int iconHeight = icon.getLayoutParams().height;
|
||||
mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_ICON, iconHeight);
|
||||
mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON, iconHeight);
|
||||
|
||||
// Search divider
|
||||
View searchDivider = adapter.onCreateViewHolder(this,
|
||||
AllAppsGridAdapter.VIEW_TYPE_SEARCH_DIVIDER).mContent;
|
||||
AllAppsGridAdapter.VIEW_TYPE_SEARCH_DIVIDER).itemView;
|
||||
searchDivider.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
int searchDividerHeight = searchDivider.getMeasuredHeight();
|
||||
mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_SEARCH_DIVIDER, searchDividerHeight);
|
||||
|
||||
// Generic dividers
|
||||
View divider = adapter.onCreateViewHolder(this,
|
||||
AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER).mContent;
|
||||
AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER).itemView;
|
||||
divider.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
int dividerHeight = divider.getMeasuredHeight();
|
||||
mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER, dividerHeight);
|
||||
|
@ -138,18 +137,15 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
|||
|
||||
// Search views
|
||||
View emptySearch = adapter.onCreateViewHolder(this,
|
||||
AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH).mContent;
|
||||
AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH).itemView;
|
||||
emptySearch.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH,
|
||||
emptySearch.getMeasuredHeight());
|
||||
View searchMarket = adapter.onCreateViewHolder(this,
|
||||
AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET).mContent;
|
||||
AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET).itemView;
|
||||
searchMarket.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET,
|
||||
searchMarket.getMeasuredHeight());
|
||||
|
||||
// Section breaks
|
||||
mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_SECTION_BREAK, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,18 +48,6 @@ public class AlphabeticalAppsList {
|
|||
|
||||
private final int mFastScrollDistributionMode = FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS;
|
||||
|
||||
/**
|
||||
* Info about a section in the alphabetic list
|
||||
*/
|
||||
public static class SectionInfo {
|
||||
// The number of applications in this section
|
||||
public int numApps;
|
||||
// The section break AdapterItem for this section
|
||||
public AdapterItem sectionBreakItem;
|
||||
// The first app AdapterItem for this section
|
||||
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.
|
||||
|
@ -87,16 +75,10 @@ public class AlphabeticalAppsList {
|
|||
// The type of this item
|
||||
public int viewType;
|
||||
|
||||
/** Section & App properties */
|
||||
// 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 = -1;
|
||||
// The row that this item shows up on
|
||||
public int rowIndex;
|
||||
// The index of this app in the row
|
||||
|
@ -106,30 +88,19 @@ public class AlphabeticalAppsList {
|
|||
// The index of this app not including sections
|
||||
public int appIndex = -1;
|
||||
|
||||
public static AdapterItem asSectionBreak(int pos, SectionInfo section) {
|
||||
AdapterItem item = new AdapterItem();
|
||||
item.viewType = AllAppsGridAdapter.VIEW_TYPE_SECTION_BREAK;
|
||||
item.position = pos;
|
||||
item.sectionInfo = section;
|
||||
section.sectionBreakItem = item;
|
||||
return item;
|
||||
}
|
||||
|
||||
public static AdapterItem asPredictedApp(int pos, SectionInfo section, String sectionName,
|
||||
int sectionAppIndex, AppInfo appInfo, int appIndex) {
|
||||
AdapterItem item = asApp(pos, section, sectionName, sectionAppIndex, appInfo, appIndex);
|
||||
public static AdapterItem asPredictedApp(int pos, String sectionName, AppInfo appInfo,
|
||||
int appIndex) {
|
||||
AdapterItem item = asApp(pos, sectionName, appInfo, appIndex);
|
||||
item.viewType = AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON;
|
||||
return item;
|
||||
}
|
||||
|
||||
public static AdapterItem asApp(int pos, SectionInfo section, String sectionName,
|
||||
int sectionAppIndex, AppInfo appInfo, int appIndex) {
|
||||
public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo,
|
||||
int appIndex) {
|
||||
AdapterItem item = new AdapterItem();
|
||||
item.viewType = AllAppsGridAdapter.VIEW_TYPE_ICON;
|
||||
item.position = pos;
|
||||
item.sectionInfo = section;
|
||||
item.sectionName = sectionName;
|
||||
item.sectionAppIndex = sectionAppIndex;
|
||||
item.appInfo = appInfo;
|
||||
item.appIndex = appIndex;
|
||||
return item;
|
||||
|
@ -171,14 +142,6 @@ public class AlphabeticalAppsList {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Common interface for different merging strategies.
|
||||
*/
|
||||
public interface MergeAlgorithm {
|
||||
boolean continueMerging(SectionInfo section, SectionInfo withSection,
|
||||
int sectionAppCount, int numAppsPerRow, int mergeCount);
|
||||
}
|
||||
|
||||
private Launcher mLauncher;
|
||||
|
||||
// The set of apps from the system not including predictions
|
||||
|
@ -189,8 +152,6 @@ public class AlphabeticalAppsList {
|
|||
private List<AppInfo> mFilteredApps = new ArrayList<>();
|
||||
// The current set of adapter items
|
||||
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)
|
||||
private List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
|
||||
// The set of predicted app component names
|
||||
|
@ -203,7 +164,6 @@ public class AlphabeticalAppsList {
|
|||
private AllAppsGridAdapter mAdapter;
|
||||
private AlphabeticIndexCompat mIndexer;
|
||||
private AppNameComparator mAppNameComparator;
|
||||
private MergeAlgorithm mMergeAlgorithm;
|
||||
private int mNumAppsPerRow;
|
||||
private int mNumPredictedAppsPerRow;
|
||||
private int mNumAppRowsInAdapter;
|
||||
|
@ -217,11 +177,9 @@ public class AlphabeticalAppsList {
|
|||
/**
|
||||
* Sets the number of apps per row.
|
||||
*/
|
||||
public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow,
|
||||
MergeAlgorithm mergeAlgorithm) {
|
||||
public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow) {
|
||||
mNumAppsPerRow = numAppsPerRow;
|
||||
mNumPredictedAppsPerRow = numPredictedAppsPerRow;
|
||||
mMergeAlgorithm = mergeAlgorithm;
|
||||
|
||||
updateAdapterItems();
|
||||
}
|
||||
|
@ -240,13 +198,6 @@ public class AlphabeticalAppsList {
|
|||
return mApps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sections of all the current filtered applications.
|
||||
*/
|
||||
public List<SectionInfo> getSections() {
|
||||
return mSections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns fast scroller sections of all the current filtered applications.
|
||||
*/
|
||||
|
@ -403,7 +354,6 @@ public class AlphabeticalAppsList {
|
|||
* mCachedSectionNames to have been calculated for the set of all apps in mApps.
|
||||
*/
|
||||
private void updateAdapterItems() {
|
||||
SectionInfo lastSectionInfo = null;
|
||||
String lastSectionName = null;
|
||||
FastScrollSectionInfo lastFastScrollerSectionInfo = null;
|
||||
int position = 0;
|
||||
|
@ -413,7 +363,6 @@ public class AlphabeticalAppsList {
|
|||
mFilteredApps.clear();
|
||||
mFastScrollerSections.clear();
|
||||
mAdapterItems.clear();
|
||||
mSections.clear();
|
||||
|
||||
if (DEBUG_PREDICTIONS) {
|
||||
if (mPredictedAppComponents.isEmpty() && !mApps.isEmpty()) {
|
||||
|
@ -451,19 +400,14 @@ public class AlphabeticalAppsList {
|
|||
|
||||
if (!mPredictedApps.isEmpty()) {
|
||||
// Add a section for the predictions
|
||||
lastSectionInfo = new SectionInfo();
|
||||
lastFastScrollerSectionInfo = new FastScrollSectionInfo("");
|
||||
AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
|
||||
mSections.add(lastSectionInfo);
|
||||
mFastScrollerSections.add(lastFastScrollerSectionInfo);
|
||||
mAdapterItems.add(sectionItem);
|
||||
|
||||
// Add the predicted app items
|
||||
for (AppInfo info : mPredictedApps) {
|
||||
AdapterItem appItem = AdapterItem.asPredictedApp(position++, lastSectionInfo,
|
||||
"", lastSectionInfo.numApps++, info, appIndex++);
|
||||
if (lastSectionInfo.firstAppItem == null) {
|
||||
lastSectionInfo.firstAppItem = appItem;
|
||||
AdapterItem appItem = AdapterItem.asPredictedApp(position++, "", info,
|
||||
appIndex++);
|
||||
if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
|
||||
lastFastScrollerSectionInfo.fastScrollToItem = appItem;
|
||||
}
|
||||
mAdapterItems.add(appItem);
|
||||
|
@ -480,25 +424,15 @@ public class AlphabeticalAppsList {
|
|||
String sectionName = getAndUpdateCachedSectionName(info.title);
|
||||
|
||||
// Create a new section if the section names do not match
|
||||
if (lastSectionInfo == null || !sectionName.equals(lastSectionName)) {
|
||||
if (!sectionName.equals(lastSectionName)) {
|
||||
lastSectionName = sectionName;
|
||||
lastSectionInfo = new SectionInfo();
|
||||
lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName);
|
||||
mSections.add(lastSectionInfo);
|
||||
mFastScrollerSections.add(lastFastScrollerSectionInfo);
|
||||
|
||||
// Create a new section item to break the flow of items in the list
|
||||
if (!hasFilter()) {
|
||||
AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
|
||||
mAdapterItems.add(sectionItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an app item
|
||||
AdapterItem appItem = AdapterItem.asApp(position++, lastSectionInfo, sectionName,
|
||||
lastSectionInfo.numApps++, info, appIndex++);
|
||||
if (lastSectionInfo.firstAppItem == null) {
|
||||
lastSectionInfo.firstAppItem = appItem;
|
||||
AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, appIndex++);
|
||||
if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
|
||||
lastFastScrollerSectionInfo.fastScrollToItem = appItem;
|
||||
}
|
||||
mAdapterItems.add(appItem);
|
||||
|
@ -515,9 +449,6 @@ public class AlphabeticalAppsList {
|
|||
mAdapterItems.add(AdapterItem.asMarketSearch(position++));
|
||||
}
|
||||
|
||||
// Merge multiple sections together as requested by the merge strategy for this device
|
||||
mergeSections();
|
||||
|
||||
if (mNumAppsPerRow != 0) {
|
||||
// Update the number of rows in the adapter after we do all the merging (otherwise, we
|
||||
// would have to shift the values again)
|
||||
|
@ -593,61 +524,6 @@ public class AlphabeticalAppsList {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges multiple sections to reduce visual raggedness.
|
||||
*/
|
||||
private void mergeSections() {
|
||||
// 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 (!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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cached section name for the given title, recomputing and updating the cache if
|
||||
* the title has no cached section name.
|
||||
|
|
|
@ -27,12 +27,10 @@ import android.view.ViewGroup;
|
|||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.WidgetPreviewLoader;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
|
||||
|
|
Loading…
Reference in New Issue