自定义TextView无法从styles.xml文件中获取textStyle属性

4
我有一个自定义的TextView,基本上实现方式与这篇博客文章中的相同,它默认使用某种字体,但使用textStyle属性来设置普通、粗体或斜体风格的不同字体。 构造函数检查textStyle并设置字体。

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);
    ...
  }
}

问题是,如果我在继承的 style 中设置了 textStyle,它不会被检测到,getAttributeIntValue(ANDROID_SCHEMA, "textStyle", Typeface.NORMAL) 总是返回我的默认值 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" />

不设置粗体。

但是如果我直接在元素上设置textStyle,像这样:

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

它确实检测到了,并且getAttributeIntValue(ANDROID_SCHEMA, "textStyle", Typeface.NORMAL)返回的是Typeface.BOLD,这正如它应该的那样。我也知道它正确地加载了styles.xml属性,因为它总是获取textAllCaps属性以及其他一些属性。

我需要以不同于直接设置属性的方式访问在styles.xml中设置的属性吗?

根据这个答案,如果我至少可以得到用style="@style/TextView_MyInfo"设置的样式标签,我可以使用它来检查是否在那里定义了textStyle

其他信息:

  • compileSdkVersion 23
  • minSdkVersion 19
  • targetSdkVersion 22

2
你解决了这个问题吗?我也遇到了同样的问题。 - Mubarak
很遗憾,我从未解决过这个问题。我猜测这是某种错误。我只能绕过这个问题。最终,我们采用了完全不同的方法。我们没有使用自定义文本视图类,而是使用常规的Android文本视图,并使用数据绑定和BindingAdapter注入字体:https://developer.android.com/reference/android/databinding/BindingAdapter.html - ScottyC
感谢您的快速和有价值的回复。我可以得到一小段代码来实现目标吗?在textStyle的情况下,我该怎么做? - Mubarak
1个回答

1

我也遇到了这个问题,尽管现在已经是2022年且使用的是Android 12+。

原因是:

构造函数无法将样式准确地转换为属性。

以下是我的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
        
    }


所以,我的解决方法是,我会检查getResourceEntryName的styleName是否包含“BStyle”。 当然,您也可以深入研究并找到其他方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接