Kaynaklardaki bir dizeyi XML'deki dinamik bir değişkenle birleştirmek için veri bağlamayı nasıl kullanabilirim?


125

Kodlanmış bir dizeye sahip bir TextView var ve bu dizenin sonuna koymak istediğim bir dinamik değişkenim var. Bu benim kodum:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp">
    <TextView
        android:id="@+id/PeopleName"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/Generic_Text"+"@{ Profile.name }" />


</LinearLayout>

İle ilgili bir sorun yaşıyorum android:text="@string/Generic_Text"+"@{ Profile.name }". Generic_TextDevletler ardından "Benim adıdır" Profile.namedinamiktir ve açıkçası profiline profilinden değiştirir. Tüm TextView çıktısının Benim Adım {Profile.name} olmasını istiyorum . Herhangi bir yardım harika olur.


Veri bağlama kullanıyor musunuz?
malmling

Evet veri bağlamayı kullanıyorum
Ignacio Perez

Lütfen mevcut java kodunuzu da ekleyin.
malmling

Yanıtlar:


162

Bunu yapabilirsiniz:

android:text= "@{String.format(@string/Generic_Text, Profile.name)}"

dizeniz için dize biçimlendirmesi kullanıyorsanız Generic_Text. ex. %ssonunda


Çok teşekkürler, sadece onu yerleştirdim ve doğru çalıştı
Ignacio Perez

5
Metni işlemek için aslında Veri bağlama özelliklerini kullanmadığından, bu kabul edilen yanıt olmamalıdır.
Darwind

1
bakınız, @Darwind katılıyorum benim cevap Adaptörleri Bağlama ile bir çalışma uygulanması için
juanagui

@IgorGanapolsky bu cevap 3 yaşın üzerinde ama kesinlikle daha önce çalışıyordu - denediğinizde neyin yanlış gittiğini hatırlıyor musunuz?
C0D3LIC1OU5

320

Bunu daha da basit bir şekilde yapabilirsiniz:

android:text= "@{@string/generic_text(profile.name)}"

dizenin şöyle olmalı:

<string name="generic_text">My Name is %s</string>

Düzenle:

  1. Elbette ihtiyacınız olduğu kadar çok değişken kullanabilirsiniz:

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
  2. Sadece veri bağlamada tasarlandığı için çalışır. Dokümanlarda daha fazlası: https://developer.android.com/topic/libraries/data-binding/expressions#resources


1
ancak My Name is nullverilerin henüz hazır olup olmadığını gösterir (örneğin, ağdan yüklenmemişse)
user924

1
Bu durumda daha önce kontrol edin. android:text= "@{profile == null ? @string/loading : @string/generic_text(profile.firstName, profile.secondName)}"
Roman_D

Bu yardımcı olur!
akash89

En iyi cevap :)
Heriberto Rivera

55

Dizeleri birleştirmenin birçok yolu

1. Dize kaynağını kullanma ( Yerelleştirme nedeniyle önerilir )

android:text= "@{@string/generic_name(user.name)}"

Sadece böyle bir dize kaynağı yapın.

<string name="generic_name">Hello %s</string>

2. Sabit kodlu concat

android:text="@{`Hello ` + user.name}"/>

Bu, telefon numarası için + gibi kodlanmış eke ihtiyacınız olduğunda kullanışlıdır.

3. Stringconcat yöntemini kullanma

android:text="@{user.firstName.concat(@string/space).concat(user.lastName)}"

İşte spaceiçine yerleştirilmiş bir html varlığı strings.xml. Çünkü XMLHtml varlıklarını veya özel karakterleri doğrudan kabul etmez. (Html ​​Varlıklarını Bağla)

<string name="space">\u0020</string>

4. kullanma String.format()

android:text= "@{String.format(@string/Hello, user.name)}"

String sınıfını bu tipte layout'ta içe aktarmanız gerekir.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="String" />
    </data>
    <TextView
        android:text= "@{String.format(@string/Hello, user.name)}"
        ... >
    </TextView>
</layout>

5. İki dizgeyi dizge kaynağına göre birleştirin.

android:text="@{@string/generic_name(user.firstName,user.lastName)}"

Bu durumda bir string kaynağı koyun strings.xml

<string name="generic_name">%1$s, %2$s</string>

Başka birçok yol olabilir, ihtiyacınız olan birini seçin.


5

Bir Bağlama Adaptörü kullanın .

Bu örnek Kotlin'de yazılmıştır ve bağlı değişkenin boş olabileceğini hesaba katar:

@BindingAdapter("my_name")
fun TextView.setMyName(name: String?) {
    this.text =
        if (name.isNullOrEmpty()) "" else "${this.context.getString(R.string.Generic_Text)} $name"
}

sonra android:textözellik yerine XML'inizdeki bağlama bağdaştırıcısını kullanın

app:my_name="@{Profile.name}"

Bağlamada içe aktarılan işlevleri çağırırken çok fazla sorun yaşıyorum, bu yanıt benim için mükemmel çalışıyor ve uzantılarımı yeniden kullanmama izin veriyor. Teşekkürler!
Danny Buonocore

Temel manipülasyon zaten Stringsınıf tarafından sağlandığından xml, bu çözüm yalnızca gereksinimlerinize bağlı olarak gelişmiş String manipülasyonları için kullanılabilir. Ancak yanlış değildir.
sud007

3

2019 Güncellemesi, Android stüdyosu 3.4'e, Android Gradle Eklentisi 3.4'e

İçe aktarmaya daha fazla gerek yok

<import type="java.lang.String" />" 

dize işlemleri için. Lütfen bu yanıtı kontrol edin .


1

Eğer olamaz içerecek şekilde kaynak dizesini değiştirmek %ssonunda (örneğin o eki olmadan başka yerlerde kullanıldığından.):

android:text="@{@string/Generic_Text.concat(Profile.name)}"

Eğer Profile.namenull olamaz, bu kadar yeter. Ancak, bir nullolursa, çökecektir. Başka bir katman eklemelisiniz:

android:text="@{@string/Generic_Text.concat(Objects.toString(Profile.name))}"

( <import type="java.util.Objects"/>çalışmayı gerektirir .)

Yine: tüm bu fazladan çalışma, yalnızca başka bir yerde kullanılan kaynak dizesine sahipseniz buna değer. İkinci neden, null"boş" değişmez değeri yerine "boş dize" olarak işlem yapmak istediğiniz zamandır.


2
Dize kaynağı başka bir yerde kullanılıyorsa, neden sadece yeni bir kaynak yapılmasın?
Jarett Millard

0

İsterseniz durumda metni yazın XML, kullanabileceğiniz `` tırnak.

android:text="@{`Device Name`}"

String veya değişken ile Concat yapmanız gereken başka bir yerde , kullanabilirsiniz

android:text="@{`Device Name`.concat(android.os.Build.MANUFACTURER)}"

İstersen Concat dize kaynağı yerine yapabileceğiniz değişkenin,

android:text="@{@string/app_name.concat(`Device Name`)}"

0

Sadece +operatör kullanmak benim için çalışıyor:

android:text= "@{@string/Generic_Text +' '+ Profile.name)}"

String.xml şöyle olacaktır:

<string name="Generic_Text">Hello</string>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.