Merge "Adding fast scroller in app list"

This commit is contained in:
Sunny Goyal
2016-02-03 21:35:20 +00:00
committed by Android (Google) Code Review

View File

@@ -22,12 +22,15 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.icu.text.AlphabeticIndex;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.preference.PreferenceFrameLayout; import android.preference.PreferenceFrameLayout;
import android.text.TextUtils;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.LocaleList;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
@@ -45,6 +48,7 @@ import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ListView; import android.widget.ListView;
import android.widget.SectionIndexer;
import android.widget.Spinner; import android.widget.Spinner;
import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.AppHeader; import com.android.settings.AppHeader;
@@ -79,6 +83,7 @@ import com.android.settingslib.applications.ApplicationsState.VolumeFilter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Locale;
/** /**
* Activity to pick an application that will be used to display installation information and * Activity to pick an application that will be used to display installation information and
@@ -300,6 +305,7 @@ public class ManageApplications extends InstrumentedFragment
} }
mListView.setAdapter(mApplications); mListView.setAdapter(mApplications);
mListView.setRecyclerListener(mApplications); mListView.setRecyclerListener(mApplications);
mListView.setFastScrollEnabled(isFastScrollEnabled());
Utils.prepareCustomPreferencesList(container, mRootView, mListView, false); Utils.prepareCustomPreferencesList(container, mRootView, mListView, false);
} }
@@ -372,6 +378,17 @@ public class ManageApplications extends InstrumentedFragment
} }
} }
private boolean isFastScrollEnabled() {
switch (mListType) {
case LIST_TYPE_MAIN:
case LIST_TYPE_NOTIFICATION:
case LIST_TYPE_STORAGE:
return mSortOrder == R.id.sort_order_alpha;
default:
return false;
}
}
@Override @Override
protected int getMetricsCategory() { protected int getMetricsCategory() {
switch (mListType) { switch (mListType) {
@@ -545,6 +562,7 @@ public class ManageApplications extends InstrumentedFragment
case R.id.sort_order_alpha: case R.id.sort_order_alpha:
case R.id.sort_order_size: case R.id.sort_order_size:
mSortOrder = menuId; mSortOrder = menuId;
mListView.setFastScrollEnabled(isFastScrollEnabled());
if (mApplications != null) { if (mApplications != null) {
mApplications.rebuild(mSortOrder); mApplications.rebuild(mSortOrder);
} }
@@ -699,7 +717,9 @@ public class ManageApplications extends InstrumentedFragment
*/ */
static class ApplicationsAdapter extends BaseAdapter implements Filterable, static class ApplicationsAdapter extends BaseAdapter implements Filterable,
ApplicationsState.Callbacks, AppStateBaseBridge.Callback, ApplicationsState.Callbacks, AppStateBaseBridge.Callback,
AbsListView.RecyclerListener { AbsListView.RecyclerListener, SectionIndexer {
private static final SectionInfo[] EMPTY_SECTIONS = new SectionInfo[0];
private final ApplicationsState mState; private final ApplicationsState mState;
private final ApplicationsState.Session mSession; private final ApplicationsState.Session mSession;
private final ManageApplications mManageApplications; private final ManageApplications mManageApplications;
@@ -718,6 +738,10 @@ public class ManageApplications extends InstrumentedFragment
private boolean mHasReceivedLoadEntries; private boolean mHasReceivedLoadEntries;
private boolean mHasReceivedBridgeCallback; private boolean mHasReceivedBridgeCallback;
private AlphabeticIndex.ImmutableIndex mIndex;
private SectionInfo[] mSections = EMPTY_SECTIONS;
private int[] mPositionToSectionIndex;
private Filter mFilter = new Filter() { private Filter mFilter = new Filter() {
@Override @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {
@@ -867,9 +891,49 @@ public class ManageApplications extends InstrumentedFragment
mBaseEntries = entries; mBaseEntries = entries;
if (mBaseEntries != null) { if (mBaseEntries != null) {
mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries); mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries);
if (mManageApplications.mListView.isFastScrollEnabled()) {
// Rebuild sections
if (mIndex == null) {
LocaleList locales = mContext.getResources().getConfiguration().getLocales();
if (locales.size() == 0) {
locales = new LocaleList(Locale.ENGLISH);
}
AlphabeticIndex index = new AlphabeticIndex<>(locales.getPrimary());
int localeCount = locales.size();
for (int i = 1; i < localeCount; i++) {
index.addLabels(locales.get(i));
}
// Ensure we always have some base English locale buckets
index.addLabels(Locale.ENGLISH);
mIndex = index.buildImmutableIndex();
}
ArrayList<SectionInfo> sections = new ArrayList<>();
int lastSecId = -1;
int totalEntries = mEntries.size();
mPositionToSectionIndex = new int[totalEntries];
for (int pos = 0; pos < totalEntries; pos++) {
String label = mEntries.get(pos).label;
int secId = mIndex.getBucketIndex(TextUtils.isEmpty(label) ? "" : label);
if (secId != lastSecId) {
lastSecId = secId;
sections.add(new SectionInfo(mIndex.getBucket(secId).getLabel(), pos));
}
mPositionToSectionIndex[pos] = sections.size() - 1;
}
mSections = sections.toArray(EMPTY_SECTIONS);
} else {
mSections = EMPTY_SECTIONS;
mPositionToSectionIndex = null;
}
} else { } else {
mEntries = null; mEntries = null;
mSections = EMPTY_SECTIONS;
mPositionToSectionIndex = null;
} }
notifyDataSetChanged(); notifyDataSetChanged();
if (mSession.getAllApps().size() != 0 if (mSession.getAllApps().size() != 0
@@ -1112,6 +1176,21 @@ public class ManageApplications extends InstrumentedFragment
return mContext.getString(R.string.domain_urls_summary_some, result.valueAt(0)); return mContext.getString(R.string.domain_urls_summary_some, result.valueAt(0));
} }
} }
@Override
public Object[] getSections() {
return mSections;
}
@Override
public int getPositionForSection(int sectionIndex) {
return mSections[sectionIndex].position;
}
@Override
public int getSectionForPosition(int position) {
return mPositionToSectionIndex[position];
}
} }
private static class SummaryProvider implements SummaryLoader.SummaryProvider, private static class SummaryProvider implements SummaryLoader.SummaryProvider,
@@ -1185,6 +1264,21 @@ public class ManageApplications extends InstrumentedFragment
} }
} }
private static class SectionInfo {
final String label;
final int position;
public SectionInfo(String label, int position) {
this.label = label;
this.position = position;
}
@Override
public String toString() {
return label;
}
}
public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
= new SummaryLoader.SummaryProviderFactory() { = new SummaryLoader.SummaryProviderFactory() {
@Override @Override