diff options
author | Winson Chung <winsonc@google.com> | 2015-03-10 16:28:47 -0700 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2015-03-12 18:57:02 -0700 |
commit | 93f98eaf1800024cb2f28379bdd997f3debae63a (patch) | |
tree | 5b9efef68c1b651ec13b69ede29bb20bd67cb64f /src/com/android/launcher3/AlphabeticalAppsList.java | |
parent | 74081b02730bb7205f5cfe43f206039df38a20db (diff) | |
download | android_packages_apps_Trebuchet-93f98eaf1800024cb2f28379bdd997f3debae63a.tar.gz android_packages_apps_Trebuchet-93f98eaf1800024cb2f28379bdd997f3debae63a.tar.bz2 android_packages_apps_Trebuchet-93f98eaf1800024cb2f28379bdd997f3debae63a.zip |
Adding app grid layout with fastscroller.
- Adding filtering and using alphabetic index for app grouping.
Change-Id: I745b644fa8f90f5ff24a8642ac377ef1c65d8aff
Diffstat (limited to 'src/com/android/launcher3/AlphabeticalAppsList.java')
-rw-r--r-- | src/com/android/launcher3/AlphabeticalAppsList.java | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/src/com/android/launcher3/AlphabeticalAppsList.java b/src/com/android/launcher3/AlphabeticalAppsList.java new file mode 100644 index 000000000..2847afc89 --- /dev/null +++ b/src/com/android/launcher3/AlphabeticalAppsList.java @@ -0,0 +1,242 @@ +package com.android.launcher3; + +import android.content.ComponentName; +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import com.android.launcher3.compat.AlphabeticIndexCompat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + + +/** + * The alphabetically sorted list of applications. + */ +public class AlphabeticalAppsList { + + /** + * Info about a section in the alphabetic list + */ + public class SectionInfo { + public String sectionName; + public int numAppsInSection; + } + + /** + * A filter interface to limit the set of applications in the apps list. + */ + public interface Filter { + public boolean retainApp(AppInfo info); + } + + // Hack to force RecyclerView to break sections + public static final AppInfo SECTION_BREAK_INFO = null; + + private List<AppInfo> mApps = new ArrayList<>(); + private List<AppInfo> mFilteredApps = new ArrayList<>(); + private List<AppInfo> mSectionedFilteredApps = new ArrayList<>(); + private List<SectionInfo> mSections = new ArrayList<>(); + private RecyclerView.Adapter mAdapter; + private Filter mFilter; + private AlphabeticIndexCompat mIndexer; + + public AlphabeticalAppsList(Context context) { + mIndexer = new AlphabeticIndexCompat(context); + } + + /** + * Sets the adapter to notify when this dataset changes. + */ + public void setAdapter(RecyclerView.Adapter adapter) { + mAdapter = adapter; + } + + /** + * Returns sections of all the current filtered applications. + */ + public List<SectionInfo> getSections() { + return mSections; + } + + /** + * Returns the current filtered list of applications broken down into their sections. + */ + public List<AppInfo> getApps() { + return mSectionedFilteredApps; + } + + /** + * Returns the current filtered list of applications. + */ + public List<AppInfo> getAppsWithoutSectionBreaks() { + return mFilteredApps; + } + + /** + * Returns the section name for the application. + */ + public String getSectionNameForApp(AppInfo info) { + String title = info.title.toString(); + String sectionName = mIndexer.getBucketLabel(mIndexer.getBucketIndex(title)); + return sectionName; + } + + /** + * Returns the indexer for this locale. + */ + public AlphabeticIndexCompat getIndexer() { + return mIndexer; + } + + /** + * Sets the current filter for this list of apps. + */ + public void setFilter(Filter f) { + mFilter = f; + onAppsUpdated(); + mAdapter.notifyDataSetChanged(); + } + + /** + * Sets the current set of apps. + */ + public void setApps(List<AppInfo> apps) { + Collections.sort(apps, LauncherModel.getAppNameComparator()); + mApps.clear(); + mApps.addAll(apps); + onAppsUpdated(); + mAdapter.notifyDataSetChanged(); + } + + /** + * Adds new apps to the list. + */ + public void addApps(List<AppInfo> apps) { + // We add it in place, in alphabetical order + for (AppInfo info : apps) { + addApp(info); + } + } + + /** + * Updates existing apps in the list + */ + public void updateApps(List<AppInfo> apps) { + for (AppInfo info : apps) { + int index = mApps.indexOf(info); + if (index != -1) { + mApps.set(index, info); + onAppsUpdated(); + mAdapter.notifyItemChanged(index); + } else { + addApp(info); + } + } + } + + /** + * Removes some apps from the list. + */ + public void removeApps(List<AppInfo> apps) { + for (AppInfo info : apps) { + int removeIndex = findAppByComponent(mApps, info); + if (removeIndex != -1) { + int sectionedIndex = mSectionedFilteredApps.indexOf(info); + int numAppsInSection = numAppsInSection(info); + mApps.remove(removeIndex); + onAppsUpdated(); + if (numAppsInSection == 1) { + // Remove the section and the icon + mAdapter.notifyItemRemoved(sectionedIndex - 1); + mAdapter.notifyItemRemoved(sectionedIndex - 1); + } else { + mAdapter.notifyItemRemoved(sectionedIndex); + } + } + } + } + + /** + * Finds the index of an app given a target AppInfo. + */ + private int findAppByComponent(List<AppInfo> apps, AppInfo targetInfo) { + ComponentName targetComponent = targetInfo.intent.getComponent(); + int length = apps.size(); + for (int i = 0; i < length; ++i) { + AppInfo info = apps.get(i); + if (info.user.equals(info.user) + && info.intent.getComponent().equals(targetComponent)) { + return i; + } + } + return -1; + } + + /** + * Implementation to actually add an app to the alphabetic list + */ + private void addApp(AppInfo info) { + Comparator<AppInfo> appNameComparator = LauncherModel.getAppNameComparator(); + int index = Collections.binarySearch(mApps, info, appNameComparator); + if (index < 0) { + mApps.add(-(index + 1), info); + onAppsUpdated(); + + int sectionedIndex = mSectionedFilteredApps.indexOf(info); + int numAppsInSection = numAppsInSection(info); + if (numAppsInSection == 1) { + // New section added along with icon + mAdapter.notifyItemInserted(sectionedIndex - 1); + mAdapter.notifyItemInserted(sectionedIndex - 1); + } else { + mAdapter.notifyItemInserted(sectionedIndex); + } + } + } + + /** + * Returns the number of apps in the section that the given info is in. + */ + private int numAppsInSection(AppInfo info) { + int appIndex = mFilteredApps.indexOf(info); + int appCount = 0; + for (SectionInfo section : mSections) { + if (appCount + section.numAppsInSection > appIndex) { + return section.numAppsInSection; + } + appCount += section.numAppsInSection; + } + return 1; + } + + /** + * Updates internals when the set of apps are updated. + */ + private void onAppsUpdated() { + // Recreate the filtered apps + mFilteredApps.clear(); + for (AppInfo info : mApps) { + if (mFilter == null || mFilter.retainApp(info)) { + mFilteredApps.add(info); + } + } + + // Section the apps (for convenience for the grid layout) + mSections.clear(); + mSectionedFilteredApps.clear(); + SectionInfo lastSectionInfo = null; + for (AppInfo info : mFilteredApps) { + String sectionName = getSectionNameForApp(info); + if (lastSectionInfo == null || !lastSectionInfo.sectionName.equals(sectionName)) { + lastSectionInfo = new SectionInfo(); + lastSectionInfo.sectionName = sectionName; + mSectionedFilteredApps.add(SECTION_BREAK_INFO); + mSections.add(lastSectionInfo); + } + lastSectionInfo.numAppsInSection++; + mSectionedFilteredApps.add(info); + } + } +} |