2015-03-10 16:28:47 -07:00
|
|
|
package com.android.launcher3;
|
|
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.res.Resources;
|
|
|
|
|
import android.graphics.Canvas;
|
|
|
|
|
import android.graphics.Paint;
|
2015-05-07 18:21:28 -07:00
|
|
|
import android.graphics.PointF;
|
2015-03-10 16:28:47 -07:00
|
|
|
import android.graphics.Rect;
|
|
|
|
|
import android.support.v7.widget.GridLayoutManager;
|
|
|
|
|
import android.support.v7.widget.RecyclerView;
|
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewGroup;
|
2015-03-13 11:14:16 -07:00
|
|
|
import android.widget.TextView;
|
2015-03-18 14:16:05 -07:00
|
|
|
import com.android.launcher3.util.Thunk;
|
2015-03-10 16:28:47 -07:00
|
|
|
|
2015-05-05 17:21:58 -07:00
|
|
|
import java.util.HashMap;
|
2015-04-06 15:12:49 -07:00
|
|
|
import java.util.List;
|
|
|
|
|
|
2015-03-10 16:28:47 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The grid view adapter of all the apps.
|
|
|
|
|
*/
|
|
|
|
|
class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
|
|
|
|
|
|
|
|
|
public static final String TAG = "AppsGridAdapter";
|
2015-05-05 17:21:58 -07:00
|
|
|
private static final boolean DEBUG = false;
|
2015-03-10 16:28:47 -07:00
|
|
|
|
|
|
|
|
private static final int SECTION_BREAK_VIEW_TYPE = 0;
|
|
|
|
|
private static final int ICON_VIEW_TYPE = 1;
|
2015-03-13 11:14:16 -07:00
|
|
|
private static final int EMPTY_VIEW_TYPE = 2;
|
2015-03-10 16:28:47 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ViewHolder for each icon.
|
|
|
|
|
*/
|
|
|
|
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
|
|
|
|
public View mContent;
|
2015-03-13 11:14:16 -07:00
|
|
|
public boolean mIsEmptyRow;
|
2015-03-10 16:28:47 -07:00
|
|
|
|
2015-05-08 17:34:17 -07:00
|
|
|
public ViewHolder(View v, boolean isEmptyRow) {
|
2015-03-10 16:28:47 -07:00
|
|
|
super(v);
|
|
|
|
|
mContent = v;
|
2015-03-13 11:14:16 -07:00
|
|
|
mIsEmptyRow = isEmptyRow;
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper class to size the grid items.
|
|
|
|
|
*/
|
|
|
|
|
public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup {
|
2015-05-05 17:21:58 -07:00
|
|
|
|
|
|
|
|
public GridSpanSizer() {
|
|
|
|
|
super();
|
|
|
|
|
setSpanIndexCacheEnabled(true);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-10 16:28:47 -07:00
|
|
|
@Override
|
|
|
|
|
public int getSpanSize(int position) {
|
2015-03-13 11:14:16 -07:00
|
|
|
if (mApps.hasNoFilteredResults()) {
|
|
|
|
|
// Empty view spans full width
|
|
|
|
|
return mAppsPerRow;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-06 15:12:49 -07:00
|
|
|
if (mApps.getAdapterItems().get(position).isSectionHeader) {
|
2015-03-13 11:14:16 -07:00
|
|
|
// Section break spans full width
|
2015-05-11 22:12:38 -07:00
|
|
|
return mAppsPerRow;
|
2015-03-10 16:28:47 -07:00
|
|
|
} else {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper class to draw the section headers
|
|
|
|
|
*/
|
|
|
|
|
public class GridItemDecoration extends RecyclerView.ItemDecoration {
|
|
|
|
|
|
2015-05-05 17:21:58 -07:00
|
|
|
private static final boolean FADE_OUT_SECTIONS = false;
|
|
|
|
|
|
2015-05-07 18:21:28 -07:00
|
|
|
private HashMap<String, PointF> mCachedSectionBounds = new HashMap<>();
|
2015-05-05 17:21:58 -07:00
|
|
|
private Rect mTmpBounds = new Rect();
|
|
|
|
|
|
2015-03-10 16:28:47 -07:00
|
|
|
@Override
|
|
|
|
|
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
2015-05-05 17:21:58 -07:00
|
|
|
if (mApps.hasFilter()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 16:30:13 -07:00
|
|
|
DeviceProfile grid = LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile();
|
2015-04-06 15:12:49 -07:00
|
|
|
List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
|
2015-05-08 17:34:17 -07:00
|
|
|
boolean hasDrawnPredictedAppDivider = false;
|
2015-05-07 18:21:28 -07:00
|
|
|
int childCount = parent.getChildCount();
|
2015-05-05 17:21:58 -07:00
|
|
|
int lastSectionTop = 0;
|
|
|
|
|
int lastSectionHeight = 0;
|
2015-05-07 18:21:28 -07:00
|
|
|
for (int i = 0; i < childCount; i++) {
|
2015-03-10 16:28:47 -07:00
|
|
|
View child = parent.getChildAt(i);
|
|
|
|
|
ViewHolder holder = (ViewHolder) parent.getChildViewHolder(child);
|
2015-05-08 17:34:17 -07:00
|
|
|
if (!isValidHolderAndChild(holder, child, items)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (shouldDrawItemDivider(holder, items) && !hasDrawnPredictedAppDivider) {
|
|
|
|
|
// Draw the divider under the predicted app
|
|
|
|
|
int top = child.getTop() + child.getHeight();
|
|
|
|
|
int left = parent.getPaddingLeft();
|
|
|
|
|
int right = parent.getWidth() - parent.getPaddingRight();
|
|
|
|
|
int iconInset = (((right - left) / mAppsPerRow) - grid.allAppsIconSizePx) / 2;
|
|
|
|
|
c.drawLine(left + iconInset, top, right - iconInset, top, mPredictedAppsDividerPaint);
|
|
|
|
|
hasDrawnPredictedAppDivider = true;
|
|
|
|
|
|
2015-05-11 16:30:13 -07:00
|
|
|
} else if (grid.isPhone() && shouldDrawItemSection(holder, i, items)) {
|
2015-05-07 18:21:28 -07:00
|
|
|
// At this point, we only draw sections for each section break;
|
|
|
|
|
int viewTopOffset = (2 * child.getPaddingTop());
|
2015-05-05 17:21:58 -07:00
|
|
|
int pos = holder.getPosition();
|
|
|
|
|
AlphabeticalAppsList.AdapterItem item = items.get(pos);
|
2015-05-07 18:21:28 -07:00
|
|
|
AlphabeticalAppsList.SectionInfo sectionInfo = item.sectionInfo;
|
2015-05-05 17:21:58 -07:00
|
|
|
|
2015-05-07 18:21:28 -07:00
|
|
|
// Draw all the sections for this index
|
|
|
|
|
String lastSectionName = item.sectionName;
|
2015-05-08 12:04:45 -07:00
|
|
|
for (int j = item.sectionAppIndex; j < sectionInfo.numApps; j++, pos++) {
|
2015-05-07 18:21:28 -07:00
|
|
|
AlphabeticalAppsList.AdapterItem nextItem = items.get(pos);
|
2015-05-08 12:04:45 -07:00
|
|
|
String sectionName = nextItem.sectionName;
|
2015-05-07 18:21:28 -07:00
|
|
|
if (nextItem.sectionInfo != sectionInfo) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-05-08 12:04:45 -07:00
|
|
|
if (j > item.sectionAppIndex && sectionName.equals(lastSectionName)) {
|
2015-05-07 18:21:28 -07:00
|
|
|
continue;
|
2015-05-05 17:21:58 -07:00
|
|
|
}
|
|
|
|
|
|
2015-05-11 16:30:13 -07:00
|
|
|
|
|
|
|
|
// Find the section name bounds
|
2015-05-08 12:04:45 -07:00
|
|
|
PointF sectionBounds = getAndCacheSectionBounds(sectionName);
|
2015-05-07 18:21:28 -07:00
|
|
|
|
|
|
|
|
// Calculate where to draw the section
|
2015-05-08 12:04:45 -07:00
|
|
|
int sectionBaseline = (int) (viewTopOffset + sectionBounds.y);
|
2015-05-07 18:21:28 -07:00
|
|
|
int x = mIsRtl ? parent.getWidth() - mPaddingStart - mStartMargin :
|
2015-05-05 17:21:58 -07:00
|
|
|
mPaddingStart;
|
2015-05-08 12:04:45 -07:00
|
|
|
x += (int) ((mStartMargin - sectionBounds.x) / 2f);
|
2015-05-07 18:21:28 -07:00
|
|
|
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));
|
2015-05-08 12:04:45 -07:00
|
|
|
AlphabeticalAppsList.AdapterItem nextRowItem = items.get(nextRowPos);
|
|
|
|
|
boolean fixedToRow = !sectionName.equals(nextRowItem.sectionName);
|
2015-05-07 18:21:28 -07:00
|
|
|
if (!fixedToRow) {
|
|
|
|
|
y = Math.max(sectionBaseline, y);
|
2015-05-05 17:21:58 -07:00
|
|
|
}
|
2015-05-07 18:21:28 -07:00
|
|
|
|
|
|
|
|
// 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;
|
2015-05-05 17:21:58 -07:00
|
|
|
}
|
2015-05-07 18:21:28 -07:00
|
|
|
|
|
|
|
|
// Draw the section header
|
2015-05-05 17:21:58 -07:00
|
|
|
if (FADE_OUT_SECTIONS) {
|
2015-05-07 18:21:28 -07:00
|
|
|
int alpha = 255;
|
|
|
|
|
if (fixedToRow) {
|
2015-05-08 12:04:45 -07:00
|
|
|
alpha = Math.min(255,
|
|
|
|
|
(int) (255 * (Math.max(0, y) / (float) sectionBaseline)));
|
2015-05-07 18:21:28 -07:00
|
|
|
}
|
2015-05-05 17:21:58 -07:00
|
|
|
mSectionTextPaint.setAlpha(alpha);
|
|
|
|
|
}
|
2015-05-08 12:04:45 -07:00
|
|
|
c.drawText(sectionName, x, y, mSectionTextPaint);
|
2015-05-07 18:21:28 -07:00
|
|
|
|
|
|
|
|
lastSectionTop = y;
|
2015-05-08 12:04:45 -07:00
|
|
|
lastSectionHeight = (int) (sectionBounds.y + mSectionHeaderOffset);
|
|
|
|
|
lastSectionName = sectionName;
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
2015-05-08 12:04:45 -07:00
|
|
|
i += (sectionInfo.numApps - item.sectionAppIndex);
|
2015-05-05 17:21:58 -07:00
|
|
|
}
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
|
|
|
|
|
RecyclerView.State state) {
|
|
|
|
|
// Do nothing
|
|
|
|
|
}
|
2015-05-04 15:28:34 -07:00
|
|
|
|
2015-05-07 18:21:28 -07:00
|
|
|
/**
|
2015-05-08 12:04:45 -07:00
|
|
|
* Given a section name, return the bounds of the given section name.
|
2015-05-07 18:21:28 -07:00
|
|
|
*/
|
|
|
|
|
private PointF getAndCacheSectionBounds(String sectionName) {
|
|
|
|
|
PointF bounds = mCachedSectionBounds.get(sectionName);
|
2015-05-05 17:21:58 -07:00
|
|
|
if (bounds == null) {
|
|
|
|
|
mSectionTextPaint.getTextBounds(sectionName, 0, sectionName.length(), mTmpBounds);
|
2015-05-07 18:21:28 -07:00
|
|
|
bounds = new PointF(mSectionTextPaint.measureText(sectionName), mTmpBounds.height());
|
2015-05-05 17:21:58 -07:00
|
|
|
mCachedSectionBounds.put(sectionName, bounds);
|
|
|
|
|
}
|
|
|
|
|
return bounds;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 18:21:28 -07:00
|
|
|
/**
|
2015-05-08 17:34:17 -07:00
|
|
|
* Returns whether we consider this a valid view holder for us to draw a divider or section for.
|
2015-05-07 18:21:28 -07:00
|
|
|
*/
|
2015-05-08 17:34:17 -07:00
|
|
|
private boolean isValidHolderAndChild(ViewHolder holder, View child,
|
2015-05-04 15:28:34 -07:00
|
|
|
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;
|
|
|
|
|
}
|
2015-05-08 17:34:17 -07:00
|
|
|
// 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 divider for a given child.
|
|
|
|
|
*/
|
|
|
|
|
private boolean shouldDrawItemDivider(ViewHolder holder, List<AlphabeticalAppsList.AdapterItem> items) {
|
|
|
|
|
int pos = holder.getPosition();
|
|
|
|
|
return items.get(pos).isPredictedApp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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);
|
|
|
|
|
|
2015-05-04 15:28:34 -07:00
|
|
|
// Ensure it's not an empty row
|
|
|
|
|
if (holder.mIsEmptyRow) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-05-08 17:34:17 -07:00
|
|
|
// Ensure this is not a section break
|
|
|
|
|
if (item.isSectionHeader) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Ensure this is not a predicted app
|
|
|
|
|
if (item.isPredictedApp) {
|
2015-05-04 15:28:34 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
2015-05-07 18:21:28 -07:00
|
|
|
// Draw the section header for the first item in each section
|
2015-05-08 17:34:17 -07:00
|
|
|
return (childIndex == 0) || (items.get(pos - 1).isSectionHeader && !item.isSectionHeader);
|
2015-05-04 15:28:34 -07:00
|
|
|
}
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private LayoutInflater mLayoutInflater;
|
2015-03-18 14:16:05 -07:00
|
|
|
@Thunk AlphabeticalAppsList mApps;
|
2015-04-08 10:27:49 -07:00
|
|
|
private GridLayoutManager mGridLayoutMgr;
|
2015-03-10 16:28:47 -07:00
|
|
|
private GridSpanSizer mGridSizer;
|
|
|
|
|
private GridItemDecoration mItemDecoration;
|
|
|
|
|
private View.OnTouchListener mTouchListener;
|
|
|
|
|
private View.OnClickListener mIconClickListener;
|
|
|
|
|
private View.OnLongClickListener mIconLongClickListener;
|
2015-03-18 14:16:05 -07:00
|
|
|
@Thunk int mAppsPerRow;
|
|
|
|
|
@Thunk boolean mIsRtl;
|
2015-03-13 11:14:16 -07:00
|
|
|
private String mEmptySearchText;
|
2015-03-10 16:28:47 -07:00
|
|
|
|
|
|
|
|
// Section drawing
|
2015-03-18 14:16:05 -07:00
|
|
|
@Thunk int mPaddingStart;
|
|
|
|
|
@Thunk int mStartMargin;
|
2015-05-05 17:21:58 -07:00
|
|
|
@Thunk int mSectionHeaderOffset;
|
2015-03-18 14:16:05 -07:00
|
|
|
@Thunk Paint mSectionTextPaint;
|
2015-05-08 17:34:17 -07:00
|
|
|
@Thunk Paint mPredictedAppsDividerPaint;
|
2015-03-10 16:28:47 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
public AppsGridAdapter(Context context, AlphabeticalAppsList apps, int appsPerRow,
|
|
|
|
|
View.OnTouchListener touchListener, View.OnClickListener iconClickListener,
|
|
|
|
|
View.OnLongClickListener iconLongClickListener) {
|
|
|
|
|
Resources res = context.getResources();
|
|
|
|
|
mApps = apps;
|
|
|
|
|
mAppsPerRow = appsPerRow;
|
|
|
|
|
mGridSizer = new GridSpanSizer();
|
2015-04-08 10:27:49 -07:00
|
|
|
mGridLayoutMgr = new GridLayoutManager(context, appsPerRow, GridLayoutManager.VERTICAL,
|
|
|
|
|
false);
|
|
|
|
|
mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
|
2015-03-10 16:28:47 -07:00
|
|
|
mItemDecoration = new GridItemDecoration();
|
|
|
|
|
mLayoutInflater = LayoutInflater.from(context);
|
|
|
|
|
mTouchListener = touchListener;
|
|
|
|
|
mIconClickListener = iconClickListener;
|
|
|
|
|
mIconLongClickListener = iconLongClickListener;
|
2015-05-11 22:12:38 -07:00
|
|
|
mStartMargin = res.getDimensionPixelSize(R.dimen.apps_grid_view_start_margin);
|
|
|
|
|
mSectionHeaderOffset = res.getDimensionPixelSize(R.dimen.apps_grid_section_y_offset);
|
2015-03-16 12:39:05 -07:00
|
|
|
mPaddingStart = res.getDimensionPixelSize(R.dimen.apps_container_inset);
|
2015-05-08 17:34:17 -07:00
|
|
|
|
2015-03-10 16:28:47 -07:00
|
|
|
mSectionTextPaint = new Paint();
|
|
|
|
|
mSectionTextPaint.setTextSize(res.getDimensionPixelSize(
|
|
|
|
|
R.dimen.apps_view_section_text_size));
|
|
|
|
|
mSectionTextPaint.setColor(res.getColor(R.color.apps_view_section_text_color));
|
|
|
|
|
mSectionTextPaint.setAntiAlias(true);
|
2015-05-08 17:34:17 -07:00
|
|
|
|
|
|
|
|
mPredictedAppsDividerPaint = new Paint();
|
|
|
|
|
mPredictedAppsDividerPaint.setStrokeWidth(DynamicGrid.pxFromDp(1.5f, res.getDisplayMetrics()));
|
|
|
|
|
mPredictedAppsDividerPaint.setColor(0x10000000);
|
|
|
|
|
mPredictedAppsDividerPaint.setAntiAlias(true);
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
|
|
|
|
|
2015-04-08 10:27:49 -07:00
|
|
|
/**
|
|
|
|
|
* Sets the number of apps per row.
|
|
|
|
|
*/
|
|
|
|
|
public void setNumAppsPerRow(int appsPerRow) {
|
|
|
|
|
mAppsPerRow = appsPerRow;
|
|
|
|
|
mGridLayoutMgr.setSpanCount(appsPerRow);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-10 16:28:47 -07:00
|
|
|
/**
|
|
|
|
|
* Sets whether we are in RTL mode.
|
|
|
|
|
*/
|
|
|
|
|
public void setRtl(boolean rtl) {
|
|
|
|
|
mIsRtl = rtl;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-13 11:14:16 -07:00
|
|
|
/**
|
|
|
|
|
* Sets the text to show when there are no apps.
|
|
|
|
|
*/
|
|
|
|
|
public void setEmptySearchText(String query) {
|
|
|
|
|
mEmptySearchText = query;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-10 16:28:47 -07:00
|
|
|
/**
|
|
|
|
|
* Returns the grid layout manager.
|
|
|
|
|
*/
|
2015-05-05 17:21:58 -07:00
|
|
|
public GridLayoutManager getLayoutManager() {
|
2015-04-08 10:27:49 -07:00
|
|
|
return mGridLayoutMgr;
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the item decoration for the recycler view.
|
|
|
|
|
*/
|
|
|
|
|
public RecyclerView.ItemDecoration getItemDecoration() {
|
2015-05-05 17:21:58 -07:00
|
|
|
// We don't draw any headers when we are uncomfortably dense
|
2015-05-11 22:12:38 -07:00
|
|
|
return mItemDecoration;
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the left padding for the recycler view.
|
|
|
|
|
*/
|
|
|
|
|
public int getContentMarginStart() {
|
|
|
|
|
return mStartMargin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
|
|
|
|
switch (viewType) {
|
2015-03-13 11:14:16 -07:00
|
|
|
case EMPTY_VIEW_TYPE:
|
|
|
|
|
return new ViewHolder(mLayoutInflater.inflate(R.layout.apps_empty_view, parent,
|
2015-05-08 17:34:17 -07:00
|
|
|
false), true /* isEmptyRow */);
|
2015-03-10 16:28:47 -07:00
|
|
|
case SECTION_BREAK_VIEW_TYPE:
|
2015-05-08 17:34:17 -07:00
|
|
|
return new ViewHolder(new View(parent.getContext()), false /* isEmptyRow */);
|
2015-03-10 16:28:47 -07:00
|
|
|
case ICON_VIEW_TYPE:
|
|
|
|
|
BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
|
|
|
|
|
R.layout.apps_grid_row_icon_view, parent, false);
|
|
|
|
|
icon.setOnTouchListener(mTouchListener);
|
|
|
|
|
icon.setOnClickListener(mIconClickListener);
|
|
|
|
|
icon.setOnLongClickListener(mIconLongClickListener);
|
|
|
|
|
icon.setFocusable(true);
|
2015-05-08 17:34:17 -07:00
|
|
|
return new ViewHolder(icon, false /* isEmptyRow */);
|
2015-03-10 16:28:47 -07:00
|
|
|
default:
|
|
|
|
|
throw new RuntimeException("Unexpected view type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
2015-03-13 11:14:16 -07:00
|
|
|
switch (holder.getItemViewType()) {
|
|
|
|
|
case ICON_VIEW_TYPE:
|
2015-04-06 15:12:49 -07:00
|
|
|
AppInfo info = mApps.getAdapterItems().get(position).appInfo;
|
2015-03-13 11:14:16 -07:00
|
|
|
BubbleTextView icon = (BubbleTextView) holder.mContent;
|
|
|
|
|
icon.applyFromApplicationInfo(info);
|
|
|
|
|
break;
|
|
|
|
|
case EMPTY_VIEW_TYPE:
|
|
|
|
|
TextView emptyViewText = (TextView) holder.mContent.findViewById(R.id.empty_text);
|
|
|
|
|
emptyViewText.setText(mEmptySearchText);
|
|
|
|
|
break;
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public int getItemCount() {
|
2015-03-13 11:14:16 -07:00
|
|
|
if (mApps.hasNoFilteredResults()) {
|
|
|
|
|
// For the empty view
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2015-04-06 15:12:49 -07:00
|
|
|
return mApps.getAdapterItems().size();
|
2015-03-10 16:28:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public int getItemViewType(int position) {
|
2015-03-13 11:14:16 -07:00
|
|
|
if (mApps.hasNoFilteredResults()) {
|
|
|
|
|
return EMPTY_VIEW_TYPE;
|
2015-04-06 15:12:49 -07:00
|
|
|
} else if (mApps.getAdapterItems().get(position).isSectionHeader) {
|
2015-03-10 16:28:47 -07:00
|
|
|
return SECTION_BREAK_VIEW_TYPE;
|
|
|
|
|
}
|
|
|
|
|
return ICON_VIEW_TYPE;
|
|
|
|
|
}
|
|
|
|
|
}
|