New attribute textFontWeight for selecting weight in the font family

Note that AppCompatTextView doesn't work well with this attribute since
it overwrites the selected Typeface.

Bug: 63135308
Test: atest android.widget.cts.TextViewFontWeightTest
Change-Id: I76ee5e3007ea5f96249d2a0bfb66ff5975c62522
This commit is contained in:
Seigo Nonaka
2018-02-22 11:26:39 -08:00
parent f42a1080d5
commit e245116af3
5 changed files with 91 additions and 35 deletions

View File

@@ -1378,6 +1378,7 @@ package android {
field public static final int textEditSidePasteWindowLayout = 16843614; // 0x101035e
field public static final int textEditSuggestionItemLayout = 16843636; // 0x1010374
field public static final int textFilterEnabled = 16843007; // 0x10100ff
field public static final int textFontWeight = 16844166; // 0x1010586
field public static final int textIsSelectable = 16843542; // 0x1010316
field public static final int textOff = 16843045; // 0x1010125
field public static final int textOn = 16843044; // 0x1010124

View File

@@ -319,6 +319,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Enum for the "typeface" XML parameter.
// TODO: How can we get this from the XML instead of hardcoding it here?
/** @hide */
@IntDef(value = {DEFAULT_TYPEFACE, SANS, SERIF, MONOSPACE})
@Retention(RetentionPolicy.SOURCE)
public @interface XMLTypefaceAttr{}
private static final int DEFAULT_TYPEFACE = -1;
private static final int SANS = 1;
private static final int SERIF = 2;
private static final int MONOSPACE = 3;
@@ -1976,33 +1981,52 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
private void setTypefaceFromAttrs(Typeface fontTypeface, String familyName, int typefaceIndex,
int styleIndex) {
Typeface tf = fontTypeface;
if (tf == null && familyName != null) {
tf = Typeface.create(familyName, styleIndex);
} else if (tf != null && tf.getStyle() != styleIndex) {
tf = Typeface.create(tf, styleIndex);
/**
* Sets the Typeface taking into account the given attributes.
*
* @param typeface a typeface
* @param familyName family name string, e.g. "serif"
* @param typefaceIndex an index of the typeface enum, e.g. SANS, SERIF.
* @param style a typeface style
* @param weight a weight value for the Typeface or -1 if not specified.
*/
private void setTypefaceFromAttrs(@Nullable Typeface typeface, @Nullable String familyName,
@XMLTypefaceAttr int typefaceIndex, @Typeface.Style int style,
@IntRange(from = -1, to = Typeface.MAX_WEIGHT) int weight) {
if (typeface == null && familyName != null) {
// Lookup normal Typeface from system font map.
final Typeface normalTypeface = Typeface.create(familyName, Typeface.NORMAL);
resolveStyleAndSetTypeface(normalTypeface, style, weight);
} else if (typeface != null) {
resolveStyleAndSetTypeface(typeface, style, weight);
} else { // both typeface and familyName is null.
switch (typefaceIndex) {
case SANS:
resolveStyleAndSetTypeface(Typeface.SANS_SERIF, style, weight);
break;
case SERIF:
resolveStyleAndSetTypeface(Typeface.SERIF, style, weight);
break;
case MONOSPACE:
resolveStyleAndSetTypeface(Typeface.MONOSPACE, style, weight);
break;
case DEFAULT_TYPEFACE:
default:
resolveStyleAndSetTypeface(null, style, weight);
break;
}
}
if (tf != null) {
setTypeface(tf);
return;
}
private void resolveStyleAndSetTypeface(@NonNull Typeface typeface, @Typeface.Style int style,
@IntRange(from = -1, to = Typeface.MAX_WEIGHT) int weight) {
if (weight >= 0) {
weight = Math.min(Typeface.MAX_WEIGHT, weight);
final boolean italic = (style & Typeface.ITALIC) != 0;
setTypeface(Typeface.create(typeface, weight, italic));
} else {
setTypeface(Typeface.create(typeface, style));
}
switch (typefaceIndex) {
case SANS:
tf = Typeface.SANS_SERIF;
break;
case SERIF:
tf = Typeface.SERIF;
break;
case MONOSPACE:
tf = Typeface.MONOSPACE;
break;
}
setTypeface(tf, styleIndex);
}
private void setRelativeDrawablesIfNeeded(Drawable start, Drawable end) {
@@ -3392,6 +3416,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
boolean mFontFamilyExplicit = false;
int mTypefaceIndex = -1;
int mStyleIndex = -1;
int mFontWeight = -1;
boolean mAllCaps = false;
int mShadowColor = 0;
float mShadowDx = 0, mShadowDy = 0, mShadowRadius = 0;
@@ -3416,6 +3441,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
+ " mFontFamilyExplicit:" + mFontFamilyExplicit + "\n"
+ " mTypefaceIndex:" + mTypefaceIndex + "\n"
+ " mStyleIndex:" + mStyleIndex + "\n"
+ " mFontWeight:" + mFontWeight + "\n"
+ " mAllCaps:" + mAllCaps + "\n"
+ " mShadowColor:" + mShadowColor + "\n"
+ " mShadowDx:" + mShadowDx + "\n"
@@ -3451,6 +3477,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
com.android.internal.R.styleable.TextAppearance_fontFamily);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_textStyle,
com.android.internal.R.styleable.TextAppearance_textStyle);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_textFontWeight,
com.android.internal.R.styleable.TextAppearance_textFontWeight);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_textAllCaps,
com.android.internal.R.styleable.TextAppearance_textAllCaps);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_shadowColor,
@@ -3536,6 +3564,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
case com.android.internal.R.styleable.TextAppearance_textStyle:
attributes.mStyleIndex = appearance.getInt(attr, attributes.mStyleIndex);
break;
case com.android.internal.R.styleable.TextAppearance_textFontWeight:
attributes.mFontWeight = appearance.getInt(attr, attributes.mFontWeight);
break;
case com.android.internal.R.styleable.TextAppearance_textAllCaps:
attributes.mAllCaps = appearance.getBoolean(attr, attributes.mAllCaps);
break;
@@ -3598,7 +3629,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
attributes.mFontFamily = null;
}
setTypefaceFromAttrs(attributes.mFontTypeface, attributes.mFontFamily,
attributes.mTypefaceIndex, attributes.mStyleIndex);
attributes.mTypefaceIndex, attributes.mStyleIndex, attributes.mFontWeight);
if (attributes.mShadowColor != 0) {
setShadowLayer(attributes.mShadowRadius, attributes.mShadowDx, attributes.mShadowDy,
@@ -5938,15 +5969,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
boolean forceUpdate = false;
if (isPassword) {
setTransformationMethod(PasswordTransformationMethod.getInstance());
setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */, MONOSPACE, 0);
setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */, MONOSPACE,
Typeface.NORMAL, -1 /* weight, not specifeid */);
} else if (isVisiblePassword) {
if (mTransformation == PasswordTransformationMethod.getInstance()) {
forceUpdate = true;
}
setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */, MONOSPACE, 0);
setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */, MONOSPACE,
Typeface.NORMAL, -1 /* weight, not specified */);
} else if (wasPassword || wasVisiblePassword) {
// not in password mode, clean up typeface and transformation
setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */, -1, -1);
setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */,
DEFAULT_TYPEFACE /* typeface index */, Typeface.NORMAL,
-1 /* weight, not specified */);
if (mTransformation == PasswordTransformationMethod.getInstance()) {
forceUpdate = true;
}

