How do I use databinding to combine a string from

2019-01-22 05:55发布

问题:

I have a TextView which has a hardcoded string and I have a dynamic variable that I want to put at the end of this string. This is my code:

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

I am having an issue with android:text="@string/Generic_Text"+"@{ Profile.name }" . The Generic_Text states " My Name is " then the Profile.name is dynamic and obviously changes from profile to profile. I want it so that the whole TextView output is My Name is {Profile.name}. Any help would be great.

回答1:

You can do this:

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

if you use string formatting for your Generic_Text string. ex. %s at the end



回答2:

You can do this even simplier:

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

you string should be like this:

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

Edit:

  1. Of course you can use as many variables as you need:

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
    
  2. It works just because it's designed in data binding. More in docs: https://developer.android.com/topic/libraries/data-binding/expressions#resources



回答3:

Many ways to concat strings

1. Using string resource (Recommended because Localization)

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

Just make string resource like this.

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

2. Hard coded concat

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

This is useful when you need hardcoded append like + for phone number.

3. Using String's concat method

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

Here space is an html entity which is placed inside strings.xml. Because XML does not accept Html entities or special characters directly. (Link Html Entities)

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

4. Using String.format()

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

you have to import String class in layout in this type.

<?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. concat two strings by string resource.

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

In this case put a string resource in strings.xml

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

There can be many other ways, choose one you need.



回答4:

In case you can't change the resource string to contain %s at the end (eg. because it's used elsewhere without the suffix):

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

If Profile.name can't be null, that's enough. However, if a null happens, it'll crash. You have to add another layer:

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

(which requires <import type="java.util.Objects"/> to work.)

Again: all this extra work is worth it only if you have the resource string used elsewhere. The second reason is when you want to handle null as "empty string" instead of a "null" literal.