summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2015-09-14 21:55:16 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-09-14 21:55:16 +0000
commit54d17dff6db6847b33bf07e1af6fbaa2e3bbe19d (patch)
tree82db2e21449fd52665d7cff5f67b72ea655d185f /src/com/android/launcher3/allapps/AllAppsGridAdapter.java
parentedd51ad30741098e2110e3d0533085b02cbe752c (diff)
parent00e827c70cb4213ee05140157006a37d12662448 (diff)
downloadandroid_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.java160
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;
+ }
}