Як отримати програмні атрибути стилю програмно з styles.xml


82

В даний час я використовую або WebView, або TextView, щоб показати деякі динамічні дані, що надходять від веб-служби в одному з моїх програм. Якщо дані містять чистий текст, вони використовують TextView і застосовують стиль із styles.xml. Якщо дані містять HTML (переважно текст та зображення), вони використовують WebView.

Однак цей WebView є нестильовим. Тому це виглядає набагато інакше, ніж звичайний TextView. Я читав, що можна стилізувати текст у WebView, просто вставляючи трохи HTML безпосередньо в дані. Це звучить досить просто, але я хотів би використовувати дані з мого 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.


Чому б вам просто не проаналізувати XML (наприклад, синтаксичний аналізатор SAX для Android)?
m0skit0

Відповіді:


177

Можна отримати користувацькі стилі із 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()

Чудовий колега по роботі. Після того, як вам сказали (і багато читали), що цього зробити неможливо, ви чудово показали, що можете. Просто спробував, і я зміг отримати колір шрифту за своїм стилем. Поки що не можу отримати розмір тексту, але я розберуся. Як тільки я зможу надіслати нагороду (100 годин відтепер), вам належить 100 очок. Дуже дякую!
Sander van't Veer

4
чи можна також змінити значення, визначені у стилі під час виконання?
ekjyot

Що робити, якщо я хочу змінити колір отриманих атрибутів? Як динамічна зміна кольору фону або тексту в цьому коді?
MSIslam

2
У мене проблема з цим рядком: 'TypedArray ta = getStyledAttributes (R.style.MyCustomStyle, attrs);', студія Android каже мені, що вона очікує ресурс типу styleable, і я не бачу жодного способу придушити анотації в бібліотека підтримки. Я припускаю, що отриматиStyledAttributes має анотацію @ResStyleable, яка заважає мені передавати стиль як int. Будь-які ідеї?
Бен Пірсон,

1
@BenPearson - У мене була та ж проблема, що і у вас при спробі отримати атрибут textSize. Відповідь PrivatMamtora працює і повинна бути прийнятою відповіддю.
thecoolmacdude

52

Відповідь, яку дав @Ole, здається, порушується при використанні певних атрибутів, таких як shadowColor, shadowDx, shadowDy, shadowRadius (це лише декілька, які я знайшов, може бути і більше)

Я поняття не маю, чому виникає ця проблема, про яку я тут запитую , але стиль кодування @AntoineMarques, схоже, вирішує проблему.

Щоб зробити цю роботу з будь-яким атрибутом, це було б приблизно так


По-перше, визначте стиль, який міститиме такі ідентифікатори ресурсів

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

Перевага використання цього методу полягає в тому, що ви отримуєте значення за іменем, а не за індексом.


3
Це має бути прийнятою відповіддю, оскільки відповідь Оле породила для мене попередження про "очікуваний ресурс із стилем"
thecoolmacdude

1
Працює у мене, але в Android Studio мені потрібно додавати префікс до @SuppressWarnings("ResourceType").
eruve

2
Ця відповідь повинна бути прийнятою. Це робота на весь мій атрибут, і найбільш обраний витратив мені багато часу.
джеррі

1
Подякуйте могутньому дельфіну за ваше рішення. Прийнята відповідь створила для мене проблеми з такими атрибутами, як фон (при використанні, що малюється) та розмір тексту. Це рішення не тільки працює для всіх потрібних мені атрибутів, але також дає чистіший код.
Маріус П.

2
Яким повинен бути R.style.MyCustomStyle?
janosch

1

Відповіді Оле та ПриватМамтора мені не вдались, але це зробило.

Скажімо, я хотів прочитати цей стиль програмно:

<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()
}

Я надихнувся класом TextAppearanceSpan для Android, ви можете знайти його тут: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/style/TextAppearanceSpan.java


-4

Якщо прийняте рішення не працює, спробуйте перейменувати attr.xml в attrs.xml (спрацювало для мене)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.