summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r--src/com/android/launcher3/AppsCustomizePagedView.java150
-rw-r--r--src/com/android/launcher3/FastBitmapDrawable.java2
-rw-r--r--src/com/android/launcher3/LauncherModel.java100
-rw-r--r--src/com/android/launcher3/settings/HiddenAppsActivity.java302
-rw-r--r--src/com/android/launcher3/settings/SettingsActivity.java9
-rw-r--r--src/com/android/launcher3/settings/SettingsProvider.java3
-rw-r--r--src/com/android/launcher3/widget/CheckableLinearLayout.java50
-rw-r--r--src/com/android/launcher3/widget/InertCheckBox.java69
8 files changed, 669 insertions, 16 deletions
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 28bc4e477..0cc540436 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -27,6 +27,7 @@ import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -175,6 +176,11 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
private SortMode mSortMode = SortMode.Title;
+ private int mFilterApps = FILTER_APPS_SYSTEM_FLAG | FILTER_APPS_DOWNLOADED_FLAG;
+
+ private static final int FILTER_APPS_SYSTEM_FLAG = 1;
+ private static final int FILTER_APPS_DOWNLOADED_FLAG = 2;
+
// Refs
private Launcher mLauncher;
private DragController mDragController;
@@ -189,6 +195,11 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private ArrayList<AppInfo> mApps;
private ArrayList<Object> mWidgets;
+ private ArrayList<AppInfo> mFilteredApps;
+ private ArrayList<Object> mFilteredWidgets;
+ private ArrayList<ComponentName> mHiddenApps;
+ private ArrayList<String> mHiddenPackages;
+
// Cling
private boolean mHasShownAllAppsCling;
private int mClingFocusedX;
@@ -279,7 +290,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mLayoutInflater = LayoutInflater.from(context);
mPackageManager = context.getPackageManager();
mApps = new ArrayList<AppInfo>();
+ mFilteredApps = new ArrayList<AppInfo>();
mWidgets = new ArrayList<Object>();
+ mFilteredWidgets = new ArrayList<Object>();
mIconCache = (LauncherAppState.getInstance()).getIconCache();
mCanvas = new Canvas();
mRunningTasks = new ArrayList<AppsCustomizeAsyncTask>();
@@ -309,6 +322,18 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
+
+ String[] flattened = SettingsProvider.getStringCustomDefault(context,
+ SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|");
+ mHiddenApps = new ArrayList<ComponentName>(flattened.length);
+ mHiddenPackages = new ArrayList<String>(flattened.length);
+ for (String flat : flattened) {
+ ComponentName cmp = ComponentName.unflattenFromString(flat);
+ if (cmp != null) {
+ mHiddenApps.add(cmp);
+ mHiddenPackages.add(cmp.getPackageName());
+ }
+ }
}
@Override
@@ -351,7 +376,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
i = (currentPage * numItemsPerPage) + (childCount / 2);
}
} else if (mContentType == ContentType.Widgets) {
- int numApps = mApps.size();
+ int numApps = mFilteredApps.size();
PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(currentPage);
int numItemsPerPage = mWidgetCountX * mWidgetCountY;
int childCount = layout.getChildCount();
@@ -379,12 +404,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int getPageForComponent(int index) {
if (index < 0) return 0;
- if (index < mApps.size()) {
+ if (index < mFilteredApps.size()) {
int numItemsPerPage = mCellCountX * mCellCountY;
return (index / numItemsPerPage);
} else {
int numItemsPerPage = mWidgetCountX * mWidgetCountY;
- return (index - mApps.size()) / numItemsPerPage;
+ return (index - mFilteredApps.size()) / numItemsPerPage;
}
}
@@ -395,9 +420,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
private void updatePageCounts() {
- mNumWidgetPages = (int) Math.ceil(mWidgets.size() /
- (float) (mWidgetCountX * mWidgetCountY));
- mNumAppsPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
+ mNumWidgetPages = (int) Math.ceil((float) mFilteredWidgets.size()
+ / (mWidgetCountX * mWidgetCountY));
+ mNumAppsPages = (int) Math.ceil((float) mFilteredApps.size() / (mCellCountX * mCellCountY));
}
protected void onDataReady(int width, int height) {
@@ -462,7 +487,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (!isDataReady()) {
- if ((DISABLE_ALL_APPS || !mApps.isEmpty()) && !mWidgets.isEmpty()) {
+ if ((DISABLE_ALL_APPS || !mFilteredApps.isEmpty()) && !mFilteredWidgets.isEmpty()) {
setDataIsReady();
setMeasuredDimension(width, height);
onDataReady(width, height);
@@ -507,7 +532,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mWidgets.add(o);
}
}
- updatePageCountsAndInvalidateData();
+ filterWidgets();
}
public void setBulkBind(boolean bulkBind) {
@@ -1083,14 +1108,14 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
final boolean isRtl = isLayoutRtl();
int numCells = mCellCountX * mCellCountY;
int startIndex = page * numCells;
- int endIndex = Math.min(startIndex + numCells, mApps.size());
+ int endIndex = Math.min(startIndex + numCells, mFilteredApps.size());
AppsCustomizeCellLayout layout = (AppsCustomizeCellLayout) getPageAt(page);
layout.removeAllViewsOnPage();
ArrayList<Object> items = new ArrayList<Object>();
ArrayList<Bitmap> images = new ArrayList<Bitmap>();
for (int i = startIndex; i < endIndex; ++i) {
- AppInfo info = mApps.get(i);
+ AppInfo info = mFilteredApps.get(i);
PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
R.layout.apps_customize_application, layout, false);
icon.applyFromApplicationInfo(info, true, this);
@@ -1239,8 +1264,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// Prepare the set of widgets to load previews for in the background
int offset = page * numItemsPerPage;
- for (int i = offset; i < Math.min(offset + numItemsPerPage, mWidgets.size()); ++i) {
- items.add(mWidgets.get(i));
+ for (int i = offset; i < Math.min(offset + numItemsPerPage, mFilteredWidgets.size()); ++i) {
+ items.add(mFilteredWidgets.get(i));
}
// Prepopulate the pages with the other widget info, and fill in the previews later
@@ -1865,7 +1890,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mSortMode = sortMode;
- Collections.sort(mApps, getComparatorForSortMode());
+ Collections.sort(mFilteredApps, getComparatorForSortMode());
if (mContentType == ContentType.Applications) {
for (int i = 0; i < getChildCount(); i++) {
@@ -1903,13 +1928,40 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
}
+ public void setShowSystemApps(boolean show) {
+ if (show) {
+ mFilterApps |= FILTER_APPS_SYSTEM_FLAG;
+ } else {
+ mFilterApps &= ~FILTER_APPS_SYSTEM_FLAG;
+ }
+ filterApps();
+ }
+
+ public void setShowDownloadedApps(boolean show) {
+ if (show) {
+ mFilterApps |= FILTER_APPS_DOWNLOADED_FLAG;
+ } else {
+ mFilterApps &= ~FILTER_APPS_DOWNLOADED_FLAG;
+ }
+ filterApps();
+ }
+
+ public boolean getShowSystemApps() {
+ return (mFilterApps & FILTER_APPS_SYSTEM_FLAG) != 0;
+ }
+
+ public boolean getShowDownloadedApps() {
+ return (mFilterApps & FILTER_APPS_DOWNLOADED_FLAG) != 0;
+ }
+
public void setApps(ArrayList<AppInfo> list) {
if (!DISABLE_ALL_APPS) {
mApps = list;
- Collections.sort(mApps, getComparatorForSortMode());
+ filterAppsWithoutInvalidate();
updatePageCountsAndInvalidateData();
}
}
+
private void addAppsWithoutInvalidate(ArrayList<AppInfo> list) {
// We add it in place, in alphabetical order
int count = list.size();
@@ -1921,12 +1973,15 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
}
}
+
public void addApps(ArrayList<AppInfo> list) {
if (!DISABLE_ALL_APPS) {
addAppsWithoutInvalidate(list);
+ filterAppsWithoutInvalidate();
updatePageCountsAndInvalidateData();
}
}
+
private int findAppByComponent(List<AppInfo> list, AppInfo item) {
ComponentName removeComponent = item.intent.getComponent();
int length = list.size();
@@ -1938,6 +1993,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
return -1;
}
+
private void removeAppsWithoutInvalidate(ArrayList<AppInfo> list) {
// loop through all the apps and remove apps that have the same component
int length = list.size();
@@ -1949,12 +2005,15 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
}
}
+
public void removeApps(ArrayList<AppInfo> appInfos) {
if (!DISABLE_ALL_APPS) {
removeAppsWithoutInvalidate(appInfos);
+ filterAppsWithoutInvalidate();
updatePageCountsAndInvalidateData();
}
}
+
public void updateApps(ArrayList<AppInfo> list) {
// We remove and re-add the updated applications list because it's properties may have
// changed (ie. the title), and this will ensure that the items will be in their proper
@@ -1962,10 +2021,73 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
if (!DISABLE_ALL_APPS) {
removeAppsWithoutInvalidate(list);
addAppsWithoutInvalidate(list);
+ filterAppsWithoutInvalidate();
updatePageCountsAndInvalidateData();
}
}
+ public void filterAppsWithoutInvalidate() {
+ mFilteredApps = new ArrayList<AppInfo>(mApps);
+ Iterator<AppInfo> iterator = mFilteredApps.iterator();
+ while (iterator.hasNext()) {
+ AppInfo appInfo = iterator.next();
+ boolean system = (appInfo.flags & AppInfo.DOWNLOADED_FLAG) == 0;
+ if (mHiddenApps.contains(appInfo.componentName) ||
+ (system && !getShowSystemApps()) ||
+ (!system && !getShowDownloadedApps())) {
+ iterator.remove();
+ }
+ }
+ Collections.sort(mFilteredApps, getComparatorForSortMode());
+ }
+
+ public void filterApps() {
+ filterAppsWithoutInvalidate();
+ updatePageCountsAndInvalidateData();
+ }
+
+ public void filterWidgetsWithoutInvalidate() {
+ mFilteredWidgets = new ArrayList<Object>(mWidgets);
+
+ Iterator<Object> iterator = mFilteredWidgets.iterator();
+ while (iterator.hasNext()) {
+ Object o = iterator.next();
+
+ String packageName;
+ if (o instanceof AppWidgetProviderInfo) {
+ AppWidgetProviderInfo widgetInfo = (AppWidgetProviderInfo) o;
+ if (widgetInfo.provider == null) {
+ continue;
+ }
+ packageName = widgetInfo.provider.getPackageName();
+ } else if (o instanceof ResolveInfo) {
+ ResolveInfo shortcut = (ResolveInfo) o;
+ packageName = shortcut.activityInfo.applicationInfo.packageName;
+ } else {
+ Log.w(TAG, "Unknown class in widgets list: " + o.getClass());
+ continue;
+ }
+
+ int flags;
+ try {
+ flags = AppInfo.initFlags(mPackageManager.getPackageInfo(packageName, 0));
+ } catch (NameNotFoundException e) {
+ flags = 0;
+ }
+ boolean system = (flags & AppInfo.DOWNLOADED_FLAG) == 0;
+ if (mHiddenPackages.contains(packageName) ||
+ (system && !getShowSystemApps()) ||
+ (!system && !getShowDownloadedApps())) {
+ iterator.remove();
+ }
+ }
+ }
+
+ public void filterWidgets() {
+ filterWidgetsWithoutInvalidate();
+ updatePageCountsAndInvalidateData();
+ }
+
public void reset() {
// If we have reset, then we should not continue to restore the previous state
mSaveInstanceStateItemIndex = -1;
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 14760c7b6..8061c619d 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -32,7 +32,7 @@ class FastBitmapDrawable extends Drawable {
private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
FastBitmapDrawable(Bitmap b) {
- mAlpha = 255;
+ mAlpha = 255;
mBitmap = b;
if (b != null) {
mWidth = mBitmap.getWidth();
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index bc97e0af2..e06fe5fb3 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -19,8 +19,16 @@ package com.android.launcher3;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
-import android.content.*;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentProviderClient;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
+import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -42,7 +50,9 @@ import android.os.SystemClock;
import android.provider.BaseColumns;
import android.util.Log;
import android.util.Pair;
+
import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
+import com.android.launcher3.settings.SettingsProvider;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
@@ -2201,6 +2211,92 @@ public class LauncherModel extends BroadcastReceiver {
runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
}
+ private void removeHiddenAppsWorkspaceItems(
+ final ArrayList<ItemInfo> workspaceItems,
+ final ArrayList<LauncherAppWidgetInfo> appWidgets,
+ final HashMap<Long, FolderInfo> folders) {
+
+ // Get hidden apps
+ ArrayList<ComponentName> mHiddenApps = new ArrayList<ComponentName>();
+ ArrayList<String> mHiddenAppsPackages = new ArrayList<String>();
+ Context context = mApp.getContext();
+ String[] flattened = SettingsProvider.getStringCustomDefault(context,
+ SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|");
+ boolean hideShortcuts = SettingsProvider.getBoolean(context,
+ SettingsProvider.SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_SHORTCUTS,
+ R.bool.preferences_interface_drawer_remove_hidden_apps_shortcuts_default);
+ boolean hideWidgets = SettingsProvider.getBoolean(context,
+ SettingsProvider.SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_WIDGETS,
+ R.bool.preferences_interface_drawer_remove_hidden_apps_widgets_default);
+
+ for (String flat : flattened) {
+ ComponentName cmp = ComponentName.unflattenFromString(flat);
+ if (cmp != null) {
+ mHiddenApps.add(cmp);
+ mHiddenAppsPackages.add(cmp.getPackageName());
+ }
+ }
+
+ // Shortcuts
+ if (hideShortcuts) {
+ int N = workspaceItems.size() - 1;
+ for (int i = N; i >= 0; i--) {
+ final ItemInfo item = workspaceItems.get(i);
+ if (item instanceof ShortcutInfo) {
+ ShortcutInfo shortcut = (ShortcutInfo)item;
+ if (shortcut.intent != null && shortcut.intent.getComponent() != null) {
+ if (mHiddenApps.contains(shortcut.intent.getComponent())) {
+ LauncherModel.deleteItemFromDatabase(mContext, shortcut);
+ workspaceItems.remove(i);
+ }
+ }
+ } else {
+ final FolderInfo folder = (FolderInfo)item;
+ List<ShortcutInfo> shortcuts = folder.contents;
+ int NN = shortcuts.size() - 1;
+ for (int j = NN; j >= 0; j--) {
+ ShortcutInfo sci = shortcuts.get(j);
+ if (sci.intent != null && sci.intent.getComponent() != null) {
+ if (mHiddenApps.contains(sci.intent.getComponent())) {
+ LauncherModel.deleteItemFromDatabase(mContext, sci);
+ folder.remove(sci);
+ }
+ }
+ }
+
+ if (folder.contents.size() == 1 /*&& !(folder instanceof LiveFolderInfo)*/) {
+ ShortcutInfo finalItem = folder.contents.get(0);
+ finalItem.container = folder.container;
+ LauncherModel.deleteItemFromDatabase(mContext, folder);
+ LauncherModel.addOrMoveItemInDatabase(mContext, finalItem, folder.container,
+ folder.screenId, folder.cellX, folder.cellY);
+ workspaceItems.remove(i);
+ workspaceItems.add(finalItem);
+ folders.remove(Long.valueOf(item.id));
+ } else if (folder.contents.size() == 0 /*&& !(folder instanceof LiveFolderInfo)*/) {
+ LauncherModel.deleteFolderContentsFromDatabase(mContext, folder);
+ workspaceItems.remove(i);
+ folders.remove(Long.valueOf(item.id));
+ }
+ }
+ }
+ }
+
+ // AppWidgets
+ if (hideWidgets) {
+ int N = appWidgets.size() - 1;
+ for (int i = N; i >= 0; i--) {
+ final LauncherAppWidgetInfo item = appWidgets.get(i);
+ if (item.providerName != null) {
+ if (mHiddenAppsPackages.contains(item.providerName.getPackageName())) {
+ LauncherModel.deleteItemFromDatabase(mContext, item);
+ appWidgets.remove(i);
+ }
+ }
+ }
+ }
+ }
+
private void bindWorkspaceItems(final Callbacks oldCallbacks,
final ArrayList<ItemInfo> workspaceItems,
final ArrayList<LauncherAppWidgetInfo> appWidgets,
@@ -2209,6 +2305,8 @@ public class LauncherModel extends BroadcastReceiver {
final boolean postOnMainThread = (deferredBindRunnables != null);
+ removeHiddenAppsWorkspaceItems(workspaceItems, appWidgets, folders);
+
// Bind the workspace items
int N = workspaceItems.size();
for (int i = 0; i < N; i += ITEMS_CHUNK) {
diff --git a/src/com/android/launcher3/settings/HiddenAppsActivity.java b/src/com/android/launcher3/settings/HiddenAppsActivity.java
new file mode 100644
index 000000000..57ea7bc36
--- /dev/null
+++ b/src/com/android/launcher3/settings/HiddenAppsActivity.java
@@ -0,0 +1,302 @@
+package com.android.launcher3.settings;
+
+import android.app.ListActivity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.SparseBooleanArray;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.launcher3.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class HiddenAppsActivity extends ListActivity {
+
+ private boolean mSaved;
+
+ private static final int MENU_RESET = 0;
+
+ private PackageManager mPackageManager;
+
+ private AppsAdapter mAppsAdapter;
+
+ protected void onCreate(Bundle savedInstanceState) {
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ super.onCreate(savedInstanceState);
+
+ setTitle(R.string.hidden_apps_title);
+ setContentView(R.layout.hidden_apps_list);
+
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ setProgressBarIndeterminateVisibility(true);
+ setProgressBarIndeterminate(true);
+
+ mPackageManager = getPackageManager();
+ mAppsAdapter = new AppsAdapter(this, R.layout.hidden_apps_list_item);
+ mAppsAdapter.setNotifyOnChange(true);
+
+ setListAdapter(mAppsAdapter);
+
+ AsyncTask<Void, Void, List<AppEntry>> refreshAppsTask = new AsyncTask<Void, Void, List<AppEntry>>() {
+
+ @Override
+ protected void onPostExecute(List<AppEntry> apps) {
+ mAppsAdapter.clear();
+ mAppsAdapter.addAll(apps);
+ restoreCheckedItems();
+ setProgressBarIndeterminateVisibility(false);
+ setProgressBarIndeterminate(false);
+ }
+
+ @Override
+ protected List<AppEntry> doInBackground(Void... params) {
+ return refreshApps();
+ }
+ };
+ refreshAppsTask.execute(null, null, null);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ save();
+ }
+
+ private void save() {
+ if (mSaved) {
+ return;
+ }
+ String string = "";
+
+ SparseBooleanArray checked = getListView().getCheckedItemPositions();
+
+ AppsAdapter listAdapter = (AppsAdapter) getListAdapter();
+ for (int i = 0; i < checked.size(); i++) {
+ if (checked.valueAt(i)) {
+ AppEntry app = listAdapter.getItem(checked.keyAt(i));
+ if (!string.isEmpty())
+ string += "|";
+ string += app.componentName.flattenToString();
+ }
+ }
+
+ SharedPreferences.Editor editor = SettingsProvider.get(this).edit();
+ editor.putString(SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, string);
+ editor.putBoolean(SettingsProvider.SETTINGS_CHANGED, true);
+ editor.apply();
+
+ mSaved = true;
+ }
+
+ private void restoreCheckedItems() {
+ List<ComponentName> apps = new ArrayList<ComponentName>();
+ String[] flattened = SettingsProvider.getStringCustomDefault(this,
+ SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|");
+ for (String flat : flattened) {
+ apps.add(ComponentName.unflattenFromString(flat));
+ }
+
+ AppsAdapter listAdapter = (AppsAdapter) getListAdapter();
+
+ for (int i = 0; i < listAdapter.getCount(); i++) {
+ AppEntry info = listAdapter.getItem(i);
+ if (apps.contains(info.componentName)) {
+ getListView().setItemChecked(i, true);
+ }
+ }
+
+ mSaved = true;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add(0, MENU_RESET, 0, R.string.menu_hidden_apps_delete)
+ .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+
+ return true;
+ }
+
+ private void reset() {
+ for (int i = 0; i < getListView().getCount(); i++) {
+ getListView().setItemChecked(i, false);
+ }
+
+ mSaved = false;
+ }
+
+ private List<AppEntry> refreshApps() {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ List<ResolveInfo> apps = mPackageManager.queryIntentActivities(mainIntent, 0);
+ Collections.sort(apps, new ResolveInfo.DisplayNameComparator(mPackageManager));
+ List<AppEntry> appEntries = new ArrayList<AppEntry>(apps.size());
+ for (ResolveInfo info : apps) {
+ appEntries.add(new AppEntry(info));
+ }
+ return appEntries;
+ }
+
+ @Override
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ } else if (item.getItemId() == MENU_RESET) {
+ reset();
+ return true;
+ }
+ return super.onMenuItemSelected(featureId, item);
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ mSaved = false;
+ }
+
+ private final class AppEntry {
+
+ public final ComponentName componentName;
+ public final String title;
+
+ public AppEntry(ResolveInfo info) {
+ componentName = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+ title = info.loadLabel(mPackageManager).toString();
+ }
+ }
+
+ /**
+ * App view holder used to reuse the views inside the list.
+ */
+ private static class AppViewHolder {
+ public final TextView title;
+ public final ImageView icon;
+
+ public AppViewHolder(View parentView) {
+ icon = (ImageView) parentView.findViewById(R.id.icon);
+ title = (TextView) parentView.findViewById(R.id.title);
+ }
+ }
+
+ public class AppsAdapter extends ArrayAdapter<AppEntry> {
+
+ private final LayoutInflater mInflator;
+
+ private ConcurrentHashMap<String, Drawable> mIcons;
+ private Drawable mDefaultImg;
+ private List<AppEntry> mApps;
+
+ public AppsAdapter(Context context, int textViewResourceId) {
+ super(context, textViewResourceId);
+
+ mApps = new ArrayList<AppEntry>();
+
+ mInflator = LayoutInflater.from(context);
+
+ // set the default icon till the actual app icon is loaded in async
+ // task
+ mDefaultImg = context.getResources().getDrawable(android.R.mipmap.sym_def_app_icon);
+ mIcons = new ConcurrentHashMap<String, Drawable>();
+ }
+
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ AppViewHolder viewHolder;
+
+ if (convertView == null) {
+ convertView = mInflator.inflate(R.layout.hidden_apps_list_item, parent, false);
+ viewHolder = new AppViewHolder(convertView);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (AppViewHolder) convertView.getTag();
+ }
+
+ AppEntry app = getItem(position);
+
+ viewHolder.title.setText(app.title);
+
+ Drawable icon = mIcons.get(app.componentName.getPackageName());
+ viewHolder.icon.setImageDrawable(icon != null ? icon : mDefaultImg);
+
+ return convertView;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ super.notifyDataSetChanged();
+ // If we have new items, we have to load their icons
+ // If items were deleted, remove them from our mApps
+ List<AppEntry> newApps = new ArrayList<AppEntry>(getCount());
+ List<AppEntry> oldApps = new ArrayList<AppEntry>(getCount());
+ for (int i = 0; i < getCount(); i++) {
+ AppEntry app = getItem(i);
+ if (mApps.contains(app)) {
+ oldApps.add(app);
+ } else {
+ newApps.add(app);
+ }
+ }
+
+ if (newApps.size() > 0) {
+ new LoadIconsTask().execute(newApps.toArray(new AppEntry[] {}));
+ newApps.addAll(oldApps);
+ mApps = newApps;
+ } else {
+ mApps = oldApps;
+ }
+ }
+
+ /**
+ * An asynchronous task to load the icons of the installed applications.
+ */
+ private class LoadIconsTask extends AsyncTask<AppEntry, Void, Void> {
+ @Override
+ protected Void doInBackground(AppEntry... apps) {
+ for (AppEntry app : apps) {
+ try {
+ if (mIcons.containsKey(app.componentName.getPackageName())) {
+ continue;
+ }
+ Drawable icon = mPackageManager.getApplicationIcon(app.componentName
+ .getPackageName());
+ mIcons.put(app.componentName.getPackageName(), icon);
+ publishProgress();
+ } catch (PackageManager.NameNotFoundException e) {
+ // ignored; app will show up with default image
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onProgressUpdate(Void... progress) {
+ notifyDataSetChanged();
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 182a6bff8..dbbf95f52 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -153,6 +153,15 @@ public class SettingsActivity extends PreferenceActivity
}
}
+ public static class DrawerFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.preferences_drawer);
+ }
+ }
+
private static class HeaderAdapter extends ArrayAdapter<Header> {
private static final int HEADER_TYPE_NORMAL = 0;
private static final int HEADER_TYPE_CATEGORY = 1;
diff --git a/src/com/android/launcher3/settings/SettingsProvider.java b/src/com/android/launcher3/settings/SettingsProvider.java
index 8ef3c9c7f..3a211952a 100644
--- a/src/com/android/launcher3/settings/SettingsProvider.java
+++ b/src/com/android/launcher3/settings/SettingsProvider.java
@@ -32,6 +32,9 @@ public final class SettingsProvider {
public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_FADE_ADJACENT = "ui_homescreen_scrolling_fade_adjacent";
public static final String SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT = "ui_drawer_scrolling_transition_effect";
public static final String SETTINGS_UI_DRAWER_SCROLLING_FADE_ADJACENT = "ui_drawer_scrolling_fade_adjacent";
+ public static final String SETTINGS_UI_DRAWER_HIDDEN_APPS = "ui_drawer_hidden_apps";
+ public static final String SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_SHORTCUTS = "ui_drawer_remove_hidden_apps_shortcuts";
+ public static final String SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_WIDGETS = "ui_drawer_remove_hidden_apps_widgets";
public static final String SETTINGS_UI_GENERAL_ICONS_LARGE = "ui_general_icons_large";
public static final String SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_FAMILY = "ui_general_icons_text_font";
public static final String SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_STYLE = "ui_general_icons_text_font_style";
diff --git a/src/com/android/launcher3/widget/CheckableLinearLayout.java b/src/com/android/launcher3/widget/CheckableLinearLayout.java
new file mode 100644
index 000000000..f834c10b8
--- /dev/null
+++ b/src/com/android/launcher3/widget/CheckableLinearLayout.java
@@ -0,0 +1,50 @@
+package com.android.launcher3.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.CheckBox;
+import android.widget.Checkable;
+import android.widget.LinearLayout;
+
+import com.android.launcher3.R;
+
+/*
+ * This class is useful for using inside of ListView that needs to have checkable items.
+ */
+public class CheckableLinearLayout extends LinearLayout implements Checkable {
+ private CheckBox mCheckBox;
+
+ public CheckableLinearLayout(Context context) {
+ super(context);
+ }
+
+ public CheckableLinearLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mCheckBox = (CheckBox) findViewById(R.id.checkbox);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mCheckBox.isChecked();
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ mCheckBox.setChecked(checked);
+ }
+
+ @Override
+ public void toggle() {
+ mCheckBox.toggle();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/widget/InertCheckBox.java b/src/com/android/launcher3/widget/InertCheckBox.java
new file mode 100644
index 000000000..e990a8b85
--- /dev/null
+++ b/src/com/android/launcher3/widget/InertCheckBox.java
@@ -0,0 +1,69 @@
+package com.android.launcher3.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.widget.CheckBox;
+
+
+// CheckBox that does not react to any user event in order to let the container handle them.
+public class InertCheckBox extends CheckBox {
+
+ @SuppressWarnings("unused")
+ public InertCheckBox(Context context) {
+ super(context);
+ }
+
+ @SuppressWarnings("unused")
+ public InertCheckBox(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @SuppressWarnings("unused")
+ public InertCheckBox(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyShortcut(int keyCode, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+} \ No newline at end of file