如何使用数据绑定将资源中的字符串与XML中的动态变量组合在一起?


125

我有一个TextView,它具有一个硬编码的字符串,并且有一个动态变量,我想将其放在该字符串的末尾。这是我的代码:

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

我有一个问题 android:text="@string/Generic_Text"+"@{ Profile.name }"。该Generic_Text州“我的名字是”,则Profile.name是动态的,显然从个人资料的更改配置文件。我想要它,以便整个TextView输出为My Name为{Profile.name}。任何帮助都会很棒。


您正在使用数据绑定吗?
malmling

是的,我正在使用数据绑定
Ignacio Perez

请同时添加您当前的Java代码。
Malmling

Answers:


162

你可以这样做:

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

如果您对Generic_Text字符串使用字符串格式。例如 %s在末尾


非常感谢,我只是把它放进去了,并且工作正常
Ignacio Perez

5
这不应该是公认的答案,因为它实际上并不使用数据绑定功能来操纵文本。
达尔文

1
同意@Darwind,请参阅我的绑定适配器有效实施方案的答案
juanagui

@IgorGanapolsky这个答案已有3年以上的历史了,但肯定是以前工作过-您还记得尝试时出了什么问题吗?
C0D3LIC1OU5 '19

320

您甚至可以执行以下操作:

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

您的字符串应如下所示:

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

编辑:

  1. 当然,您可以根据需要使用任意多个变量:

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
  2. 之所以起作用,是因为它是在数据绑定中设计的。文档中的更多信息:https : //developer.android.com/topic/libraries/data-binding/expressions#resources


1
但是它显示My Name is null数据是否尚未准备好(例如尚未从网络加载)
user924

1
在这种情况下,只需检查一下即可。android:text= "@{profile == null ? @string/loading : @string/generic_text(profile.firstName, profile.secondName)}"
Roman_D

这很有帮助!
akash89

最佳答案:)
Heriberto Rivera

55

连接字符串的多种方法

1.使用字符串资源(建议使用本地化

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

只是像这样使字符串资源。

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

2.硬编码的连接器

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

当您需要硬编码的附加电话号码(例如+)时,此功能非常有用。

3.使用String的concat方法

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

space是放在其中的html实体strings.xml。因为XML不直接接受HTML实体或特殊字符。(链接HTML实体)

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

4.使用 String.format()

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

您必须以这种类型在布局中导入String类。

<?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.通过字符串资源连接两个字符串。

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

在这种情况下,将字符串资源放入 strings.xml

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

可以有许多其他方法,选择您需要的一种。


5

使用绑定适配器

该示例使用Kotlin编写,并考虑到绑定变量可以为null:

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

然后在XML中使用绑定适配器而不是android:text属性

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

在绑定中调用导入的函数时遇到了很多麻烦,这个答案对我来说非常有效,并允许我重用扩展。谢谢!
Danny Buonocore

由于Stringclass 已经提供了基本的操作xml,因此该解决方案仅适合根据您的要求用于高级String操作。但是,这是不正确的。
sud007

3

2019更新,Android Studio升级至3.4,Android Gradle插件升级至3.4

不再需要导入

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

用于字符串操作。请检查此答案


1

如果您无法更改要包含%s在结尾的资源字符串(例如,因为它在没有后缀的其他地方使用):

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

如果Profile.name不能为null,那就足够了。但是,如果null发生这种情况,它将崩溃。您必须添加另一层:

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

(这需要<import type="java.util.Objects"/>工作。)

同样,只有当您在其他地方使用了资源字符串时,所有这些额外的工作才是值得的。第二个原因是当您要处理null为“空字符串”而不是“空”文字时。


2
如果字符串资源在其他地方使用,为什么不仅仅创建一个新资源呢?
Jarett Millard '18

0

如果要以XML 键入文本,可以使用``引号。

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

在其他需要使用String或变量连接的地方,可以使用

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

如果您想使用Concat字符串资源而不是变量,则可以执行以下操作:

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

0

仅使用+运算符对我有效:

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

String.xml将是:

<string name="Generic_Text">Hello</string>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.