So rufen Sie Stilattribute programmgesteuert aus der Datei styles.xml ab

81

Derzeit verwende ich entweder eine WebView oder eine TextView, um einige dynamische Daten anzuzeigen, die von einem Webservice in einer meiner Apps stammen. Wenn die Daten reinen Text enthalten, wird die Textansicht verwendet und ein Stil aus der Datei styles.xml angewendet. Wenn die Daten HTML enthalten (hauptsächlich Text und Bilder), wird WebView verwendet.

Dieses WebView ist jedoch nicht formatiert. Daher sieht es ganz anders aus als die übliche TextView. Ich habe gelesen, dass es möglich ist, den Text in einer WebView zu formatieren, indem einfach HTML direkt in die Daten eingefügt wird. Das hört sich einfach an, aber ich möchte die Daten aus meiner Styles.xml als die in diesem HTML erforderlichen Werte verwenden, damit ich die Farben usw. nicht an zwei Stellen ändern muss, wenn ich meine Stile ändere.

Wie könnte ich das tun? Ich habe einige umfangreiche Suchvorgänge durchgeführt, aber ich habe keine Möglichkeit gefunden, die verschiedenen Stilattribute tatsächlich aus Ihrer styles.xml abzurufen. Vermisse ich hier etwas oder ist es wirklich nicht möglich, diese Werte abzurufen?

Der Stil, aus dem ich die Daten abrufen möchte, ist folgender:

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

Ich interessiere mich hauptsächlich für textSize und textColor.

Sander van't Veer
quelle
Warum analysieren Sie nicht einfach das XML (z. B. den SAX-Parser von Android)?
m0skit0

Antworten:

174

Es ist möglich, benutzerdefinierte Stile styles.xmlprogrammgesteuert abzurufen .

Definieren Sie einen beliebigen Stil in 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>

Rufen Sie nun die Stile wie folgt ab

// 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
quelle
Super Arbeitskollege. Nachdem Ihnen gesagt wurde (und viel gelesen wurde), dass dies nicht möglich ist, haben Sie perfekt gezeigt, dass dies möglich ist. Ich habe es gerade ausprobiert und konnte die Schriftfarbe aus meinem Stil herausholen. Ich kann die Textgröße noch nicht ganz bekommen, aber ich werde es herausfinden. 100 Punkte kommen auf dich zu, sobald ich das Kopfgeld senden kann (in 18 Stunden). Danke vielmals!
Sander van't Veer
4
Ist es auch möglich, die zur Laufzeit stilistisch definierten Werte zu ändern?
Ekjyot
Was ist, wenn ich die Farbe der abgerufenen Attribute ändern möchte? Möchten Sie den Hintergrund oder die Textfarbe in diesem Code dynamisch ändern?
MSIslam
2
Ich habe ein Problem mit dieser Zeile: 'TypedArray ta = getStyledAttributes (R.style.MyCustomStyle, attrs);' Unterstützungsbibliothek. Ich gehe davon aus, dass getStyledAttributes eine @ ResStyleable-Annotation hat, die verhindert, dass ich einen Stil als int durchlaufe. Irgendwelche Ideen?
Ben Pearson
1
@ BenPearson - Ich hatte das gleiche Problem wie Sie beim Versuch, das textSize-Attribut abzurufen. Die Antwort von PrivatMamtora funktioniert und sollte die akzeptierte Antwort sein.
Thecoolmacdude
51

Die Antwort, die @Ole gegeben hat, scheint zu brechen, wenn bestimmte Attribute wie shadowColor, shadowDx, shadowDy, shadowRadius verwendet werden (dies sind nur einige, die ich gefunden habe, möglicherweise gibt es mehr).

Ich habe keine Ahnung, warum dieses Problem auftritt, worüber ich hier frage , aber der Codierungsstil @AntoineMarques scheint das Problem zu lösen.

Damit dies mit einem beliebigen Attribut funktioniert, wäre es ungefähr so


Definieren Sie zunächst ein Stylable, das die Ressourcen-IDs wie folgt enthält

attrs.xml

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

Dann würden Sie dies im Code tun, um den Text zu erhalten.

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

Der Vorteil dieser Methode besteht darin, dass Sie den Wert anhand des Namens und nicht anhand eines Index abrufen.

PrivatMamtora
quelle
3
Dies sollte die akzeptierte Antwort sein, da Oles Antwort eine Warnung "Erwartete Ressource vom Typ stilisierbar" für mich generiert hat.
Thecoolmacdude
1
Funktioniert für mich, aber mit Android Studio muss ich dem ein voranstellen @SuppressWarnings("ResourceType").
Eruve
2
Diese Antwort sollte akzeptiert werden. Es ist Arbeit für alle meine Attribute, und der am meisten gewählte hat mir viel Zeit verschwendet.
Jerry
1
Vielen Dank an den mächtigen Delphin für Ihre Lösung. Die akzeptierte Antwort verursachte für mich Probleme mit Attributen wie Hintergrund (bei Verwendung von Zeichen) und Textgröße. Diese Lösung funktioniert nicht nur für alle Attribute, die ich benötige, sondern liefert auch einen saubereren Code.
Marius P.
2
Was soll R.style.MyCustomStyle sein?
Janosch
0

Die Antworten von Ole und PrivatMamtora haben bei mir nicht gut funktioniert, aber das hat funktioniert.

Angenommen, ich wollte diesen Stil programmatisch lesen:

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

Ich könnte es so machen:

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

Ich habe mich von der TextAppearanceSpan-Klasse von Android inspirieren lassen. Sie finden sie hier: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/style/TextAppearanceSpan.java

janosch
quelle
-3

Wenn die akzeptierte Lösung nicht funktioniert, versuchen Sie, attr.xml in attrs.xml umzubenennen (hat bei mir funktioniert)

Юра Перменко
quelle