- <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 を渡す方では、最終的に 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!
返信削除