diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2015-09-14 21:55:16 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-09-14 21:55:16 +0000 |
commit | 54d17dff6db6847b33bf07e1af6fbaa2e3bbe19d (patch) | |
tree | 82db2e21449fd52665d7cff5f67b72ea655d185f /src/com/android/launcher3/allapps/AllAppsGridAdapter.java | |
parent | edd51ad30741098e2110e3d0533085b02cbe752c (diff) | |
parent | 00e827c70cb4213ee05140157006a37d12662448 (diff) | |
download | android_packages_apps_Trebuchet-54d17dff6db6847b33bf07e1af6fbaa2e3bbe19d.tar.gz android_packages_apps_Trebuchet-54d17dff6db6847b33bf07e1af6fbaa2e3bbe19d.tar.bz2 android_packages_apps_Trebuchet-54d17dff6db6847b33bf07e1af6fbaa2e3bbe19d.zip |
am 00e827c7: am 5fcaab43: am ea9ad5ce: Merge remote-tracking branch \'origin/ub-launcher3-burnaby\' into mnc-dev
* commit '00e827c70cb4213ee05140157006a37d12662448': (76 commits)
Restoring provider behavior for reloading app on old devices > For older devices, launcher will only reload in case of inserts with specific query parameters > For older devices, launcehr will notify content observers of any internal inserts > Chaning TAG for Launcher provider as max logging tag is only 23 characters
Removing items which are on invalid screen
Preventing null pointer crash when opening a folder
Revert workaround for move to default screen on home intent.
Fixing NPE in recycler view scroll bar.
Adding workaround for regression caused by ag/752175
Adding gradle script for Android Studio
Override the overscroll color for the widget rows.
Adding graphic for all apps empty search screen.
Using GET_UNINSTALLED_PACKAGES flag when getting packageInfo for a managed profile app
Revert "Adding viewId for the QSB"
Adding viewId for the QSB
Fixing issue with missing scroll bar after fast-scrolling and searching.
Fixing an issue where you would inadvertently start fastscrolling.
Pending bind callbacks should be cleared before starting the loader, similar to startBinding
Fixing widgets container inactive scroll bar color.
Making the detached scrollbar catch up faster to the actual scroll position.
Updating theme to use the light theme by default, instead of wallpaper theme > This allows us to use all the goodness of material theme > Cursor in folder edit text is no longer 1px wide
Updating the target sdk to launcher
Using the usermanager api to get creation time
...
Diffstat (limited to 'src/com/android/launcher3/allapps/AllAppsGridAdapter.java')
-rw-r--r-- | src/com/android/launcher3/allapps/AllAppsGridAdapter.java | 160 |
1 files changed, 132 insertions, 28 deletions
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index 057883cab..1f95133d4 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -16,21 +16,30 @@ package com.android.launcher3.allapps; import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.Rect; -import android.os.Handler; +import android.graphics.drawable.Drawable; +import android.support.v4.view.accessibility.AccessibilityRecordCompat; +import android.support.v4.view.accessibility.AccessibilityEventCompat; +import android.net.Uri; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import android.widget.TextView; import com.android.launcher3.AppInfo; import com.android.launcher3.BubbleTextView; +import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.util.Thunk; @@ -42,7 +51,7 @@ import java.util.List; /** * The grid view adapter of all the apps. */ -class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> { +public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> { public static final String TAG = "AppsGridAdapter"; private static final boolean DEBUG = false; @@ -55,6 +64,10 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol public static final int PREDICTION_ICON_VIEW_TYPE = 2; // The message shown when there are no filtered results public static final int EMPTY_SEARCH_VIEW_TYPE = 3; + // A divider that separates the apps list and the search market button + public static final int SEARCH_MARKET_DIVIDER_VIEW_TYPE = 4; + // The message to continue to a market search when there are no filtered results + public static final int SEARCH_MARKET_VIEW_TYPE = 5; /** * ViewHolder for each icon. @@ -69,6 +82,38 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol } /** + * A subclass of GridLayoutManager that overrides accessibility values during app search. + */ + public class AppsGridLayoutManager extends GridLayoutManager { + + public AppsGridLayoutManager(Context context) { + super(context, 1, GridLayoutManager.VERTICAL, false); + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + + // Ensure that we only report the number apps for accessibility not including other + // adapter views + final AccessibilityRecordCompat record = AccessibilityEventCompat + .asRecord(event); + record.setItemCount(mApps.getNumFilteredApps()); + } + + @Override + public int getRowCountForAccessibility(RecyclerView.Recycler recycler, + RecyclerView.State state) { + if (mApps.hasNoFilteredResults()) { + // Disregard the no-search-results text as a list item for accessibility + return 0; + } else { + return super.getRowCountForAccessibility(recycler, state); + } + } + } + + /** * Helper class to size the grid items. */ public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup { @@ -80,11 +125,6 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol @Override public int getSpanSize(int position) { - if (mApps.hasNoFilteredResults()) { - // Empty view spans full width - return mAppsPerRow; - } - switch (mApps.getAdapterItems().get(position).viewType) { case AllAppsGridAdapter.ICON_VIEW_TYPE: case AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE: @@ -279,6 +319,7 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol } } + private Launcher mLauncher; private LayoutInflater mLayoutInflater; @Thunk AlphabeticalAppsList mApps; private GridLayoutManager mGridLayoutMgr; @@ -291,7 +332,19 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol @Thunk int mPredictionBarDividerOffset; @Thunk int mAppsPerRow; @Thunk boolean mIsRtl; - private String mEmptySearchText; + + // The text to show when there are no search results and no market search handler. + private String mEmptySearchMessage; + // The name of the market app which handles searches, to be used in the format str + // below when updating the search-market view. Only needs to be loaded once. + private String mMarketAppName; + // The text to show when there is a market app which can handle a specific query, updated + // each time the search query changes. + private String mMarketSearchMessage; + // The intent to send off to the market app, updated each time the search query changes. + private Intent mMarketSearchIntent; + // The last query that the user entered into the search field + private String mLastSearchQuery; // Section drawing @Thunk int mSectionNamesMargin; @@ -299,16 +352,18 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol @Thunk Paint mSectionTextPaint; @Thunk Paint mPredictedAppsDividerPaint; - public AllAppsGridAdapter(Context context, AlphabeticalAppsList apps, + public AllAppsGridAdapter(Launcher launcher, AlphabeticalAppsList apps, View.OnTouchListener touchListener, View.OnClickListener iconClickListener, View.OnLongClickListener iconLongClickListener) { - Resources res = context.getResources(); + Resources res = launcher.getResources(); + mLauncher = launcher; mApps = apps; + mEmptySearchMessage = res.getString(R.string.all_apps_loading_message); mGridSizer = new GridSpanSizer(); - mGridLayoutMgr = new GridLayoutManager(context, 1, GridLayoutManager.VERTICAL, false); + mGridLayoutMgr = new AppsGridLayoutManager(launcher); mGridLayoutMgr.setSpanSizeLookup(mGridSizer); mItemDecoration = new GridItemDecoration(); - mLayoutInflater = LayoutInflater.from(context); + mLayoutInflater = LayoutInflater.from(launcher); mTouchListener = touchListener; mIconClickListener = iconClickListener; mIconLongClickListener = iconLongClickListener; @@ -328,6 +383,14 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol mPredictionBarDividerOffset = (-res.getDimensionPixelSize(R.dimen.all_apps_prediction_icon_bottom_padding) + res.getDimensionPixelSize(R.dimen.all_apps_icon_top_bottom_padding)) / 2; + + // Resolve the market app handling additional searches + PackageManager pm = launcher.getPackageManager(); + ResolveInfo marketInfo = pm.resolveActivity(createMarketSearchIntent(""), + PackageManager.MATCH_DEFAULT_ONLY); + if (marketInfo != null) { + mMarketAppName = marketInfo.loadLabel(pm).toString(); + } } /** @@ -346,10 +409,19 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol } /** - * Sets the text to show when there are no apps. + * 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 setEmptySearchText(String query) { - mEmptySearchText = query; + public void setLastSearchQuery(String query) { + Resources res = mLauncher.getResources(); + String formatStr = res.getString(R.string.all_apps_no_search_results); + mLastSearchQuery = query; + mEmptySearchMessage = String.format(formatStr, query); + if (mMarketAppName != null) { + mMarketSearchMessage = String.format(res.getString(R.string.all_apps_search_market_message), + mMarketAppName); + mMarketSearchIntent = createMarketSearchIntent(query); + } } /** @@ -378,9 +450,6 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { - case EMPTY_SEARCH_VIEW_TYPE: - return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search, parent, - false)); case SECTION_BREAK_VIEW_TYPE: return new ViewHolder(new View(parent.getContext())); case ICON_VIEW_TYPE: { @@ -405,6 +474,22 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol icon.setFocusable(true); return new ViewHolder(icon); } + case EMPTY_SEARCH_VIEW_TYPE: + return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search, + parent, false)); + case SEARCH_MARKET_DIVIDER_VIEW_TYPE: + return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_search_market_divider, + parent, false)); + case SEARCH_MARKET_VIEW_TYPE: + View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market, + parent, false); + searchMarketView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mLauncher.startSearchFromAllApps(v, mMarketSearchIntent, mLastSearchQuery); + } + }); + return new ViewHolder(searchMarketView); default: throw new RuntimeException("Unexpected view type"); } @@ -426,28 +511,47 @@ class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHol break; } case EMPTY_SEARCH_VIEW_TYPE: - TextView emptyViewText = (TextView) holder.mContent.findViewById(R.id.empty_text); - emptyViewText.setText(mEmptySearchText); + TextView emptyViewText = (TextView) holder.mContent; + emptyViewText.setText(mEmptySearchMessage); + emptyViewText.setGravity(mApps.hasNoFilteredResults() ? Gravity.CENTER : + Gravity.START | Gravity.CENTER_VERTICAL); + break; + case SEARCH_MARKET_VIEW_TYPE: + TextView searchView = (TextView) holder.mContent; + if (mMarketSearchIntent != null) { + searchView.setVisibility(View.VISIBLE); + searchView.setContentDescription(mMarketSearchMessage); + searchView.setGravity(mApps.hasNoFilteredResults() ? Gravity.CENTER : + Gravity.START | Gravity.CENTER_VERTICAL); + searchView.setText(mMarketSearchMessage); + } else { + searchView.setVisibility(View.GONE); + } break; } } @Override public int getItemCount() { - if (mApps.hasNoFilteredResults()) { - // For the empty view - return 1; - } return mApps.getAdapterItems().size(); } @Override public int getItemViewType(int position) { - if (mApps.hasNoFilteredResults()) { - return EMPTY_SEARCH_VIEW_TYPE; - } - AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position); return item.viewType; } + + /** + * Creates a new market search intent. + */ + private Intent createMarketSearchIntent(String query) { + Uri marketSearchUri = Uri.parse("market://search") + .buildUpon() + .appendQueryParameter("q", query) + .build(); + Intent marketSearchIntent = new Intent(Intent.ACTION_VIEW); + marketSearchIntent.setData(marketSearchUri); + return marketSearchIntent; + } } |