<TextView
...
android:fontFamily="sans-serif" or "sans-serif-medium"
android:textStyle="normal" or "bold" />
fontFamily | textStyle | weight | style | isBold |
---|---|---|---|---|
sans-serif | normal | 400 | 0 | false |
sans-serif | bold | 700 | 1 | true |
sans-serif-medium | normal | 500 | 0 | false |
sans-serif-medium | bold | 800 | 1 | true |
Typeface の style は textStyle の設定が反映されます。style が 1 だと Typeface.BOLD, 2 だと Typeface.ITALIC, 3 だと Typeface.BOLD_ITALIC です。なので style が 1 のとき isBold が true になっています。
"sans-serif-medium" + normal はちょっと太いですが isBold は false です。
android:textStyle の値をプログラムから変更するには TextView.setTypeface() メソッドを使います。このメソッドには引数の異なる2種類があります。
public void setTypeface(@Nullable Typeface tf, @Typeface.Style int style) {
if (style > 0) {
if (tf == null) {
tf = Typeface.defaultFromStyle(style);
} else {
tf = Typeface.create(tf, style);
}
setTypeface(tf);
// now compute what (if any) algorithmic styling is needed
int typefaceStyle = tf != null ? tf.getStyle() : 0;
int need = style & ~typefaceStyle;
mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0);
mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
} else {
mTextPaint.setFakeBoldText(false);
mTextPaint.setTextSkewX(0);
setTypeface(tf);
}
}
public void setTypeface(@Nullable Typeface tf) {
if (mTextPaint.getTypeface() != tf) {
mTextPaint.setTypeface(tf);
if (mLayout != null) {
nullLayouts();
requestLayout();
invalidate();
}
}
}
Typeface.Style を渡さない方では mTextPaint に Typeface をセットして invalidate しています。
Typeface.Style を渡す方では、最終的に setTypeface(@Nullable Typeface tf) を呼び出しています。
style が 0 より大きい場合、つまり bold, italic, bold_italic のいずれかのときは Typeface.defaultFromStyle() または Typeface.create() を使って style に対応する Typeface を生成します。 生成した Typeface が style に対応していない場合だけ FakeBold や TextSkewX がセットされます。
style が 0 (= Typeface.NORMAL)の場合、style に対応する Typeface を生成せず、渡された Typeface をそのままセットします。
これによりどういうことが起こるかと言うと、
"sans-serif-medium" + normal な TextView に setTypeface(tv.typeface, Typeface.BOLD) すると bold になるのに、
"sans-serif-medium" + bold な TextView に setTypeface(tv.typeface, Typeface.NORMAL) すると normal にならない!
のです。
mediumNormalTextView.setTypeface(mediumNormalTextView.typeface, Typeface.BOLD)
mediumBoldTextView.setTypeface(mediumBoldTextView.typeface, Typeface.NORMAL)
これは "sans-serif-medium" + bold のときに生成される Typeface 自体が bold になっていて(FakeBold を使わない)、style が 0 (= Typeface.NORMAL)の場合は渡した bold な Typeface をそのままセットされてしまうからです。
これを防ぐには、Typeface.create() で Typeface.NORMAL を適用した Typeface を生成して setTypeface() に渡します。
val tf = Typeface.create(mediumBoldTextView.typeface, Typeface.NORMAL)
mediumBoldTextView.setTypeface(tf, Typeface.NORMAL)
thanks for your help!
返信削除