Adding fast scroller in app list
Change-Id: I9b5c2225a7acf6d7d83d7d7a7bb08a023a66183d
This commit is contained in:
@@ -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
|
||||||
|
Reference in New Issue
Block a user