summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWinson Chung <winsonc@google.com>2015-03-13 11:14:16 -0700
committerWinson Chung <winsonc@google.com>2015-03-13 11:48:45 -0700
commit888b3a10bf1e99192f12c844ee275c6f360d6b34 (patch)
tree0dd028c7b444b7deb9a9c34a91f1efe3a81d1466
parent93f98eaf1800024cb2f28379bdd997f3debae63a (diff)
downloadandroid_packages_apps_Trebuchet-888b3a10bf1e99192f12c844ee275c6f360d6b34.tar.gz
android_packages_apps_Trebuchet-888b3a10bf1e99192f12c844ee275c6f360d6b34.tar.bz2
android_packages_apps_Trebuchet-888b3a10bf1e99192f12c844ee275c6f360d6b34.zip
Minor changes to apps view.
- Ensuring that apps with numbers and in other locals have a section header. - Adding an empty state when there are no apps with the current filter - Removing unnecessary call to check AppInfos Change-Id: I9dc541c680475b98745fa257ad7e4af06e3966c9
-rw-r--r--res/layout-sw600dp/apps_view.xml2
-rw-r--r--res/layout/apps_empty_view.xml28
-rw-r--r--res/layout/apps_reveal_view.xml (renamed from res/layout/apps_list_reveal_view.xml)0
-rw-r--r--res/layout/apps_view.xml2
-rw-r--r--res/values/strings.xml4
-rw-r--r--src/com/android/launcher3/AlphabeticalAppsList.java11
-rw-r--r--src/com/android/launcher3/AppsContainerView.java24
-rw-r--r--src/com/android/launcher3/AppsGridAdapter.java53
-rw-r--r--src/com/android/launcher3/AppsListAdapter.java66
-rw-r--r--src/com/android/launcher3/BubbleTextView.java3
-rw-r--r--src/com/android/launcher3/compat/AlphabeticIndexCompat.java26
11 files changed, 173 insertions, 46 deletions
diff --git a/res/layout-sw600dp/apps_view.xml b/res/layout-sw600dp/apps_view.xml
index 3bb6ec505..0628ca6d3 100644
--- a/res/layout-sw600dp/apps_view.xml
+++ b/res/layout-sw600dp/apps_view.xml
@@ -22,7 +22,7 @@
android:background="#22000000"
android:descendantFocusability="afterDescendants">
<include
- layout="@layout/apps_list_reveal_view"
+ layout="@layout/apps_reveal_view"
android:layout_width="@dimen/apps_container_width"
android:layout_height="540dp"
android:layout_gravity="center" />
diff --git a/res/layout/apps_empty_view.xml b/res/layout/apps_empty_view.xml
new file mode 100644
index 000000000..8408077a2
--- /dev/null
+++ b/res/layout/apps_empty_view.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/empty_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:paddingTop="24dp"
+ android:paddingBottom="24dp"
+ android:paddingRight="@dimen/apps_grid_view_start_margin"
+ android:textSize="16sp"
+ android:textColor="#4c4c4c"
+ android:focusable="false" />
+
diff --git a/res/layout/apps_list_reveal_view.xml b/res/layout/apps_reveal_view.xml
index 19e462bee..19e462bee 100644
--- a/res/layout/apps_list_reveal_view.xml
+++ b/res/layout/apps_reveal_view.xml
diff --git a/res/layout/apps_view.xml b/res/layout/apps_view.xml
index c1bae63f6..00f3cca88 100644
--- a/res/layout/apps_view.xml
+++ b/res/layout/apps_view.xml
@@ -22,7 +22,7 @@
android:background="@drawable/apps_customize_bg"
android:descendantFocusability="afterDescendants">
<include
- layout="@layout/apps_list_reveal_view" />
+ layout="@layout/apps_reveal_view" />
<include
layout="@layout/apps_list_view" />
</com.android.launcher3.AppsContainerView> \ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0d113dbf7..408109d15 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -74,6 +74,10 @@
<!-- Apps view -->
<!-- Search bar text in the apps view. [CHAR_LIMIT=50] -->
<string name="apps_view_search_bar_hint">Search Apps</string>
+ <!-- Loading apps text. [CHAR_LIMIT=50] -->
+ <string name="loading_apps_message">Loading Apps...</string>
+ <!-- No-search-results text. [CHAR_LIMIT=50] -->
+ <string name="apps_view_no_search_results">No Apps found matching \"<xliff:g id="query" example="Android">%1$s</xliff:g>\"</string>
<!-- Folders -->
<skip />
diff --git a/src/com/android/launcher3/AlphabeticalAppsList.java b/src/com/android/launcher3/AlphabeticalAppsList.java
index 2847afc89..c1d2738da 100644
--- a/src/com/android/launcher3/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/AlphabeticalAppsList.java
@@ -78,9 +78,7 @@ public class AlphabeticalAppsList {
* 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;
+ return mIndexer.computeSectionName(info.title.toString().trim());
}
/**
@@ -91,6 +89,13 @@ public class AlphabeticalAppsList {
}
/**
+ * Returns whether there are no filtered results.
+ */
+ public boolean hasNoFilteredResults() {
+ return (mFilter != null) && mFilteredApps.isEmpty();
+ }
+
+ /**
* Sets the current filter for this list of apps.
*/
public void setFilter(Filter f) {
diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java
index cc31e20fa..64b27baf5 100644
--- a/src/com/android/launcher3/AppsContainerView.java
+++ b/src/com/android/launcher3/AppsContainerView.java
@@ -16,10 +16,12 @@
package com.android.launcher3;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
+import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.KeyEvent;
@@ -30,7 +32,6 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
-import com.android.launcher3.compat.AlphabeticIndexCompat;
import java.util.List;
@@ -76,6 +77,7 @@ public class AppsContainerView extends FrameLayout implements DragSource, View.O
super(context, attrs, defStyleAttr, defStyleRes);
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ Resources res = context.getResources();
mLauncher = (Launcher) context;
mApps = new AlphabeticalAppsList(context);
@@ -83,6 +85,7 @@ public class AppsContainerView extends FrameLayout implements DragSource, View.O
mNumAppsPerRow = grid.appsViewNumCols;
AppsGridAdapter adapter = new AppsGridAdapter(context, mApps, mNumAppsPerRow, this,
mLauncher, this);
+ adapter.setEmptySearchText(res.getString(R.string.loading_apps_message));
mLayoutManager = adapter.getLayoutManager(context);
mItemDecoration = adapter.getItemDecoration();
mAdapter = adapter;
@@ -90,6 +93,7 @@ public class AppsContainerView extends FrameLayout implements DragSource, View.O
} else if (USE_LAYOUT == LIST_LAYOUT) {
mNumAppsPerRow = 1;
AppsListAdapter adapter = new AppsListAdapter(context, mApps, this, mLauncher, this);
+ adapter.setEmptySearchText(res.getString(R.string.loading_apps_message));
mLayoutManager = adapter.getLayoutManager(context);
mAdapter = adapter;
}
@@ -163,10 +167,12 @@ public class AppsContainerView extends FrameLayout implements DragSource, View.O
mAppsListView.setHasFixedSize(true);
if (isRtl) {
mAppsListView.setPadding(mAppsListView.getPaddingLeft(), mAppsListView.getPaddingTop(),
- mAppsListView.getPaddingRight() + mContentMarginStart, mAppsListView.getPaddingBottom());
+ mAppsListView.getPaddingRight() + mContentMarginStart,
+ mAppsListView.getPaddingBottom());
} else {
- mAppsListView.setPadding(mAppsListView.getPaddingLeft() + mContentMarginStart, mAppsListView.getPaddingTop(),
- mAppsListView.getPaddingRight(), mAppsListView.getPaddingBottom());
+ mAppsListView.setPadding(mAppsListView.getPaddingLeft() + mContentMarginStart,
+ mAppsListView.getPaddingTop(), mAppsListView.getPaddingRight(),
+ mAppsListView.getPaddingBottom());
}
if (mItemDecoration != null) {
mAppsListView.addItemDecoration(mItemDecoration);
@@ -299,7 +305,15 @@ public class AppsContainerView extends FrameLayout implements DragSource, View.O
if (s.toString().isEmpty()) {
mApps.setFilter(null);
} else {
- final AlphabeticIndexCompat indexer = mApps.getIndexer();
+ String formatStr = getResources().getString(R.string.apps_view_no_search_results);
+ if (USE_LAYOUT == GRID_LAYOUT) {
+ ((AppsGridAdapter) mAdapter).setEmptySearchText(String.format(formatStr,
+ s.toString()));
+ } else {
+ ((AppsListAdapter) mAdapter).setEmptySearchText(String.format(formatStr,
+ s.toString()));
+ }
+
final String filterText = s.toString().toLowerCase().replaceAll("\\s+", "");
mApps.setFilter(new AlphabeticalAppsList.Filter() {
@Override
diff --git a/src/com/android/launcher3/AppsGridAdapter.java b/src/com/android/launcher3/AppsGridAdapter.java
index 6727e4f09..028cd8f70 100644
--- a/src/com/android/launcher3/AppsGridAdapter.java
+++ b/src/com/android/launcher3/AppsGridAdapter.java
@@ -10,6 +10,7 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextView;
import com.android.launcher3.compat.AlphabeticIndexCompat;
@@ -22,6 +23,7 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
private static final int SECTION_BREAK_VIEW_TYPE = 0;
private static final int ICON_VIEW_TYPE = 1;
+ private static final int EMPTY_VIEW_TYPE = 2;
/**
* ViewHolder for each icon.
@@ -29,11 +31,13 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder {
public View mContent;
public boolean mIsSectionRow;
+ public boolean mIsEmptyRow;
- public ViewHolder(View v, boolean isSectionRow) {
+ public ViewHolder(View v, boolean isSectionRow, boolean isEmptyRow) {
super(v);
mContent = v;
mIsSectionRow = isSectionRow;
+ mIsEmptyRow = isEmptyRow;
}
}
@@ -43,8 +47,14 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup {
@Override
public int getSpanSize(int position) {
+ if (mApps.hasNoFilteredResults()) {
+ // Empty view spans full width
+ return mAppsPerRow;
+ }
+
AppInfo info = mApps.getApps().get(position);
if (info == AlphabeticalAppsList.SECTION_BREAK_INFO) {
+ // Section break spans full width
return mAppsPerRow;
} else {
return 1;
@@ -59,14 +69,13 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
- AlphabeticIndexCompat indexer = mApps.getIndexer();
for (int i = 0; i < parent.getChildCount(); i++) {
View child = parent.getChildAt(i);
ViewHolder holder = (ViewHolder) parent.getChildViewHolder(child);
if (holder != null) {
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)
child.getLayoutParams();
- if (!holder.mIsSectionRow && !lp.isItemRemoved()) {
+ if (!holder.mIsSectionRow && !holder.mIsEmptyRow && !lp.isItemRemoved()) {
if (mApps.getApps().get(holder.getPosition() - 1) ==
AlphabeticalAppsList.SECTION_BREAK_INFO) {
// Draw at the parent
@@ -106,6 +115,7 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
private View.OnLongClickListener mIconLongClickListener;
private int mAppsPerRow;
private boolean mIsRtl;
+ private String mEmptySearchText;
// Section drawing
private int mStartMargin;
@@ -141,6 +151,13 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
}
/**
+ * Sets the text to show when there are no apps.
+ */
+ public void setEmptySearchText(String query) {
+ mEmptySearchText = query;
+ }
+
+ /**
* Returns the grid layout manager.
*/
public GridLayoutManager getLayoutManager(Context context) {
@@ -167,8 +184,12 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
+ case EMPTY_VIEW_TYPE:
+ return new ViewHolder(mLayoutInflater.inflate(R.layout.apps_empty_view, parent,
+ false), false /* isSectionRow */, true /* isEmptyRow */);
case SECTION_BREAK_VIEW_TYPE:
- return new ViewHolder(new View(parent.getContext()), true);
+ return new ViewHolder(new View(parent.getContext()), true /* isSectionRow */,
+ false /* isEmptyRow */);
case ICON_VIEW_TYPE:
BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
R.layout.apps_grid_row_icon_view, parent, false);
@@ -176,7 +197,7 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
icon.setOnClickListener(mIconClickListener);
icon.setOnLongClickListener(mIconLongClickListener);
icon.setFocusable(true);
- return new ViewHolder(icon, false);
+ return new ViewHolder(icon, false /* isSectionRow */, false /* isEmptyRow */);
default:
throw new RuntimeException("Unexpected view type");
}
@@ -184,21 +205,33 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
- AppInfo info = mApps.getApps().get(position);
- if (info != AlphabeticalAppsList.SECTION_BREAK_INFO) {
- BubbleTextView icon = (BubbleTextView) holder.mContent;
- icon.applyFromApplicationInfo(info);
+ switch (holder.getItemViewType()) {
+ case ICON_VIEW_TYPE:
+ AppInfo info = mApps.getApps().get(position);
+ BubbleTextView icon = (BubbleTextView) holder.mContent;
+ icon.applyFromApplicationInfo(info);
+ break;
+ case EMPTY_VIEW_TYPE:
+ TextView emptyViewText = (TextView) holder.mContent.findViewById(R.id.empty_text);
+ emptyViewText.setText(mEmptySearchText);
+ break;
}
}
@Override
public int getItemCount() {
+ if (mApps.hasNoFilteredResults()) {
+ // For the empty view
+ return 1;
+ }
return mApps.getApps().size();
}
@Override
public int getItemViewType(int position) {
- if (mApps.getApps().get(position) == AlphabeticalAppsList.SECTION_BREAK_INFO) {
+ if (mApps.hasNoFilteredResults()) {
+ return EMPTY_VIEW_TYPE;
+ } else if (mApps.getApps().get(position) == AlphabeticalAppsList.SECTION_BREAK_INFO) {
return SECTION_BREAK_VIEW_TYPE;
}
return ICON_VIEW_TYPE;
diff --git a/src/com/android/launcher3/AppsListAdapter.java b/src/com/android/launcher3/AppsListAdapter.java
index 8ac381e79..e1f4d3578 100644
--- a/src/com/android/launcher3/AppsListAdapter.java
+++ b/src/com/android/launcher3/AppsListAdapter.java
@@ -30,12 +30,14 @@ class AppsListAdapter extends RecyclerView.Adapter<AppsListAdapter.ViewHolder> {
private static final int SECTION_BREAK_VIEW_TYPE = 0;
private static final int ICON_VIEW_TYPE = 1;
+ private static final int EMPTY_VIEW_TYPE = 2;
private LayoutInflater mLayoutInflater;
private AlphabeticalAppsList mApps;
private View.OnTouchListener mTouchListener;
private View.OnClickListener mIconClickListener;
private View.OnLongClickListener mIconLongClickListener;
+ private String mEmptySearchText;
public AppsListAdapter(Context context, AlphabeticalAppsList apps,
View.OnTouchListener touchListener, View.OnClickListener iconClickListener,
@@ -51,9 +53,19 @@ class AppsListAdapter extends RecyclerView.Adapter<AppsListAdapter.ViewHolder> {
return new LinearLayoutManager(context);
}
+ /**
+ * Sets the text to show when there are no apps.
+ */
+ public void setEmptySearchText(String query) {
+ mEmptySearchText = query;
+ }
+
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
+ case EMPTY_VIEW_TYPE:
+ return new ViewHolder(mLayoutInflater.inflate(R.layout.apps_empty_view, parent,
+ false));
case SECTION_BREAK_VIEW_TYPE:
return new ViewHolder(new View(parent.getContext()));
case ICON_VIEW_TYPE:
@@ -79,39 +91,51 @@ class AppsListAdapter extends RecyclerView.Adapter<AppsListAdapter.ViewHolder> {
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
- AppInfo info = mApps.getApps().get(position);
- if (info != AlphabeticalAppsList.SECTION_BREAK_INFO) {
- ViewGroup content = (ViewGroup) holder.mContent;
- String sectionDescription = mApps.getSectionNameForApp(info);
+ switch (holder.getItemViewType()) {
+ case ICON_VIEW_TYPE:
+ AppInfo info = mApps.getApps().get(position);
+ ViewGroup content = (ViewGroup) holder.mContent;
+ String sectionDescription = mApps.getSectionNameForApp(info);
- // Bind the section header
- boolean showSectionHeader = true;
- if (position > 0) {
- AppInfo prevInfo = mApps.getApps().get(position - 1);
- showSectionHeader = (prevInfo == AlphabeticalAppsList.SECTION_BREAK_INFO);
- }
- TextView tv = (TextView) content.findViewById(R.id.section);
- if (showSectionHeader) {
- tv.setText(sectionDescription);
- tv.setVisibility(View.VISIBLE);
- } else {
- tv.setVisibility(View.INVISIBLE);
- }
+ // Bind the section header
+ boolean showSectionHeader = true;
+ if (position > 0) {
+ AppInfo prevInfo = mApps.getApps().get(position - 1);
+ showSectionHeader = (prevInfo == AlphabeticalAppsList.SECTION_BREAK_INFO);
+ }
+ TextView tv = (TextView) content.findViewById(R.id.section);
+ if (showSectionHeader) {
+ tv.setText(sectionDescription);
+ tv.setVisibility(View.VISIBLE);
+ } else {
+ tv.setVisibility(View.INVISIBLE);
+ }
- // Bind the icon
- BubbleTextView icon = (BubbleTextView) content.getChildAt(1);
- icon.applyFromApplicationInfo(info);
+ // Bind the icon
+ BubbleTextView icon = (BubbleTextView) content.getChildAt(1);
+ icon.applyFromApplicationInfo(info);
+ break;
+ case EMPTY_VIEW_TYPE:
+ TextView emptyViewText = (TextView) holder.mContent.findViewById(R.id.empty_text);
+ emptyViewText.setText(mEmptySearchText);
+ break;
}
}
@Override
public int getItemCount() {
+ if (mApps.hasNoFilteredResults()) {
+ // For the empty view
+ return 1;
+ }
return mApps.getApps().size();
}
@Override
public int getItemViewType(int position) {
- if (mApps.getApps().get(position) == AlphabeticalAppsList.SECTION_BREAK_INFO) {
+ if (mApps.hasNoFilteredResults()) {
+ return EMPTY_VIEW_TYPE;
+ } else if (mApps.getApps().get(position) == AlphabeticalAppsList.SECTION_BREAK_INFO) {
return SECTION_BREAK_VIEW_TYPE;
}
return ICON_VIEW_TYPE;
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index fabae5702..8ef234bb0 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -161,7 +161,8 @@ public class BubbleTextView extends TextView {
if (info.contentDescription != null) {
setContentDescription(info.contentDescription);
}
- setTag(info);
+ // We don't need to check the info since it's not a ShortcutInfo
+ super.setTag(info);
}
@Override
diff --git a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
index 602a84566..47e1b7a98 100644
--- a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
+++ b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
@@ -27,7 +27,7 @@ class BaseAlphabeticIndex {
/**
* Returns the index of the bucket in which the given string should appear.
*/
- public int getBucketIndex(String s) {
+ protected int getBucketIndex(String s) {
if (s.isEmpty()) {
return UNKNOWN_BUCKET_INDEX;
}
@@ -41,7 +41,7 @@ class BaseAlphabeticIndex {
/**
* Returns the label for the bucket at the given index (as returned by getBucketIndex).
*/
- public String getBucketLabel(int index) {
+ protected String getBucketLabel(int index) {
return BUCKETS.substring(index, index + 1);
}
}
@@ -100,11 +100,29 @@ public class AlphabeticIndexCompat extends BaseAlphabeticIndex {
}
/**
+ * Computes the section name for an given string {@param s}.
+ */
+ public String computeSectionName(String s) {
+ String sectionName = getBucketLabel(getBucketIndex(s));
+ if (sectionName.trim().isEmpty() && s.length() > 0) {
+ boolean startsWithDigit = Character.isDigit(s.charAt(0));
+ if (startsWithDigit) {
+ // Digit section
+ return "#";
+ } else {
+ // Unknown section
+ return "\u2022";
+ }
+ }
+ return sectionName;
+ }
+
+ /**
* Returns the index of the bucket in which {@param s} should appear.
* Function is synchronized because underlying routine walks an iterator
* whose state is maintained inside the index object.
*/
- public int getBucketIndex(String s) {
+ protected int getBucketIndex(String s) {
if (mHasValidAlphabeticIndex) {
try {
return (Integer) mGetBucketIndexMethod.invoke(mAlphabeticIndex, s);
@@ -118,7 +136,7 @@ public class AlphabeticIndexCompat extends BaseAlphabeticIndex {
/**
* Returns the label for the bucket at the given index (as returned by getBucketIndex).
*/
- public String getBucketLabel(int index) {
+ protected String getBucketLabel(int index) {
if (mHasValidAlphabeticIndex) {
try {
return (String) mGetBucketLabelMethod.invoke(mAlphabeticIndex, index);