Loading quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java +10 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,9 @@ import android.view.WindowInsets; import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.allapps.AllAppsGridAdapter; import com.android.launcher3.allapps.AlphabeticalAppsList; import com.android.launcher3.allapps.BaseAdapterProvider; import com.android.launcher3.allapps.BaseAllAppsAdapter; import com.android.launcher3.allapps.BaseAllAppsContainerView; import com.android.launcher3.allapps.search.SearchAdapterProvider; Loading Loading @@ -79,4 +82,11 @@ public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<Taskba setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect()); return super.onApplyWindowInsets(insets); } @Override protected BaseAllAppsAdapter getAdapter(AlphabeticalAppsList<TaskbarAllAppsContext> mAppsList, BaseAdapterProvider[] adapterProviders) { return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList, adapterProviders); } } src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +7 −0 Original line number Diff line number Diff line Loading @@ -256,4 +256,11 @@ public class ActivityAllAppsContainerView<T extends BaseDraggingActivity> extend layoutParams.removeRule(RelativeLayout.BELOW); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); } @Override protected BaseAllAppsAdapter getAdapter(AlphabeticalAppsList<T> mAppsList, BaseAdapterProvider[] adapterProviders) { return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList, adapterProviders); } } src/com/android/launcher3/allapps/AllAppsGridAdapter.java +28 −313 Original line number Diff line number Diff line Loading @@ -15,36 +15,20 @@ */ package com.android.launcher3.allapps; import static com.android.launcher3.touch.ItemLongClickListener.INSTANCE_ALL_APPS; import android.content.Context; import android.content.res.Resources; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.view.accessibility.AccessibilityEventCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.core.view.accessibility.AccessibilityRecordCompat; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.BubbleTextView; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.views.ActivityContext; import java.util.Arrays; import java.util.List; /** Loading @@ -53,111 +37,26 @@ import java.util.List; * @param <T> Type of context inflating all apps. */ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> { BaseAllAppsAdapter<T> { public static final String TAG = "AppsGridAdapter"; private final GridLayoutManager mGridLayoutMgr; private final GridSpanSizer mGridSizer; // A normal icon public static final int VIEW_TYPE_ICON = 1 << 1; // The message shown when there are no filtered results public static final int VIEW_TYPE_EMPTY_SEARCH = 1 << 2; // The message to continue to a market search when there are no filtered results public static final int VIEW_TYPE_SEARCH_MARKET = 1 << 3; // We use various dividers for various purposes. They share enough attributes to reuse layouts, // but differ in enough attributes to require different view types // A divider that separates the apps list and the search market button public static final int VIEW_TYPE_ALL_APPS_DIVIDER = 1 << 4; // Common view type masks public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER; public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON; private final BaseAdapterProvider[] mAdapterProviders; /** * ViewHolder for each icon. */ public static class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(View v) { super(v); } } /** * Info about a particular adapter item (can be either section or app) */ public static class AdapterItem { /** Common properties */ // The index of this adapter item in the list public int position; // The type of this item public int viewType; // The section name of this item. Note that there can be multiple items with different // sectionNames in the same section public String sectionName = null; // The row that this item shows up on public int rowIndex; // The index of this app in the row public int rowAppIndex; // The associated ItemInfoWithIcon for the item public ItemInfoWithIcon itemInfo = null; // The index of this app not including sections public int appIndex = -1; // Search section associated to result public DecorationInfo decorationInfo = null; /** * Factory method for AppIcon AdapterItem */ public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo, int appIndex) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ICON; item.position = pos; item.sectionName = sectionName; item.itemInfo = appInfo; item.appIndex = appIndex; return item; } /** * Factory method for empty search results view */ public static AdapterItem asEmptySearch(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_EMPTY_SEARCH; item.position = pos; return item; } /** * Factory method for a dividerView in AllAppsSearch */ public static AdapterItem asAllAppsDivider(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ALL_APPS_DIVIDER; item.position = pos; return item; public AllAppsGridAdapter(T activityContext, LayoutInflater inflater, AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) { super(activityContext, inflater, apps, adapterProviders); mGridSizer = new GridSpanSizer(); mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext); mGridLayoutMgr.setSpanSizeLookup(mGridSizer); setAppsPerRow(activityContext.getDeviceProfile().numShownAllAppsColumns); } /** * Factory method for a market search button * Returns the grid layout manager. */ public static AdapterItem asMarketSearch(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_SEARCH_MARKET; item.position = pos; return item; } protected boolean isCountedForAccessibility() { return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_SEARCH_MARKET; } public RecyclerView.LayoutManager getLayoutManager() { return mGridLayoutMgr; } /** Loading Loading @@ -217,7 +116,7 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends */ private int getRowsNotForAccessibility(int adapterPosition) { List<AdapterItem> items = mApps.getAdapterItems(); adapterPosition = Math.max(adapterPosition, mApps.getAdapterItems().size() - 1); adapterPosition = Math.max(adapterPosition, items.size() - 1); int extraRows = 0; for (int i = 0; i <= adapterPosition; i++) { if (!isViewType(items.get(i).viewType, VIEW_TYPE_MASK_ICON)) { Loading @@ -228,73 +127,7 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends } } /** * Helper class to size the grid items. */ public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup { public GridSpanSizer() { super(); setSpanIndexCacheEnabled(true); } @Override public int getSpanSize(int position) { int viewType = mApps.getAdapterItems().get(position).viewType; int totalSpans = mGridLayoutMgr.getSpanCount(); if (isIconViewType(viewType)) { return totalSpans / mAppsPerRow; } else { BaseAdapterProvider adapterProvider = getAdapterProvider(viewType); if (adapterProvider != null) { return totalSpans / adapterProvider.getItemsPerRow(viewType, mAppsPerRow); } // Section breaks span the full width return totalSpans; } } } private final T mActivityContext; private final LayoutInflater mLayoutInflater; private final AlphabeticalAppsList<T> mApps; private final GridLayoutManager mGridLayoutMgr; private final GridSpanSizer mGridSizer; private final OnClickListener mOnIconClickListener; private OnLongClickListener mOnIconLongClickListener = INSTANCE_ALL_APPS; private int mAppsPerRow; private OnFocusChangeListener mIconFocusListener; // The text to show when there are no search results and no market search handler. protected String mEmptySearchMessage; // The click listener to send off to the market app, updated each time the search query changes. private OnClickListener mMarketSearchClickListener; private final int mExtraHeight; public AllAppsGridAdapter(T activityContext, LayoutInflater inflater, AlphabeticalAppsList<T> apps, BaseAdapterProvider[] adapterProviders) { Resources res = activityContext.getResources(); mActivityContext = activityContext; mApps = apps; mEmptySearchMessage = res.getString(R.string.all_apps_loading_message); mGridSizer = new GridSpanSizer(); mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext); mGridLayoutMgr.setSpanSizeLookup(mGridSizer); mLayoutInflater = inflater; mOnIconClickListener = mActivityContext.getItemOnClickListener(); mAdapterProviders = adapterProviders; setAppsPerRow(mActivityContext.getDeviceProfile().numShownAllAppsColumns); mExtraHeight = mActivityContext.getResources().getDimensionPixelSize( R.dimen.all_apps_height_extra); } public void setAppsPerRow(int appsPerRow) { mAppsPerRow = appsPerRow; int totalSpans = mAppsPerRow; Loading @@ -309,148 +142,30 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends } /** * Sets the long click listener for icons */ public void setOnIconLongClickListener(@Nullable OnLongClickListener listener) { mOnIconLongClickListener = listener; } public static boolean isDividerViewType(int viewType) { return isViewType(viewType, VIEW_TYPE_MASK_DIVIDER); } public static boolean isIconViewType(int viewType) { return isViewType(viewType, VIEW_TYPE_MASK_ICON); } public static boolean isViewType(int viewType, int viewTypeMask) { return (viewType & viewTypeMask) != 0; } public void setIconFocusListener(OnFocusChangeListener focusListener) { mIconFocusListener = focusListener; } /** * Sets the last search query that was made, used to show when there are no results and to also * seed the intent for searching the market. */ public void setLastSearchQuery(String query, OnClickListener marketSearchClickListener) { Resources res = mActivityContext.getResources(); mEmptySearchMessage = res.getString(R.string.all_apps_no_search_results, query); mMarketSearchClickListener = marketSearchClickListener; } /** * Returns the grid layout manager. * Helper class to size the grid items. */ public GridLayoutManager getLayoutManager() { return mGridLayoutMgr; } public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup { @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case VIEW_TYPE_ICON: int layout = !FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get() ? R.layout.all_apps_icon : R.layout.all_apps_icon_twoline; BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate( layout, parent, false); icon.setLongPressTimeoutFactor(1f); icon.setOnFocusChangeListener(mIconFocusListener); icon.setOnClickListener(mOnIconClickListener); icon.setOnLongClickListener(mOnIconLongClickListener); // Ensure the all apps icon height matches the workspace icons in portrait mode. icon.getLayoutParams().height = mActivityContext.getDeviceProfile().allAppsCellHeightPx; if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()) { icon.getLayoutParams().height += mExtraHeight; } return new ViewHolder(icon); case VIEW_TYPE_EMPTY_SEARCH: return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search, parent, false)); case VIEW_TYPE_SEARCH_MARKET: View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market, parent, false); searchMarketView.setOnClickListener(mMarketSearchClickListener); return new ViewHolder(searchMarketView); case VIEW_TYPE_ALL_APPS_DIVIDER: return new ViewHolder(mLayoutInflater.inflate( R.layout.all_apps_divider, parent, false)); default: BaseAdapterProvider adapterProvider = getAdapterProvider(viewType); if (adapterProvider != null) { return adapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType); } throw new RuntimeException("Unexpected view type" + viewType); } public GridSpanSizer() { super(); setSpanIndexCacheEnabled(true); } @Override public void onBindViewHolder(ViewHolder holder, int position) { switch (holder.getItemViewType()) { case VIEW_TYPE_ICON: AdapterItem adapterItem = mApps.getAdapterItems().get(position); BubbleTextView icon = (BubbleTextView) holder.itemView; icon.reset(); if (adapterItem.itemInfo instanceof AppInfo) { icon.applyFromApplicationInfo((AppInfo) adapterItem.itemInfo); } else { icon.applyFromItemInfoWithIcon(adapterItem.itemInfo); } break; case VIEW_TYPE_EMPTY_SEARCH: 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.itemView; if (mMarketSearchClickListener != null) { searchView.setVisibility(View.VISIBLE); public int getSpanSize(int position) { int viewType = mApps.getAdapterItems().get(position).viewType; int totalSpans = mGridLayoutMgr.getSpanCount(); if (isIconViewType(viewType)) { return totalSpans / mAppsPerRow; } else { searchView.setVisibility(View.GONE); } break; case VIEW_TYPE_ALL_APPS_DIVIDER: // nothing to do break; default: BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType()); BaseAdapterProvider adapterProvider = getAdapterProvider(viewType); if (adapterProvider != null) { adapterProvider.onBindView(holder, position); } } } @Override public void onViewRecycled(@NonNull ViewHolder holder) { super.onViewRecycled(holder); } @Override public boolean onFailedToRecycleView(ViewHolder holder) { // Always recycle and we will reset the view when it is bound return true; return totalSpans / adapterProvider.getItemsPerRow(viewType, mAppsPerRow); } @Override public int getItemCount() { return mApps.getAdapterItems().size(); // Section breaks span the full width return totalSpans; } @Override public int getItemViewType(int position) { AdapterItem item = mApps.getAdapterItems().get(position); return item.viewType; } @Nullable private BaseAdapterProvider getAdapterProvider(int viewType) { return Arrays.stream(mAdapterProviders).filter( adapterProvider -> adapterProvider.isViewSupported(viewType)).findFirst().orElse( null); } } src/com/android/launcher3/allapps/AlphabeticalAppsList.java +3 −3 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ package com.android.launcher3.allapps; import android.content.Context; import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem; import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.util.ItemInfoMatcher; Loading Loading @@ -82,7 +82,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement // The of ordered component names as a result of a search query private ArrayList<AdapterItem> mSearchResults; private AllAppsGridAdapter<T> mAdapter; private BaseAllAppsAdapter<T> mAdapter; private AppInfoComparator mAppNameComparator; private final int mNumAppsPerRow; private int mNumAppRowsInAdapter; Loading @@ -106,7 +106,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement /** * Sets the adapter to notify when this dataset changes. */ public void setAdapter(AllAppsGridAdapter<T> adapter) { public void setAdapter(BaseAllAppsAdapter<T> adapter) { mAdapter = adapter; } Loading src/com/android/launcher3/allapps/BaseAllAppsAdapter.java 0 → 100644 +333 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java +10 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,9 @@ import android.view.WindowInsets; import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.allapps.AllAppsGridAdapter; import com.android.launcher3.allapps.AlphabeticalAppsList; import com.android.launcher3.allapps.BaseAdapterProvider; import com.android.launcher3.allapps.BaseAllAppsAdapter; import com.android.launcher3.allapps.BaseAllAppsContainerView; import com.android.launcher3.allapps.search.SearchAdapterProvider; Loading Loading @@ -79,4 +82,11 @@ public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<Taskba setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect()); return super.onApplyWindowInsets(insets); } @Override protected BaseAllAppsAdapter getAdapter(AlphabeticalAppsList<TaskbarAllAppsContext> mAppsList, BaseAdapterProvider[] adapterProviders) { return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList, adapterProviders); } }
src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +7 −0 Original line number Diff line number Diff line Loading @@ -256,4 +256,11 @@ public class ActivityAllAppsContainerView<T extends BaseDraggingActivity> extend layoutParams.removeRule(RelativeLayout.BELOW); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); } @Override protected BaseAllAppsAdapter getAdapter(AlphabeticalAppsList<T> mAppsList, BaseAdapterProvider[] adapterProviders) { return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList, adapterProviders); } }
src/com/android/launcher3/allapps/AllAppsGridAdapter.java +28 −313 Original line number Diff line number Diff line Loading @@ -15,36 +15,20 @@ */ package com.android.launcher3.allapps; import static com.android.launcher3.touch.ItemLongClickListener.INSTANCE_ALL_APPS; import android.content.Context; import android.content.res.Resources; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.view.accessibility.AccessibilityEventCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.core.view.accessibility.AccessibilityRecordCompat; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.BubbleTextView; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.views.ActivityContext; import java.util.Arrays; import java.util.List; /** Loading @@ -53,111 +37,26 @@ import java.util.List; * @param <T> Type of context inflating all apps. */ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> { BaseAllAppsAdapter<T> { public static final String TAG = "AppsGridAdapter"; private final GridLayoutManager mGridLayoutMgr; private final GridSpanSizer mGridSizer; // A normal icon public static final int VIEW_TYPE_ICON = 1 << 1; // The message shown when there are no filtered results public static final int VIEW_TYPE_EMPTY_SEARCH = 1 << 2; // The message to continue to a market search when there are no filtered results public static final int VIEW_TYPE_SEARCH_MARKET = 1 << 3; // We use various dividers for various purposes. They share enough attributes to reuse layouts, // but differ in enough attributes to require different view types // A divider that separates the apps list and the search market button public static final int VIEW_TYPE_ALL_APPS_DIVIDER = 1 << 4; // Common view type masks public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER; public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON; private final BaseAdapterProvider[] mAdapterProviders; /** * ViewHolder for each icon. */ public static class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(View v) { super(v); } } /** * Info about a particular adapter item (can be either section or app) */ public static class AdapterItem { /** Common properties */ // The index of this adapter item in the list public int position; // The type of this item public int viewType; // The section name of this item. Note that there can be multiple items with different // sectionNames in the same section public String sectionName = null; // The row that this item shows up on public int rowIndex; // The index of this app in the row public int rowAppIndex; // The associated ItemInfoWithIcon for the item public ItemInfoWithIcon itemInfo = null; // The index of this app not including sections public int appIndex = -1; // Search section associated to result public DecorationInfo decorationInfo = null; /** * Factory method for AppIcon AdapterItem */ public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo, int appIndex) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ICON; item.position = pos; item.sectionName = sectionName; item.itemInfo = appInfo; item.appIndex = appIndex; return item; } /** * Factory method for empty search results view */ public static AdapterItem asEmptySearch(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_EMPTY_SEARCH; item.position = pos; return item; } /** * Factory method for a dividerView in AllAppsSearch */ public static AdapterItem asAllAppsDivider(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ALL_APPS_DIVIDER; item.position = pos; return item; public AllAppsGridAdapter(T activityContext, LayoutInflater inflater, AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) { super(activityContext, inflater, apps, adapterProviders); mGridSizer = new GridSpanSizer(); mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext); mGridLayoutMgr.setSpanSizeLookup(mGridSizer); setAppsPerRow(activityContext.getDeviceProfile().numShownAllAppsColumns); } /** * Factory method for a market search button * Returns the grid layout manager. */ public static AdapterItem asMarketSearch(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_SEARCH_MARKET; item.position = pos; return item; } protected boolean isCountedForAccessibility() { return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_SEARCH_MARKET; } public RecyclerView.LayoutManager getLayoutManager() { return mGridLayoutMgr; } /** Loading Loading @@ -217,7 +116,7 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends */ private int getRowsNotForAccessibility(int adapterPosition) { List<AdapterItem> items = mApps.getAdapterItems(); adapterPosition = Math.max(adapterPosition, mApps.getAdapterItems().size() - 1); adapterPosition = Math.max(adapterPosition, items.size() - 1); int extraRows = 0; for (int i = 0; i <= adapterPosition; i++) { if (!isViewType(items.get(i).viewType, VIEW_TYPE_MASK_ICON)) { Loading @@ -228,73 +127,7 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends } } /** * Helper class to size the grid items. */ public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup { public GridSpanSizer() { super(); setSpanIndexCacheEnabled(true); } @Override public int getSpanSize(int position) { int viewType = mApps.getAdapterItems().get(position).viewType; int totalSpans = mGridLayoutMgr.getSpanCount(); if (isIconViewType(viewType)) { return totalSpans / mAppsPerRow; } else { BaseAdapterProvider adapterProvider = getAdapterProvider(viewType); if (adapterProvider != null) { return totalSpans / adapterProvider.getItemsPerRow(viewType, mAppsPerRow); } // Section breaks span the full width return totalSpans; } } } private final T mActivityContext; private final LayoutInflater mLayoutInflater; private final AlphabeticalAppsList<T> mApps; private final GridLayoutManager mGridLayoutMgr; private final GridSpanSizer mGridSizer; private final OnClickListener mOnIconClickListener; private OnLongClickListener mOnIconLongClickListener = INSTANCE_ALL_APPS; private int mAppsPerRow; private OnFocusChangeListener mIconFocusListener; // The text to show when there are no search results and no market search handler. protected String mEmptySearchMessage; // The click listener to send off to the market app, updated each time the search query changes. private OnClickListener mMarketSearchClickListener; private final int mExtraHeight; public AllAppsGridAdapter(T activityContext, LayoutInflater inflater, AlphabeticalAppsList<T> apps, BaseAdapterProvider[] adapterProviders) { Resources res = activityContext.getResources(); mActivityContext = activityContext; mApps = apps; mEmptySearchMessage = res.getString(R.string.all_apps_loading_message); mGridSizer = new GridSpanSizer(); mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext); mGridLayoutMgr.setSpanSizeLookup(mGridSizer); mLayoutInflater = inflater; mOnIconClickListener = mActivityContext.getItemOnClickListener(); mAdapterProviders = adapterProviders; setAppsPerRow(mActivityContext.getDeviceProfile().numShownAllAppsColumns); mExtraHeight = mActivityContext.getResources().getDimensionPixelSize( R.dimen.all_apps_height_extra); } public void setAppsPerRow(int appsPerRow) { mAppsPerRow = appsPerRow; int totalSpans = mAppsPerRow; Loading @@ -309,148 +142,30 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends } /** * Sets the long click listener for icons */ public void setOnIconLongClickListener(@Nullable OnLongClickListener listener) { mOnIconLongClickListener = listener; } public static boolean isDividerViewType(int viewType) { return isViewType(viewType, VIEW_TYPE_MASK_DIVIDER); } public static boolean isIconViewType(int viewType) { return isViewType(viewType, VIEW_TYPE_MASK_ICON); } public static boolean isViewType(int viewType, int viewTypeMask) { return (viewType & viewTypeMask) != 0; } public void setIconFocusListener(OnFocusChangeListener focusListener) { mIconFocusListener = focusListener; } /** * Sets the last search query that was made, used to show when there are no results and to also * seed the intent for searching the market. */ public void setLastSearchQuery(String query, OnClickListener marketSearchClickListener) { Resources res = mActivityContext.getResources(); mEmptySearchMessage = res.getString(R.string.all_apps_no_search_results, query); mMarketSearchClickListener = marketSearchClickListener; } /** * Returns the grid layout manager. * Helper class to size the grid items. */ public GridLayoutManager getLayoutManager() { return mGridLayoutMgr; } public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup { @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case VIEW_TYPE_ICON: int layout = !FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get() ? R.layout.all_apps_icon : R.layout.all_apps_icon_twoline; BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate( layout, parent, false); icon.setLongPressTimeoutFactor(1f); icon.setOnFocusChangeListener(mIconFocusListener); icon.setOnClickListener(mOnIconClickListener); icon.setOnLongClickListener(mOnIconLongClickListener); // Ensure the all apps icon height matches the workspace icons in portrait mode. icon.getLayoutParams().height = mActivityContext.getDeviceProfile().allAppsCellHeightPx; if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()) { icon.getLayoutParams().height += mExtraHeight; } return new ViewHolder(icon); case VIEW_TYPE_EMPTY_SEARCH: return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search, parent, false)); case VIEW_TYPE_SEARCH_MARKET: View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market, parent, false); searchMarketView.setOnClickListener(mMarketSearchClickListener); return new ViewHolder(searchMarketView); case VIEW_TYPE_ALL_APPS_DIVIDER: return new ViewHolder(mLayoutInflater.inflate( R.layout.all_apps_divider, parent, false)); default: BaseAdapterProvider adapterProvider = getAdapterProvider(viewType); if (adapterProvider != null) { return adapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType); } throw new RuntimeException("Unexpected view type" + viewType); } public GridSpanSizer() { super(); setSpanIndexCacheEnabled(true); } @Override public void onBindViewHolder(ViewHolder holder, int position) { switch (holder.getItemViewType()) { case VIEW_TYPE_ICON: AdapterItem adapterItem = mApps.getAdapterItems().get(position); BubbleTextView icon = (BubbleTextView) holder.itemView; icon.reset(); if (adapterItem.itemInfo instanceof AppInfo) { icon.applyFromApplicationInfo((AppInfo) adapterItem.itemInfo); } else { icon.applyFromItemInfoWithIcon(adapterItem.itemInfo); } break; case VIEW_TYPE_EMPTY_SEARCH: 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.itemView; if (mMarketSearchClickListener != null) { searchView.setVisibility(View.VISIBLE); public int getSpanSize(int position) { int viewType = mApps.getAdapterItems().get(position).viewType; int totalSpans = mGridLayoutMgr.getSpanCount(); if (isIconViewType(viewType)) { return totalSpans / mAppsPerRow; } else { searchView.setVisibility(View.GONE); } break; case VIEW_TYPE_ALL_APPS_DIVIDER: // nothing to do break; default: BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType()); BaseAdapterProvider adapterProvider = getAdapterProvider(viewType); if (adapterProvider != null) { adapterProvider.onBindView(holder, position); } } } @Override public void onViewRecycled(@NonNull ViewHolder holder) { super.onViewRecycled(holder); } @Override public boolean onFailedToRecycleView(ViewHolder holder) { // Always recycle and we will reset the view when it is bound return true; return totalSpans / adapterProvider.getItemsPerRow(viewType, mAppsPerRow); } @Override public int getItemCount() { return mApps.getAdapterItems().size(); // Section breaks span the full width return totalSpans; } @Override public int getItemViewType(int position) { AdapterItem item = mApps.getAdapterItems().get(position); return item.viewType; } @Nullable private BaseAdapterProvider getAdapterProvider(int viewType) { return Arrays.stream(mAdapterProviders).filter( adapterProvider -> adapterProvider.isViewSupported(viewType)).findFirst().orElse( null); } }
src/com/android/launcher3/allapps/AlphabeticalAppsList.java +3 −3 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ package com.android.launcher3.allapps; import android.content.Context; import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem; import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.util.ItemInfoMatcher; Loading Loading @@ -82,7 +82,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement // The of ordered component names as a result of a search query private ArrayList<AdapterItem> mSearchResults; private AllAppsGridAdapter<T> mAdapter; private BaseAllAppsAdapter<T> mAdapter; private AppInfoComparator mAppNameComparator; private final int mNumAppsPerRow; private int mNumAppRowsInAdapter; Loading @@ -106,7 +106,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement /** * Sets the adapter to notify when this dataset changes. */ public void setAdapter(AllAppsGridAdapter<T> adapter) { public void setAdapter(BaseAllAppsAdapter<T> adapter) { mAdapter = adapter; } Loading
src/com/android/launcher3/allapps/BaseAllAppsAdapter.java 0 → 100644 +333 −0 File added.Preview size limit exceeded, changes collapsed. Show changes