View File

@@ -4472,6 +4472,8 @@
<attr name="textSize" />
<!-- Style (normal, bold, italic, bold|italic) for the text. -->
<attr name="textStyle" />
<!-- Weight for the font used in the TextView. -->
<attr name="textFontWeight" />
<!-- Typeface (normal, sans, serif, monospace) for the text. -->
<attr name="typeface" />
<!-- Font family (named by string or as a font resource reference) for the text. -->
@@ -4561,6 +4563,8 @@
<attr name="typeface" />
<!-- Style (normal, bold, italic, bold|italic) for the text. -->
<attr name="textStyle" />
<!-- Weight for the font used in the TextView. -->
<attr name="textFontWeight" />
<!-- Font family (named by string or as a font resource reference) for the text. -->
<attr name="fontFamily" />
<!-- Text color for links. -->

View File

@@ -2872,6 +2872,7 @@
<public name="urlBarResourceId" />
<!-- @hide @SystemApi -->
<public name="userRestriction" />
<public name="textFontWeight" />
</public-group>
<public-group type="style" first-id="0x010302e0">

View File

@@ -21,6 +21,7 @@ import static android.content.res.FontResourcesParser.FontFamilyFilesResourceEnt
import static android.content.res.FontResourcesParser.FontFileResourceEntry;
import static android.content.res.FontResourcesParser.ProviderResourceEntry;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -49,6 +50,8 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
@@ -117,6 +120,11 @@ public class Typeface {
*/
public long native_instance;
/** @hide */
@IntDef(value = {NORMAL, BOLD, ITALIC, BOLD_ITALIC})
@Retention(RetentionPolicy.SOURCE)
public @interface Style {}
// Style
public static final int NORMAL = 0;
public static final int BOLD = 1;
@@ -124,8 +132,15 @@ public class Typeface {
public static final int BOLD_ITALIC = 3;
/** @hide */ public static final int STYLE_MASK = 0x03;
private int mStyle = 0;
private int mWeight = 0;
private @Style int mStyle = 0;
/**
* A maximum value for the weight value.
* @hide
*/
public static final int MAX_WEIGHT = 1000;
private @IntRange(from = 0, to = MAX_WEIGHT) int mWeight = 0;
// Value for weight and italic. Indicates the value is resolved by font metadata.
// Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
@@ -153,7 +168,7 @@ public class Typeface {
}
/** Returns the typeface's intrinsic style attributes */
public int getStyle() {
public @Style int getStyle() {
return mStyle;
}
@@ -659,7 +674,7 @@ public class Typeface {
* e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
* @return The best matching typeface.
*/
public static Typeface create(String familyName, int style) {
public static Typeface create(String familyName, @Style int style) {
return create(sSystemFontMap.get(familyName), style);
}
@@ -680,7 +695,7 @@ public class Typeface {
* e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
* @return The best matching typeface.
*/
public static Typeface create(Typeface family, int style) {
public static Typeface create(Typeface family, @Style int style) {
if ((style & ~STYLE_MASK) != 0) {
style = NORMAL;
}
@@ -776,7 +791,7 @@ public class Typeface {
*
* @return the default typeface that corresponds to the style
*/
public static Typeface defaultFromStyle(int style) {
public static Typeface defaultFromStyle(@Style int style) {
return sDefaults[style];
}