package com.android.launcher3.compat; import android.content.Context; import android.icu.text.AlphabeticIndex; import android.os.LocaleList; import com.android.launcher3.Utilities; import java.util.Locale; import androidx.annotation.NonNull; public class AlphabeticIndexCompat { private static final String MID_DOT = "\u2219"; private final String mDefaultMiscLabel; private final AlphabeticIndex.ImmutableIndex mBaseIndex; public AlphabeticIndexCompat(Context context) { this(context.getResources().getConfiguration().getLocales()); } public AlphabeticIndexCompat(LocaleList locales) { int localeCount = locales.size(); Locale primaryLocale = localeCount == 0 ? Locale.ENGLISH : locales.get(0); AlphabeticIndex indexBuilder = new AlphabeticIndex(primaryLocale); for (int i = 1; i < localeCount; i++) { indexBuilder.addLabels(locales.get(i)); } indexBuilder.addLabels(Locale.ENGLISH); mBaseIndex = indexBuilder.buildImmutableIndex(); if (primaryLocale.getLanguage().equals(Locale.JAPANESE.getLanguage())) { // Japanese character 他 ("misc") mDefaultMiscLabel = "\u4ed6"; // TODO(winsonc, omakoto): We need to handle Japanese sections better, // especially the kanji } else { // Dot mDefaultMiscLabel = MID_DOT; } } /** * Computes the section name for an given string {@param s}. */ public String computeSectionName(@NonNull CharSequence cs) { String s = Utilities.trim(cs); String sectionName = mBaseIndex.getBucket(mBaseIndex.getBucketIndex(s)).getLabel(); if (Utilities.trim(sectionName).isEmpty() && s.length() > 0) { int c = s.codePointAt(0); boolean startsWithDigit = Character.isDigit(c); if (startsWithDigit) { // Digit section return "#"; } else { boolean startsWithLetter = Character.isLetter(c); if (startsWithLetter) { return mDefaultMiscLabel; } else { // In languages where these differ, this ensures that we differentiate // between the misc section in the native language and a misc section // for everything else. return MID_DOT; } } } return sectionName; } }