如何从styles.xml中以编程方式检索样式属性



目前我正在使用WebView或TextView来显示来自我的一个应用程序中的Web服务的一些动态数据。如果数据包含纯文本,则使用TextView并应用styles.xml中的样式。如果数据包含HTML(主要是文本和图像),则使用WebView。

但是,此WebView未设置样式。因此,它看起来与通常的TextView有很大不同。我读到过,只需在数据中直接插入一些HTML,就可以在WebView中设置文本样式。这听起来很简单,但我想使用Styles.xml中的数据作为该HTML中所需的值,这样如果我更改样式,就不需要更改两个位置的颜色等。

那么,我该怎么做呢?我做了一些广泛的搜索,但我没有找到从styles.xml中实际检索不同样式属性的方法。我是遗漏了什么,还是真的无法检索这些值?

我试图从中获取数据的样式如下:

<style name="font4">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">#E3691B</item>
<item name="android:paddingLeft">5dp</item>
<item name="android:paddingRight">10dp</item>
<item name="android:layout_marginTop">10dp</item>
<item name="android:textStyle">bold</item>
</style>

我主要对textSize和textColor感兴趣。

可以通过编程从styles.xml中检索自定义样式。

styles.xml:中定义一些任意样式

<style name="MyCustomStyle">
<item name="android:textColor">#efefef</item>
<item name="android:background">#ffffff</item>
<item name="android:text">This is my text</item>
</style>

现在,检索像这样的样式

// The attributes you want retrieved
int[] attrs = {android.R.attr.textColor, android.R.attr.background, android.R.attr.text};
// Parse MyCustomStyle, using Context.obtainStyledAttributes()
TypedArray ta = obtainStyledAttributes(R.style.MyCustomStyle, attrs);
// Fetch the text from your style like this.     
String text = ta.getString(2);
// Fetching the colors defined in your style
int textColor = ta.getColor(0, Color.BLACK);
int backgroundColor = ta.getColor(1, Color.BLACK);
// Do some logging to see if we have retrieved correct values
Log.i("Retrieved text:", text);
Log.i("Retrieved textColor as hex:", Integer.toHexString(textColor));
Log.i("Retrieved background as hex:", Integer.toHexString(backgroundColor));
// OH, and don't forget to recycle the TypedArray
ta.recycle()

@Ole给出的答案在使用某些属性时似乎会中断,如shadowColor、shadowDx、shadowDy、shadowRadius(这些只是我发现的少数,可能还有更多)

我不知道为什么会出现这个问题,我在这里问这个问题,但@AntoineMarques的编码风格似乎解决了这个问题。

要使它与任何属性一起工作,它将是这样的


首先,定义一个可包含资源id的样式,如so

attrs.xml

<resources>     
<declare-styleable name="MyStyle" >
<attr name="android:textColor" />
<attr name="android:background" />
<attr name="android:text" />
</declare-styleable>
</resources>

然后在代码中,你可以这样做来获得文本。

TypedArray ta = obtainStyledAttributes(R.style.MyCustomStyle, R.styleable.MyStyle);  
String text = ta.getString(R.styleable.MyStyle_android_text);

使用此方法的优点是,您是按名称而不是索引检索值。

我无法让早期的解决方案发挥作用。

我的风格是:

<style name="Widget.TextView.NumPadKey.Klondike" parent="Widget.TextView.NumPadKey">
<item name="android:textSize">12sp</item>
<item name="android:fontFamily">sans-serif</item>
<item name="android:textColor">?attr/wallpaperTextColorSecondary</item>
<item name="android:paddingBottom">0dp</item>
</style>

android的获取样式属性()。textSize给出字符串结果";12sp"然后我必须对其进行解析。对于android。R.attr.textColor它给出了一个资源文件的XML名称。这太麻烦了。

相反,我发现了一种使用ContextThemeWrapper的简单方法。

TextView sample = new TextView(new ContextThemeWrapper(getContext(), R.style.Widget_TextView_NumPadKey_Klondike), null, 0);

这给了我一个完全样式化的TextView来查询我想要的任何内容。例如:

float textSize = sample.getTextSize();

Ole和PrivateMamtora的回答对我来说并不奏效,但这确实奏效了。

假设我想以编程方式阅读这种风格:

<style name="Footnote">
<item name="android:fontFamily">@font/some_font</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/black</item>
</style>

我可以这样做:

fun getTextColorSizeAndFontFromStyle(
context: Context, 
textAppearanceResource: Int // Can be any style in styles.xml like R.style.Footnote
) {
val typedArray = context.obtainStyledAttributes(
textAppearanceResource,
R.styleable.TextAppearance // These are added to your project automatically.
)
val textColor = typedArray.getColorStateList(
R.styleable.TextAppearance_android_textColor
)
val textSize = typedArray.getDimensionPixelSize(
R.styleable.TextAppearance_android_textSize
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val typeface = typedArray.getFont(R.styleable.TextAppearance_android_fontFamily)
// Do something with the typeface...
} else {
val fontFamily = typedArray.getString(R.styleable.TextAppearance_fontFamily)
?: when (typedArray.getInt(R.styleable.TextAppearance_android_typeface, 0)) {
1 -> "sans"
2 -> "serif"
3 -> "monospace"
else -> null
}
// Do something with the fontFamily...
}
typedArray.recycle()
}

我从Android的TextAppearanceSpan类中获得了一些灵感,你可以在这里找到它:https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/style/TextAppearanceSpan.java

使用Kotlin,如果您在应用程序/库中包含androidx.core:core ktx库。。。

implementation("androidx.core:core-ktx:1.6.0") // Note the -ktx

您可以有以下任一项(需要回收TypedArray):

// Your desired attribute IDs
val attributes = intArrayOf(R.attr.myAttr1, R.attr.myAttr2, android.R.attr.text)
context.withStyledAttributes(R.style.MyStyle, attributes) {
val intExample = getInt(R.styleable.MyIntAttrName, 0)
val floatExample = getFloat(R.styleable.MyFloatAttrName, 0f)
val enumExample = R.styleable.MyEnumAttrName, MyEnum.ENUM_1 // See Note 1 below
// Similarly, getColor(), getBoolean(), etc.
}
context.withStyledAttributes(R.style.MyStyle, R.styleable.MyStyleable) {
// Like above
}
// attributeSet is provided to you like in the constructor of a custom view
context.withStyledAttributes(attributeSet, R.styleable.MyStyleable) {
// Like above
}

注1(感谢这个答案)

为了获得枚举值,您可以定义以下扩展函数:

internal inline fun <reified T : Enum<T>> TypedArray.getEnum(index: Int, default: T) =
getInt(index, -1).let { if (it >= 0) enumValues<T>()[it] else default }

注2

-ktx依赖项(如androidx.core:coreandroidx.core:core-ktx)之间的区别在于-ktx变体包括Kotlin的有用扩展函数。否则,它们是一样的。

此外,感谢Ole的回答

如果接受的解决方案不适用,请尝试将attr.xml重命名为attrs.xml(适用于我)

相关内容

  • 没有找到相关文章

最新更新