Bagaimana cara menggunakan penyatuan data untuk menggabungkan string dari sumber daya dengan variabel dinamis dalam XML?

125

Saya memiliki TextView yang memiliki string hardcode dan saya memiliki variabel dinamis yang ingin saya tempatkan di akhir string ini. Ini kode saya:

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

Saya mengalami masalah dengan android:text="@string/Generic_Text"+"@{ Profile.name }". The Generic_Textnegara "Nama saya adalah" maka Profile.nameadalah dinamis dan jelas perubahan dari profil ke profil. Saya menginginkannya sehingga seluruh output TextView adalah My Name is {Profile.name} . Bantuan apa pun akan sangat bagus.

Ignacio Perez
sumber
Apakah Anda menggunakan penyatuan data?
malmling
Ya, saya menggunakan penyatuan data
Ignacio Perez
Tambahkan juga kode java Anda saat ini.
malmling

Jawaban:

162

Kamu bisa melakukan ini:

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

jika Anda menggunakan pemformatan string untuk Generic_Textstring Anda . ex. %spada akhirnya

C0D3LIC1OU5
sumber
Terima kasih banyak, saya baru saja memasukkannya dan berfungsi dengan benar
Ignacio Perez
5
Ini seharusnya bukan jawaban yang diterima, karena ini sebenarnya tidak menggunakan fitur Data binding untuk memanipulasi teks.
Darwind
1
setuju dengan @Darwind, silakan lihat jawaban saya untuk implementasi yang berfungsi dengan Binding Adapters
juanagui
@IgorGanapolsky jawaban ini sudah lebih dari 3 tahun tetapi pasti pernah digunakan sebelumnya - apakah Anda ingat apa yang salah ketika Anda mencobanya?
C0D3LIC1OU5
320

Anda dapat melakukan ini dengan lebih sederhana:

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

Anda string harus seperti ini:

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

Edit:

  1. Tentu saja Anda dapat menggunakan variabel sebanyak yang Anda butuhkan:

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
  2. Ini berfungsi hanya karena dirancang dalam pengikatan data. Selengkapnya di dokumen: https://developer.android.com/topic/libraries/data-binding/expressions#resources

Roman_D
sumber
1
tetapi ini menunjukkan My Name is nulljika data belum siap (mis. tidak dimuat dari jaringan)
user924
1
Dalam hal ini periksa saja sebelumnya. android:text= "@{profile == null ? @string/loading : @string/generic_text(profile.firstName, profile.secondName)}"
Roman_D
Ini sangat membantu!
akash89
Jawaban terbaik :)
Heriberto Rivera
55

Banyak cara untuk menggabungkan string

1. Menggunakan sumber daya string ( Disarankan karena Lokalisasi )

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

Buat saja sumber daya string seperti ini.

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

2. Concat kode keras

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

Ini berguna ketika Anda membutuhkan penambahan hardcode seperti + untuk nomor telepon.

3. Menggunakan Stringmetode concat

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

Berikut spaceadalah entitas html yang ditempatkan di dalamnya strings.xml. Karena XMLtidak menerima entitas Html atau karakter khusus secara langsung. (Tautkan Entitas Html)

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

4. Menggunakan String.format()

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

Anda harus mengimpor kelas String dalam tata letak dalam tipe ini.

<?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. menggabungkan dua string dengan sumber daya string.

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

Dalam hal ini, masukkan sumber daya string strings.xml

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

Ada banyak cara lain, pilih salah satu yang Anda butuhkan.

Khemraj
sumber
5

Gunakan Adaptor Binding .

Contoh ini ditulis di Kotlin dan memperhitungkan bahwa variabel terikat bisa jadi null:

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

lalu gunakan adaptor binding di XML Anda, bukan di android:textproperti

app:my_name="@{Profile.name}"
juanagui
sumber
Telah mengalami banyak masalah dalam memanggil fungsi yang diimpor dalam penjilidan, jawaban ini bekerja dengan sempurna untuk saya dan memungkinkan saya untuk menggunakan kembali ekstensi saya. Terima kasih!
Danny Buonocore
Karena, manipulasi dasar sudah disediakan oleh Stringkelas dari xml, solusi ini hanya bagus untuk digunakan untuk manipulasi String lanjutan berdasarkan kebutuhan Anda. Namun, itu tidak salah.
sud007
3

Pembaruan 2019, Android studio ke 3.4, Android Gradle Plugin ke 3.4

Tidak perlu lagi mengimpor

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

untuk operasi string. Silakan periksa jawaban ini .

SANAT
sumber
1

Jika Anda tidak dapat mengubah string sumber daya menjadi berisi %sdi akhir (misalnya karena digunakan di tempat lain tanpa sufiks):

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

Jika Profile.nametidak bisa nol, itu sudah cukup. Namun, jika nullterjadi, itu akan macet. Anda harus menambahkan lapisan lain:

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

(yang membutuhkan <import type="java.util.Objects"/>kerja.)

Sekali lagi: semua pekerjaan tambahan ini sepadan hanya jika Anda memiliki string sumber daya yang digunakan di tempat lain. Alasan kedua adalah ketika Anda ingin menangani nullsebagai "string kosong", bukan literal "null".

Agent_L
sumber
2
Jika sumber daya string digunakan di tempat lain, mengapa tidak membuat sumber daya baru saja?
Jarett Millard
0

Jika Anda ingin mengetik teks dalam XML, Anda dapat menggunakan `` kutipan.

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

di tempat lain Anda perlu Concat dengan String atau variabel , Anda dapat menggunakan

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

jika Anda ingin menggabungkan sumber daya string daripada variabel yang bisa Anda lakukan,

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

Hanya menggunakan +operator berfungsi untuk saya:

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

String.xml akan menjadi:

<string name="Generic_Text">Hello</string>
Shalu TD
sumber