Merge "Fix bug #5199577 TextView with android:password="true" is showing the "dots" on the left even if the password chars are RTL"
This commit is contained in:
committed by
Android (Google) Code Review
commit
d32f27aec0
@@ -345,7 +345,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
|||||||
sb.append(" (no locale)");
|
sb.append(" (no locale)");
|
||||||
}
|
}
|
||||||
switch (textLayoutDirection) {
|
switch (textLayoutDirection) {
|
||||||
case LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE: sb.append(" ?layoutdir"); break;
|
|
||||||
case LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break;
|
case LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break;
|
||||||
default: sb.append(" layoutdir="); sb.append(textLayoutDirection); break;
|
default: sb.append(" layoutdir="); sb.append(textLayoutDirection); break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
package android.text;
|
package android.text;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import android.util.LocaleUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some objects that implement TextDirectionHeuristic.
|
* Some objects that implement TextDirectionHeuristic.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -75,6 +79,11 @@ public class TextDirectionHeuristics {
|
|||||||
public static final TextDirectionHeuristic CHARCOUNT_RTL =
|
public static final TextDirectionHeuristic CHARCOUNT_RTL =
|
||||||
new TextDirectionHeuristicInternal(CharCount.INSTANCE_DEFAULT, true);
|
new TextDirectionHeuristicInternal(CharCount.INSTANCE_DEFAULT, true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force the paragraph direction to the Locale direction. Falls back to left to right.
|
||||||
|
*/
|
||||||
|
public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;
|
||||||
|
|
||||||
private static enum TriState {
|
private static enum TriState {
|
||||||
TRUE, FALSE, UNKNOWN;
|
TRUE, FALSE, UNKNOWN;
|
||||||
}
|
}
|
||||||
@@ -300,4 +309,23 @@ public class TextDirectionHeuristics {
|
|||||||
public static final float DEFAULT_THRESHOLD = 0.6f;
|
public static final float DEFAULT_THRESHOLD = 0.6f;
|
||||||
public static final CharCount INSTANCE_DEFAULT = new CharCount(DEFAULT_THRESHOLD);
|
public static final CharCount INSTANCE_DEFAULT = new CharCount(DEFAULT_THRESHOLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Algorithm that uses the Locale direction to force the direction of a paragraph.
|
||||||
|
*/
|
||||||
|
public static class TextDirectionHeuristicLocale extends TextDirectionHeuristicImpl {
|
||||||
|
|
||||||
|
public TextDirectionHeuristicLocale() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean defaultIsRtl() {
|
||||||
|
final int dir = LocaleUtil.getLayoutDirectionFromLocale(java.util.Locale.getDefault());
|
||||||
|
return (dir == LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final TextDirectionHeuristicLocale INSTANCE =
|
||||||
|
new TextDirectionHeuristicLocale();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,6 @@ public class LocaleUtil {
|
|||||||
|
|
||||||
private LocaleUtil() { /* cannot be instantiated */ }
|
private LocaleUtil() { /* cannot be instantiated */ }
|
||||||
|
|
||||||
/**
|
|
||||||
* @hide Do not use. Implementation not finished.
|
|
||||||
*/
|
|
||||||
public static final int TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE = -1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide Do not use. Implementation not finished.
|
* @hide Do not use. Implementation not finished.
|
||||||
*/
|
*/
|
||||||
@@ -54,7 +49,6 @@ public class LocaleUtil {
|
|||||||
*
|
*
|
||||||
* @param locale the Locale for which we want the layout direction. Can be null.
|
* @param locale the Locale for which we want the layout direction. Can be null.
|
||||||
* @return the layout direction. This may be one of:
|
* @return the layout direction. This may be one of:
|
||||||
* {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
|
|
||||||
* {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
|
* {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
|
||||||
* {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
|
* {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
|
||||||
*
|
*
|
||||||
@@ -63,17 +57,16 @@ public class LocaleUtil {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static int getLayoutDirectionFromLocale(Locale locale) {
|
public static int getLayoutDirectionFromLocale(Locale locale) {
|
||||||
if (locale == null || locale.equals(Locale.ROOT)) {
|
if (locale != null && !locale.equals(Locale.ROOT)) {
|
||||||
return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
|
final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
|
||||||
|
if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
|
||||||
|
|
||||||
|
if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
|
||||||
|
scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
|
||||||
|
return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
|
|
||||||
if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
|
|
||||||
|
|
||||||
if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
|
|
||||||
scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
|
|
||||||
return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
|
|
||||||
}
|
|
||||||
return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
|
return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +77,6 @@ public class LocaleUtil {
|
|||||||
*
|
*
|
||||||
* @param locale
|
* @param locale
|
||||||
* @return the layout direction. This may be one of:
|
* @return the layout direction. This may be one of:
|
||||||
* {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
|
|
||||||
* {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
|
* {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
|
||||||
* {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
|
* {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
|
||||||
*
|
*
|
||||||
@@ -94,13 +86,13 @@ public class LocaleUtil {
|
|||||||
*/
|
*/
|
||||||
private static int getLayoutDirectionFromFirstChar(Locale locale) {
|
private static int getLayoutDirectionFromFirstChar(Locale locale) {
|
||||||
switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
|
switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
|
||||||
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
|
|
||||||
return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
|
|
||||||
case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
|
case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
|
||||||
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
|
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
|
||||||
return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
|
return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
|
||||||
|
|
||||||
|
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
|
||||||
default:
|
default:
|
||||||
return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
|
return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10886,6 +10886,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void resolveTextDirection() {
|
protected void resolveTextDirection() {
|
||||||
|
if (hasPasswordTransformationMethod()) {
|
||||||
|
mTextDir = TextDirectionHeuristics.LOCALE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Always need to resolve layout direction first
|
// Always need to resolve layout direction first
|
||||||
final boolean defaultIsRtl = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
|
final boolean defaultIsRtl = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import dalvik.annotation.TestLevel;
|
|||||||
import dalvik.annotation.TestTargetNew;
|
import dalvik.annotation.TestTargetNew;
|
||||||
|
|
||||||
import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
|
import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
|
||||||
import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
|
|
||||||
|
|
||||||
public class LocaleUtilTest extends AndroidTestCase {
|
public class LocaleUtilTest extends AndroidTestCase {
|
||||||
|
|
||||||
@@ -33,7 +32,7 @@ public class LocaleUtilTest extends AndroidTestCase {
|
|||||||
args = {Locale.class}
|
args = {Locale.class}
|
||||||
)
|
)
|
||||||
public void testGetLayoutDirectionFromLocale() {
|
public void testGetLayoutDirectionFromLocale() {
|
||||||
assertEquals(TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
|
assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
|
||||||
LocaleUtil.getLayoutDirectionFromLocale(null));
|
LocaleUtil.getLayoutDirectionFromLocale(null));
|
||||||
|
|
||||||
assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
|
assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
|
||||||
@@ -59,7 +58,7 @@ public class LocaleUtilTest extends AndroidTestCase {
|
|||||||
assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
|
assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
|
||||||
LocaleUtil.getLayoutDirectionFromLocale(Locale.US));
|
LocaleUtil.getLayoutDirectionFromLocale(Locale.US));
|
||||||
|
|
||||||
assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
|
assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
|
||||||
LocaleUtil.getLayoutDirectionFromLocale(Locale.ROOT));
|
LocaleUtil.getLayoutDirectionFromLocale(Locale.ROOT));
|
||||||
|
|
||||||
assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
|
assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
|
||||||
|
|||||||
@@ -27,11 +27,18 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<Button android:id="@+id/button"
|
<TextView android:id="@+id/textview_password_default"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:text="@string/button_text"
|
|
||||||
android:textSize="32dip"
|
android:textSize="32dip"
|
||||||
|
android:text="@string/textview_password_default_text"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<EditText android:id="@+id/edittext_password_default"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:textSize="32dip"
|
||||||
|
android:password="true"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView android:id="@+id/textview_default"
|
<TextView android:id="@+id/textview_default"
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
<string name="textview_ltr_text">This is a text for a LTR TextView</string>
|
<string name="textview_ltr_text">This is a text for a LTR TextView</string>
|
||||||
<string name="textview_rtl_text">This is a text for a RTL TextView</string>
|
<string name="textview_rtl_text">This is a text for a RTL TextView</string>
|
||||||
<string name="textview_default_text">This is a text for a default TextView</string>
|
<string name="textview_default_text">This is a text for a default TextView</string>
|
||||||
|
<string name="textview_password_default_text">This is a text for a password TextView</string>
|
||||||
<string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
|
<string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
|
||||||
<string name="normal_text">Normal String</string>
|
<string name="normal_text">Normal String</string>
|
||||||
<string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
|
<string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user