Replace Locale with LocaleList in LocaleSpan.
This is a straightforward upgrading of LocaleSpan.
LocaleSpan was designed to be a mechanism to override text locale only
in a certain substring. Since now text locale supports multiple locales
with LocaleList, it should make sense to let LocaleSpan have the ability
to have multiple locales with LocaleList.
This CL also addresses an existing issue that LocaleSpan maintained only
Language/Country/Variant tags. Now Locale data associated with a
LocaleSpan is guaranteed to be preserved as long as each of them can be
created from a BCP 47 language tag with Locale#forLanguageTag(String).
Bug: 26567158
Change-Id: Ib754796d399cd00f9d02005df88874a5cd5c7642
diff --git a/api/current.txt b/api/current.txt
index 05c40d1..f45fab4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -38121,9 +38121,11 @@
public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
ctor public LocaleSpan(java.util.Locale);
+ ctor public LocaleSpan(android.util.LocaleList);
ctor public LocaleSpan(android.os.Parcel);
method public int describeContents();
method public java.util.Locale getLocale();
+ method public android.util.LocaleList getLocales();
method public int getSpanTypeId();
method public void updateDrawState(android.text.TextPaint);
method public void updateMeasureState(android.text.TextPaint);
diff --git a/api/system-current.txt b/api/system-current.txt
index fb47833..42f7860 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40480,9 +40480,11 @@
public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
ctor public LocaleSpan(java.util.Locale);
+ ctor public LocaleSpan(android.util.LocaleList);
ctor public LocaleSpan(android.os.Parcel);
method public int describeContents();
method public java.util.Locale getLocale();
+ method public android.util.LocaleList getLocales();
method public int getSpanTypeId();
method public void updateDrawState(android.text.TextPaint);
method public void updateMeasureState(android.text.TextPaint);
diff --git a/api/test-current.txt b/api/test-current.txt
index 3fb9b5f..ab985a3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -38137,9 +38137,11 @@
public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
ctor public LocaleSpan(java.util.Locale);
+ ctor public LocaleSpan(android.util.LocaleList);
ctor public LocaleSpan(android.os.Parcel);
method public int describeContents();
method public java.util.Locale getLocale();
+ method public android.util.LocaleList getLocales();
method public int getSpanTypeId();
method public void updateDrawState(android.text.TextPaint);
method public void updateMeasureState(android.text.TextPaint);
diff --git a/core/java/android/text/style/LocaleSpan.java b/core/java/android/text/style/LocaleSpan.java
index d286231..117de774 100644
--- a/core/java/android/text/style/LocaleSpan.java
+++ b/core/java/android/text/style/LocaleSpan.java
@@ -16,30 +16,56 @@
package android.text.style;
+import com.android.internal.util.Preconditions;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.Paint;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.TextUtils;
+import android.util.LocaleList;
+
import java.util.Locale;
/**
* Changes the {@link Locale} of the text to which the span is attached.
*/
public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {
- private final Locale mLocale;
+ @NonNull
+ private final LocaleList mLocales;
/**
- * Creates a LocaleSpan.
- * @param locale The {@link Locale} of the text to which the span is
- * attached.
+ * Creates a {@link LocaleSpan} from a well-formed {@link Locale}. Note that only
+ * {@link Locale} objects that can be created by {@link Locale#forLanguageTag(String)} are
+ * supported.
+ *
+ * <p><b>Caveat:</b> Do not specify any {@link Locale} object that cannot be created by
+ * {@link Locale#forLanguageTag(String)}. {@code new Locale(" a ", " b c", " d")} is an
+ * example of such a malformed {@link Locale} object.</p>
+ *
+ * @param locale The {@link Locale} of the text to which the span is attached.
+ *
+ * @see #LocaleSpan(LocaleList)
*/
- public LocaleSpan(Locale locale) {
- mLocale = locale;
+ public LocaleSpan(@Nullable Locale locale) {
+ mLocales = new LocaleList(locale);
}
- public LocaleSpan(Parcel src) {
- mLocale = new Locale(src.readString(), src.readString(), src.readString());
+ /**
+ * Creates a {@link LocaleSpan} from {@link LocaleList}.
+ *
+ * @param locales The {@link LocaleList} of the text to which the span is attached.
+ * @throws NullPointerException if {@code locales} is null
+ */
+ public LocaleSpan(@NonNull LocaleList locales) {
+ Preconditions.checkNotNull(locales, "locales cannot be null");
+ mLocales = locales;
+ }
+
+ public LocaleSpan(Parcel source) {
+ mLocales = LocaleList.CREATOR.createFromParcel(source);
}
@Override
@@ -64,31 +90,40 @@
/** @hide */
public void writeToParcelInternal(Parcel dest, int flags) {
- dest.writeString(mLocale.getLanguage());
- dest.writeString(mLocale.getCountry());
- dest.writeString(mLocale.getVariant());
+ mLocales.writeToParcel(dest, flags);
}
/**
- * Returns the {@link Locale}.
+ * @return The {@link Locale} for this span. If multiple locales are associated with this
+ * span, only the first locale is returned. {@code null} if no {@link Locale} is specified.
*
- * @return The {@link Locale} for this span.
+ * @see LocaleList#getPrimary()
+ * @see #getLocales()
*/
+ @Nullable
public Locale getLocale() {
- return mLocale;
+ return mLocales.getPrimary();
+ }
+
+ /**
+ * @return The entire list of locales that are associated with this span.
+ */
+ @NonNull
+ public LocaleList getLocales() {
+ return mLocales;
}
@Override
public void updateDrawState(TextPaint ds) {
- apply(ds, mLocale);
+ apply(ds, mLocales);
}
@Override
public void updateMeasureState(TextPaint paint) {
- apply(paint, mLocale);
+ apply(paint, mLocales);
}
- private static void apply(Paint paint, Locale locale) {
- paint.setTextLocale(locale);
+ private static void apply(@NonNull Paint paint, @NonNull LocaleList locales) {
+ paint.setTextLocales(locales);
}
}