Como uso a ligação de dados para combinar uma sequência de recursos com uma variável dinâmica em XML?


125

Eu tenho um TextView que possui uma string codificada e uma variável dinâmica que eu quero colocar no final dessa string. Este é o meu código:

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

Estou tendo um problema com android:text="@string/Generic_Text"+"@{ Profile.name }". Os Generic_Textestados "Meu nome é" então Profile.nameé dinâmico e obviamente muda de perfil para perfil. Quero que toda a saída do TextView seja My Name seja {Profile.name} . Qualquer ajuda seria ótimo.


Você está usando ligação de dados?
malmling

Sim, eu estou usando ligação de dados
Ignacio Perez

Adicione seu código java atual também, por favor.
malmling

Respostas:


162

Você consegue fazer isso:

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

se você usar a formatação de sequência para sua Generic_Textsequência. ex. %sno fim


Muito obrigado Acabei de colocar isso em e funcionou corretamente
Ignacio Perez

5
Essa não deve ser a resposta aceita, pois na verdade não usa os recursos de vinculação de dados para manipular o texto.
Darwind

1
Concordo com @Darwind, consulte minha resposta para uma implementação de trabalho com adaptadores de Encadernação
juanagui

@IgorGanapolsky, esta resposta tem mais de 3 anos, mas definitivamente costumava funcionar antes - você se lembra do que deu errado quando tentou?
C0D3LIC1OU5

320

Você pode fazer isso ainda mais simples:

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

sua string deve ser assim:

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

Editar:

  1. Obviamente, você pode usar quantas variáveis ​​precisar:

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
  2. Funciona apenas porque foi projetado na ligação de dados. Mais em documentos: https://developer.android.com/topic/libraries/data-binding/expressions#resources


1
mas mostra My Name is nullse os dados ainda não estão prontos (por exemplo, não foram carregados da rede)
user924

1
Nesse caso, basta verificar antes. android:text= "@{profile == null ? @string/loading : @string/generic_text(profile.firstName, profile.secondName)}"
Roman_D

Isso é útil!
Akash89 17/10/19

A melhor resposta :)
Heriberto Rivera

55

Muitas maneiras de concatenar strings

1. Usando o recurso de string ( recomendado porque localização )

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

Basta criar recursos de string como este.

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

2. Concat codificado

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

Isso é útil quando você precisa acrescentar código codificado como + para o número de telefone.

3. Usando Stringo método concat

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

Aqui spaceestá uma entidade html que é colocada dentro strings.xml. Porque XMLnão aceita entidades Html ou caracteres especiais diretamente. (Vincular entidades HTML)

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

4. Usando String.format()

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

você precisa importar a classe String no layout desse tipo.

<?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. concatize duas strings por recurso de string.

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

Nesse caso, coloque um recurso de string em strings.xml

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

Pode haver muitas outras maneiras, escolha uma que você precisa.


5

Use um adaptador de ligação .

Este exemplo é escrito em Kotlin e leva em consideração que a variável vinculada pode ser nula:

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

em seguida, use o adaptador de ligação em seu XML em vez da android:textpropriedade

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

Tendo tido muitos problemas para chamar funções importadas na ligação, esta resposta funciona perfeitamente para mim e me permite reutilizar minhas extensões. Obrigado!
Danny Buonocore 20/03

Como a manipulação básica já é fornecida pela Stringclasse from xml, essa solução só é boa para ser usada em manipulações avançadas de String com base em seus requisitos. No entanto, não está incorreto.
sud007 26/04

3

Atualização de 2019, Android studio para 3.4, Android Gradle Plugin para 3.4

Não é mais necessário importar

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

para operações de string. Por favor, verifique esta resposta .


1

Caso você não possa alterar a cadeia de recursos a conter %sno final (por exemplo, porque é usada em outro lugar sem o sufixo):

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

Se Profile.namenão puder ser nulo, basta. No entanto, se nullacontecer, ele travará. Você precisa adicionar outra camada:

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

(o que requer <import type="java.util.Objects"/>trabalho.)

Novamente: todo esse trabalho extra vale a pena apenas se você tiver a cadeia de recursos usada em outro lugar. O segundo motivo é quando você deseja manipular nullcomo "cadeia vazia" em vez de um literal "nulo".


2
Se o recurso de cadeia de caracteres for usado em outro lugar, por que não criar um novo recurso?
Jarett Millard

0

Caso deseje digitar texto em XML, use `` quote.

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

em qualquer outro lugar em que você precise Concat com a String ou a variável , você pode usar

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

se você quiser Concat o recurso de string em vez da variável que você pode fazer,

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

0

Apenas usar o +operador funciona para mim:

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

String.xml será:

<string name="Generic_Text">Hello</string>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.