Merge "Extract out common adapter logic to support different AllApps layouts" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c19c0f9eab
@@ -25,6 +25,9 @@ import android.view.WindowInsets;
|
|||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.android.launcher3.allapps.AllAppsGridAdapter;
|
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.BaseAllAppsContainerView;
|
||||||
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
||||||
|
|
||||||
@@ -79,4 +82,11 @@ public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<Taskba
|
|||||||
setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect());
|
setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect());
|
||||||
return super.onApplyWindowInsets(insets);
|
return super.onApplyWindowInsets(insets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BaseAllAppsAdapter getAdapter(AlphabeticalAppsList<TaskbarAllAppsContext> mAppsList,
|
||||||
|
BaseAdapterProvider[] adapterProviders) {
|
||||||
|
return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList,
|
||||||
|
adapterProviders);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -256,4 +256,11 @@ public class ActivityAllAppsContainerView<T extends BaseDraggingActivity> extend
|
|||||||
layoutParams.removeRule(RelativeLayout.BELOW);
|
layoutParams.removeRule(RelativeLayout.BELOW);
|
||||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BaseAllAppsAdapter getAdapter(AlphabeticalAppsList<T> mAppsList,
|
||||||
|
BaseAdapterProvider[] adapterProviders) {
|
||||||
|
return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList,
|
||||||
|
adapterProviders);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,36 +15,20 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.launcher3.allapps;
|
package com.android.launcher3.allapps;
|
||||||
|
|
||||||
import static com.android.launcher3.touch.ItemLongClickListener.INSTANCE_ALL_APPS;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
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.ViewGroup;
|
||||||
import android.view.accessibility.AccessibilityEvent;
|
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.AccessibilityEventCompat;
|
||||||
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
|
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
|
||||||
import androidx.core.view.accessibility.AccessibilityRecordCompat;
|
import androidx.core.view.accessibility.AccessibilityRecordCompat;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
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 com.android.launcher3.views.ActivityContext;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,111 +37,26 @@ import java.util.List;
|
|||||||
* @param <T> Type of context inflating all apps.
|
* @param <T> Type of context inflating all apps.
|
||||||
*/
|
*/
|
||||||
public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
|
public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
|
||||||
RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> {
|
BaseAllAppsAdapter<T> {
|
||||||
|
|
||||||
public static final String TAG = "AppsGridAdapter";
|
public static final String TAG = "AppsGridAdapter";
|
||||||
|
private final GridLayoutManager mGridLayoutMgr;
|
||||||
|
private final GridSpanSizer mGridSizer;
|
||||||
|
|
||||||
// A normal icon
|
public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
|
||||||
public static final int VIEW_TYPE_ICON = 1 << 1;
|
AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
|
||||||
// The message shown when there are no filtered results
|
super(activityContext, inflater, apps, adapterProviders);
|
||||||
public static final int VIEW_TYPE_EMPTY_SEARCH = 1 << 2;
|
mGridSizer = new GridSpanSizer();
|
||||||
// The message to continue to a market search when there are no filtered results
|
mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext);
|
||||||
public static final int VIEW_TYPE_SEARCH_MARKET = 1 << 3;
|
mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
|
||||||
|
setAppsPerRow(activityContext.getDeviceProfile().numShownAllAppsColumns);
|
||||||
// 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)
|
* Returns the grid layout manager.
|
||||||
*/
|
*/
|
||||||
public static class AdapterItem {
|
public RecyclerView.LayoutManager getLayoutManager() {
|
||||||
/** Common properties */
|
return mGridLayoutMgr;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method for a market search button
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -217,7 +116,7 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
|
|||||||
*/
|
*/
|
||||||
private int getRowsNotForAccessibility(int adapterPosition) {
|
private int getRowsNotForAccessibility(int adapterPosition) {
|
||||||
List<AdapterItem> items = mApps.getAdapterItems();
|
List<AdapterItem> items = mApps.getAdapterItems();
|
||||||
adapterPosition = Math.max(adapterPosition, mApps.getAdapterItems().size() - 1);
|
adapterPosition = Math.max(adapterPosition, items.size() - 1);
|
||||||
int extraRows = 0;
|
int extraRows = 0;
|
||||||
for (int i = 0; i <= adapterPosition; i++) {
|
for (int i = 0; i <= adapterPosition; i++) {
|
||||||
if (!isViewType(items.get(i).viewType, VIEW_TYPE_MASK_ICON)) {
|
if (!isViewType(items.get(i).viewType, VIEW_TYPE_MASK_ICON)) {
|
||||||
@@ -228,6 +127,20 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAppsPerRow(int appsPerRow) {
|
||||||
|
mAppsPerRow = appsPerRow;
|
||||||
|
int totalSpans = mAppsPerRow;
|
||||||
|
for (BaseAdapterProvider adapterProvider : mAdapterProviders) {
|
||||||
|
for (int itemPerRow : adapterProvider.getSupportedItemsPerRowArray()) {
|
||||||
|
if (totalSpans % itemPerRow != 0) {
|
||||||
|
totalSpans *= itemPerRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mGridLayoutMgr.setSpanCount(totalSpans);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to size the grid items.
|
* Helper class to size the grid items.
|
||||||
*/
|
*/
|
||||||
@@ -255,202 +168,4 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
for (BaseAdapterProvider adapterProvider : mAdapterProviders) {
|
|
||||||
for (int itemPerRow : adapterProvider.getSupportedItemsPerRowArray()) {
|
|
||||||
if (totalSpans % itemPerRow != 0) {
|
|
||||||
totalSpans *= itemPerRow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mGridLayoutMgr.setSpanCount(totalSpans);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
public GridLayoutManager getLayoutManager() {
|
|
||||||
return mGridLayoutMgr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
} else {
|
|
||||||
searchView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case VIEW_TYPE_ALL_APPS_DIVIDER:
|
|
||||||
// nothing to do
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType());
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return mApps.getAdapterItems().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package com.android.launcher3.allapps;
|
|||||||
|
|
||||||
import android.content.Context;
|
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.config.FeatureFlags;
|
||||||
import com.android.launcher3.model.data.AppInfo;
|
import com.android.launcher3.model.data.AppInfo;
|
||||||
import com.android.launcher3.util.ItemInfoMatcher;
|
import com.android.launcher3.util.ItemInfoMatcher;
|
||||||
@@ -82,7 +82,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
|||||||
|
|
||||||
// The of ordered component names as a result of a search query
|
// The of ordered component names as a result of a search query
|
||||||
private ArrayList<AdapterItem> mSearchResults;
|
private ArrayList<AdapterItem> mSearchResults;
|
||||||
private AllAppsGridAdapter<T> mAdapter;
|
private BaseAllAppsAdapter<T> mAdapter;
|
||||||
private AppInfoComparator mAppNameComparator;
|
private AppInfoComparator mAppNameComparator;
|
||||||
private final int mNumAppsPerRow;
|
private final int mNumAppsPerRow;
|
||||||
private int mNumAppRowsInAdapter;
|
private int mNumAppRowsInAdapter;
|
||||||
@@ -106,7 +106,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
|||||||
/**
|
/**
|
||||||
* Sets the adapter to notify when this dataset changes.
|
* Sets the adapter to notify when this dataset changes.
|
||||||
*/
|
*/
|
||||||
public void setAdapter(AllAppsGridAdapter<T> adapter) {
|
public void setAdapter(BaseAllAppsAdapter<T> adapter) {
|
||||||
mAdapter = adapter;
|
mAdapter = adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,333 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
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.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter for all the apps.
|
||||||
|
*
|
||||||
|
* @param <T> Type of context inflating all apps.
|
||||||
|
*/
|
||||||
|
public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> extends
|
||||||
|
RecyclerView.Adapter<BaseAllAppsAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
public static final String TAG = "BaseAllAppsAdapter";
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
|
||||||
|
protected final BaseAdapterProvider[] mAdapterProviders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewHolder for each icon.
|
||||||
|
*/
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
public ViewHolder(View v) {
|
||||||
|
super(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the number of apps to be displayed in one row of the all apps screen. */
|
||||||
|
public abstract void setAppsPerRow(int appsPerRow);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for a market search button
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final T mActivityContext;
|
||||||
|
protected final AlphabeticalAppsList<T> mApps;
|
||||||
|
// The text to show when there are no search results and no market search handler.
|
||||||
|
protected String mEmptySearchMessage;
|
||||||
|
protected int mAppsPerRow;
|
||||||
|
|
||||||
|
private final LayoutInflater mLayoutInflater;
|
||||||
|
private final OnClickListener mOnIconClickListener;
|
||||||
|
private OnLongClickListener mOnIconLongClickListener = INSTANCE_ALL_APPS;
|
||||||
|
private OnFocusChangeListener mIconFocusListener;
|
||||||
|
// 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 BaseAllAppsAdapter(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);
|
||||||
|
mLayoutInflater = inflater;
|
||||||
|
|
||||||
|
mOnIconClickListener = mActivityContext.getItemOnClickListener();
|
||||||
|
|
||||||
|
mAdapterProviders = adapterProviders;
|
||||||
|
mExtraHeight = res.getDimensionPixelSize(R.dimen.all_apps_height_extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the long click listener for icons
|
||||||
|
*/
|
||||||
|
public void setOnIconLongClickListener(@Nullable OnLongClickListener listener) {
|
||||||
|
mOnIconLongClickListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if the passed viewType represents all apps divider. */
|
||||||
|
public static boolean isDividerViewType(int viewType) {
|
||||||
|
return isViewType(viewType, VIEW_TYPE_MASK_DIVIDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if the passed viewType represents all apps icon. */
|
||||||
|
public static boolean isIconViewType(int viewType) {
|
||||||
|
return isViewType(viewType, VIEW_TYPE_MASK_ICON);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 layout manager.
|
||||||
|
*/
|
||||||
|
public abstract RecyclerView.LayoutManager getLayoutManager();
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
} else {
|
||||||
|
searchView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VIEW_TYPE_ALL_APPS_DIVIDER:
|
||||||
|
// nothing to do
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mApps.getAdapterItems().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
AdapterItem item = mApps.getAdapterItems().get(position);
|
||||||
|
return item.viewType;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean isViewType(int viewType, int viewTypeMask) {
|
||||||
|
return (viewType & viewTypeMask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected BaseAdapterProvider getAdapterProvider(int viewType) {
|
||||||
|
return Arrays.stream(mAdapterProviders).filter(
|
||||||
|
adapterProvider -> adapterProvider.isViewSupported(viewType)).findFirst().orElse(
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,7 +44,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.android.launcher3.DeviceProfile;
|
import com.android.launcher3.DeviceProfile;
|
||||||
@@ -697,18 +696,21 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte
|
|||||||
return ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, blendRatio);
|
return ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, blendRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract BaseAllAppsAdapter getAdapter(AlphabeticalAppsList<T> mAppsList,
|
||||||
|
BaseAdapterProvider[] adapterProviders);
|
||||||
|
|
||||||
protected int getHeaderBottom() {
|
protected int getHeaderBottom() {
|
||||||
return (int) getTranslationY();
|
return (int) getTranslationY();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds a {@link AllAppsGridAdapter} and related fields. */
|
/** Holds a {@link BaseAllAppsAdapter} and related fields. */
|
||||||
public class AdapterHolder {
|
public class AdapterHolder {
|
||||||
public static final int MAIN = 0;
|
public static final int MAIN = 0;
|
||||||
public static final int WORK = 1;
|
public static final int WORK = 1;
|
||||||
|
|
||||||
private final boolean mIsWork;
|
private final boolean mIsWork;
|
||||||
public final AllAppsGridAdapter<T> adapter;
|
public final BaseAllAppsAdapter<T> adapter;
|
||||||
final LinearLayoutManager mLayoutManager;
|
final RecyclerView.LayoutManager mLayoutManager;
|
||||||
final AlphabeticalAppsList<T> mAppsList;
|
final AlphabeticalAppsList<T> mAppsList;
|
||||||
final Rect mPadding = new Rect();
|
final Rect mPadding = new Rect();
|
||||||
AllAppsRecyclerView mRecyclerView;
|
AllAppsRecyclerView mRecyclerView;
|
||||||
@@ -724,8 +726,7 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte
|
|||||||
mWorkManager.getAdapterProvider()}
|
mWorkManager.getAdapterProvider()}
|
||||||
: new BaseAdapterProvider[]{mMainAdapterProvider};
|
: new BaseAdapterProvider[]{mMainAdapterProvider};
|
||||||
|
|
||||||
adapter = new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList,
|
adapter = getAdapter(mAppsList, adapterProviders);
|
||||||
adapterProviders);
|
|
||||||
mAppsList.setAdapter(adapter);
|
mAppsList.setAdapter(adapter);
|
||||||
mLayoutManager = adapter.getLayoutManager();
|
mLayoutManager = adapter.getLayoutManager();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import com.android.launcher3.BaseDraggingActivity;
|
|||||||
import com.android.launcher3.ExtendedEditText;
|
import com.android.launcher3.ExtendedEditText;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
|
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
import com.android.launcher3.search.SearchAlgorithm;
|
import com.android.launcher3.search.SearchAlgorithm;
|
||||||
import com.android.launcher3.search.SearchCallback;
|
import com.android.launcher3.search.SearchCallback;
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ import com.android.launcher3.ExtendedEditText;
|
|||||||
import com.android.launcher3.Insettable;
|
import com.android.launcher3.Insettable;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
|
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
|
||||||
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
|
|
||||||
import com.android.launcher3.allapps.AllAppsStore;
|
import com.android.launcher3.allapps.AllAppsStore;
|
||||||
import com.android.launcher3.allapps.AlphabeticalAppsList;
|
import com.android.launcher3.allapps.AlphabeticalAppsList;
|
||||||
|
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
|
||||||
import com.android.launcher3.allapps.SearchUiManager;
|
import com.android.launcher3.allapps.SearchUiManager;
|
||||||
import com.android.launcher3.search.SearchCallback;
|
import com.android.launcher3.search.SearchCallback;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import android.os.Handler;
|
|||||||
import androidx.annotation.AnyThread;
|
import androidx.annotation.AnyThread;
|
||||||
|
|
||||||
import com.android.launcher3.LauncherAppState;
|
import com.android.launcher3.LauncherAppState;
|
||||||
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
|
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
|
||||||
import com.android.launcher3.model.AllAppsList;
|
import com.android.launcher3.model.AllAppsList;
|
||||||
import com.android.launcher3.model.BaseModelUpdateTask;
|
import com.android.launcher3.model.BaseModelUpdateTask;
|
||||||
import com.android.launcher3.model.BgDataModel;
|
import com.android.launcher3.model.BgDataModel;
|
||||||
|
|||||||
Reference in New Issue
Block a user