DataBinding: Wie erhalte ich Ressourcen nach dynamischer ID?

Lesezeit: 5 Minuten

Benutzer-Avatar
Dmitri Zaytsev

Ich weiß, dass es möglich ist, Ressourcen im Layout anhand ihrer Ressourcen-ID zu referenzieren:

android:text="@{@string/resourceName}"

Ich möchte jedoch auf die Ressource anhand der ID verweisen, die nur zur Laufzeit bekannt ist. Stellen Sie sich als einfaches Beispiel vor, wir hätten ein solches Modell:

public class MyPOJO {

    public final int resourceId = R.string.helloWorld;

}

Und jetzt muss ich diesen Wert als Wert in einer Formatzeichenfolge verwenden. Nennen wir es

<string name="myFormatString">Value is: %s</string>

Der einfachste Ansatz funktioniert nicht:

android:text="@{@string/myFormatString(myPojo.resourceId)}"

Dadurch wird nur ein ganzzahliger Wert in den Platzhalter eingefügt (es beweist auch, dass ich mein POJO korrekt initialisiert habe, daher stelle ich hier nicht das gesamte Layout bereit).

Ich habe es auch mit versucht @BindingConversionaber es hat nicht funktioniert (was eigentlich erwartet wird, aber ich habe es trotzdem versucht) – int noch dem Platzhalter zugewiesen und die Bindungsmethode wurde nicht aufgerufen.

Wie kann ich eine Ressource explizit anhand ihrer ID in der DataBinding-Bibliothek abrufen?

Eine andere Lösung besteht darin, eine benutzerdefinierte Datei zu erstellen @BindingAdapter dafür.

@BindingAdapter({"format", "argId"})
public static void setFormattedText(TextView textView, String format, int argId){
    if(argId == 0) return;
    textView.setText(String.format(format, textView.getResources().getString(argId)));
}

Und dann geben Sie die Variablen einfach separat an.

<TextView
    app:format="@{@string/myFormatString}"
    app:argId="@{myPojo.resourceId}"

Sie könnten ein Array verwenden, wenn Sie mehrere Argumente benötigen, aber in meinem Fall war eines ausreichend.

  • Dies sollte als die richtige Antwort angegeben werden, da es am prägnantesten ist.

    – Adam Hurwitz

    5. September 2019 um 23:32 Uhr

Ab Juni 2016 ist dies in XML möglich:

android:text= "@{String.format(@string/my_format_string, myPojo.resourceId)}"

  • Ich habe momentan keine Möglichkeit, es zu versuchen, also nur zur Bestätigung – wird es die Zeichenfolge für die angegebene Ressourcen-ID oder ID selbst als einfügen int?

    – Dmitri Zaytsev

    27. Juni 2016 um 11:16 Uhr

  • Es gibt die Ressourcen-ID zurück

    – Robust

    11. August 2017 um 7:02 Uhr


  • Seltsamerweise scheint es nicht zu funktionieren (stiller Kompilierungsfehler), wenn ich stattdessen eine meiner eigenen Methoden verwende String.formatobwohl es mit derselben Methode gut kompiliert wird, wenn ich anstelle von eine ganze Zahl fest codiere @string/my_format_string. Am Ende habe ich die String-Ersetzung in den Kotlin-Code verschoben und einfach den fertigen String übergeben.

    – big_m

    18. August 2020 um 14:20 Uhr


Benutzer-Avatar
Dalvinder Singh

Sie können Folgendes verwenden:

android:text="@{(id > 0) ? context.getString(id) : ""}"

  • und wie ipcjs oben sagte, der Kontext ist da, es besteht keine Notwendigkeit zu importieren, und wenn die Ressourcenzeichenfolge referenziert werden muss, verwenden Sie ‘@string/flight_departures’ innerhalb der Datenbindung wie gewohnt, siehe developer.android.com/topic/libraries/data-binding/expressions

    – Arberg

    15. April 2019 um 14:45 Uhr

Am Ende habe ich meine eigene Methode entwickelt:

public class BindingUtils {

    public static String string(int resourceId) {
        return MyApplication
                .getApplication()
                .getResources()
                .getString(resourceId);
    }

}

Einen Import dafür deklarieren:

<data>

    <import type="com.example.BindingUtils" />

    ...

</data>

Und rufen Sie es einfach während des Bindens auf:

android:text="@{@string/myFormatString(BindingUtils.string(myPojo.resourceId))}"

Wäre schön, dafür eine Out-of-the-Box-Methode zu haben. DataBinding befindet sich noch in der Beta-Phase – vielleicht kommt es in Zukunft.

Eine andere Lösung, wenn Sie bereits Context in Ihrem XML definiert, dann werden Sie nicht importieren müssen String Klasse.

android:text="@{@string/myFormatString(context.getString(pojo.res))}"

wird für arbeiten

<string name="myFormatString">Value is: %s</string>

Wenn Sie keinen Kontext in Ihrer XML-Datei haben. dann folge diesem

<data>    
     <variable
         name="context"
         type="abc.UserActivity"/>

     <variable
         name="pojo"
         type="abc.MyPOJO"/>
 </data>

und in deinem Activity

ActivityUserBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_user);
binding.setPojo(new MyPOJO());
binding.setContext(this);

  • context vorhanden ist, muss nicht importiert werden

    – ipcjs

    12. September 2018 um 6:36 Uhr

Benutzer-Avatar
Sefa Keles

Sie können Gebrauch machen automatische Methodenauswahl in der offiziellen Dokumentation der Bindungsadapter beschrieben. Die folgende Beschreibung ist diesem Dokument entnommen:

Für ein Attribut namens exampleversucht die Bibliothek automatisch, die Methode zu finden setExample(arg) die kompatible Typen als Argument akzeptiert. Der Namensraum des Attributs wird nicht berücksichtigt, nur der Attributname und -typ werden verwendet, wenn nach einer Methode gesucht wird.

Zum Beispiel angesichts der android:text="@{user.name}" Ausdruck sucht die Bibliothek nach a setText(arg) Methode, die den von zurückgegebenen Typ akzeptiert user.getName(). Wenn der Rückgabetyp von user.getName() ist Stringsucht die Bibliothek nach a setText() Methode, die a akzeptiert String Streit. Wenn der Ausdruck eine zurückgibt int Stattdessen sucht die Bibliothek nach a setText() Methode, die ein akzeptiert int Streit. Der Ausdruck muss den richtigen Typ zurückgeben, Sie können den Rückgabewert bei Bedarf umwandeln.

Vor diesem Hintergrund können Sie Ihren eigenen Bindungsadapter implementieren, der die ID einer Zeichenfolgenressource als akzeptiert int Streit.

@BindingAdapter("android:text")
fun setText(view: TextView, @StringRes resId: Int) {
    if (resId == 0) {
        view.text = null
    } else {
        view.setText(resId)
    }
}

Dadurch können Sie den Standard verwenden android:text -Attribut, um auf eine Zeichenfolge anhand ihrer Ressourcen-ID sowie ihres Werts zu verweisen.

<TextView
    android:id="@+id/text_view_id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{myPojo.resourceId}" />

  • context vorhanden ist, muss nicht importiert werden

    – ipcjs

    12. September 2018 um 6:36 Uhr

Benutzer-Avatar
Momen Zaqout

Sie können den Kontext in Ihrem XML verwenden

 <TextView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text= "@{context.getString(myPojo.resourceId)}"
   />

1180180cookie-checkDataBinding: Wie erhalte ich Ressourcen nach dynamischer ID?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy