4

I have a custom TextView, implemented essentially the same as in this blog post which defaults to a certain font, but uses the textStyle attribute to set a different font for normal, bold, or italic styles. The constructor has a check for the textStyle which sets the font.

MyFontTextView.java

public MyFontTextView(Context context, AttributeSet attrs) {
  int textStyle = attrs.getAttributeIntValue(ANDROID_SCHEMA, "textStyle", Typeface.NORMAL);
  switch (textStyle) {
    case Typeface.BOLD: // bold
      Typeface boldFont = Typeface.createFromAsset(Application.getContext().getAssets(), "fonts/boldFont.otf");
      super.setTypeface(boldFont);
    ...
  }
}

The problem is that if I set the textStyle in an inherited style, it DOES NOT detect it and getAttributeIntValue(ANDROID_SCHEMA, "textStyle", Typeface.NORMAL) always returns my default Typeface.NORMAL:

<style name="TextView_MyInfo">
    <item name="android:textStyle">bold</item>
    <item name="android:textAllCaps">true</item>
</style>

myfragment.xml

<com.myapp.views.MyFontTextView
  android:id="@+id/myinfo_name"
  style="@style/TextView_MyInfo"
  tools:text="John Smith" />

DOESN'T SET BOLD.

But if I instead set the textStyle directly on the element like this:

<com.myapp.views.MyFontTextView
  android:id="@+id/myinfo_name"
  android:textStyle="bold"
  tools:text="John Smith" />

it DOES detect it and getAttributeIntValue(ANDROID_SCHEMA, "textStyle", Typeface.NORMAL) returns Typeface.BOLD just as it should. I also know that it IS loading the styles.xml properties correctly because it always gets the textAllCaps attribute, along with a few others.

Do I need to be accessing the attributes set in styles.xml differently than directly set attributes?

Based on this answer, if I can at least get the style tag set with style="@style/TextView_MyInfo", I could use that to check for textStyle defined there as well.

Other Info:

  • compileSdkVersion 23
  • minSdkVersion 19
  • targetSdkVersion 22
ScottyC
  • 1,467
  • 1
  • 15
  • 22
  • 2
    Have u got answer of this issue? I am also facing same problem. – Mubarak Apr 12 '17 at 05:15
  • No unfortunately I never did. I'm assuming it's a bug of some sort. I just had to work around the issue. Ultimately we went a different route entirely. Instead of using a custom text view class, we use the regular Android text view and inject the font using data binding with a BindingAdapter: https://developer.android.com/reference/android/databinding/BindingAdapter.html – ScottyC Apr 12 '17 at 22:05
  • Thanks for your quick and valuable reply. Shall i get small peace of code to achieve goal?. In case of textStyle what I have to do?. – Mubarak Apr 14 '17 at 10:10

1 Answers1

1

I'm facing this issue too, although it's 2022 and android12+. The reason is:

it cannot convert style into exactly attr in the constructor function.

Here is my style in style.xml:

    <style name="CustomBText">
        <item name="android:textStyle">bold</item>
        <item name="android:textSize">15sp</item>
    </style>
    class MyTextView : AppCompatTextView {
    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        checkBoldAndSetFont(context, attrs)
    }

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        checkBoldAndSetFont(context, attrs)
    }

    fun checkBoldAndSetFont(cxt: Context, attrs: AttributeSet?) {
        var textStyle = -1
    attrs?.let {
        textStyle = it.getAttributeIntValue(
            "http://schemas.android.com/apk/res/android",
            "textStyle",
            -1
        )
        if (textStyle == -1) {
            val sid = it.getAttributeResourceValue(null, "style", 0) //same as: attrs?.getStyleAttribute()
            if (sid != 0) {
                val styleName = cxt.resources.getResourceEntryName(sid)
                if (styleName == "CustomBStyle" || styleName.contains("BText")) {
                    textStyle = 1
                }
            }
        }
    }

    var isBold = textStyle == 1
        
    }

So, as my workaround, I'll check the getResourceEntryName's styleName contains "BStyle". Of course you can study more deep and find another way.

allan
  • 31
  • 2