Làm cách nào để sử dụng tính năng liên kết dữ liệu để kết hợp một chuỗi từ tài nguyên với một biến động trong XML?


125

Tôi có một TextView có chuỗi mã cứng và tôi có một biến động mà tôi muốn đặt ở cuối chuỗi này. Đây là mã của tôi:

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

Tôi đang gặp vấn đề với android:text="@string/Generic_Text"+"@{ Profile.name }". Trạng Generic_Textthái "Tên tôi là" sau đó Profile.namelà động và rõ ràng là thay đổi từ hồ sơ này sang hồ sơ khác. Tôi muốn nó để toàn bộ đầu ra TextView là Tên tôi là {Profile.name} . Bất kỳ sự trợ giúp nào đều sẽ là tuyệt vời.


Bạn có đang sử dụng databinding không?
malmling

Có, tôi đang sử dụng databinding
Ignacio Perez

Vui lòng thêm mã java hiện tại của bạn.
malmling

Câu trả lời:


162

Bạn có thể làm được việc này:

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

nếu bạn sử dụng định dạng chuỗi cho Generic_Textchuỗi của mình . Ví dụ. %scuối cùng


Cảm ơn rất nhiều Tôi chỉ cần đặt rằng trong và nó làm việc một cách chính xác
Ignacio Perez

5
Đây không phải là câu trả lời được chấp nhận, vì điều này thực sự không sử dụng các tính năng Liên kết dữ liệu để thao tác văn bản.
Darwind

1
đồng ý với @Darwind, vui lòng xem câu trả lời của tôi cho một triển khai làm việc với Binding Adapters
juanagui

@IgorGanapolsky câu trả lời này đã hơn 3 năm tuổi nhưng chắc chắn đã từng hoạt động trước đây - bạn có nhớ lại điều gì đã xảy ra khi bạn thử nó không?
C0D3LIC1OU5

320

Bạn có thể làm điều này thậm chí còn đơn giản hơn:

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

chuỗi bạn phải như thế này:

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

Biên tập:

  1. Tất nhiên, bạn có thể sử dụng bao nhiêu biến tùy thích:

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
  2. Nó hoạt động chỉ vì nó được thiết kế trong ràng buộc dữ liệu. Thông tin khác trong tài liệu: https://developer.android.com/topic/libraries/data-binding/expressions#resources


1
nhưng nó cho thấy My Name is nullnếu dữ liệu là chưa sẵn sàng (ví dụ như không được nạp từ mạng)
user924

1
Trong trường hợp này chỉ cần kiểm tra nó trước. android:text= "@{profile == null ? @string/loading : @string/generic_text(profile.firstName, profile.secondName)}"
Roman_D

Điều này là hữu ích!
akash89

Câu trả lời hay nhất :)
Heriberto Rivera

55

Nhiều cách để nối các chuỗi

1. Sử dụng tài nguyên chuỗi ( Được khuyến nghị vì Bản địa hóa )

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

Chỉ cần tạo tài nguyên chuỗi như thế này.

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

2. concat mã hóa cứng

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

Điều này hữu ích khi bạn cần thêm mã cứng như + cho số điện thoại.

3. Sử dụng Stringphương thức concat của

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

Đây spacelà một thực thể html được đặt bên trong strings.xml. Bởi vì XMLkhông chấp nhận trực tiếp các thực thể Html hoặc các ký tự đặc biệt. (Liên kết các thực thể Html)

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

4. Sử dụng String.format()

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

bạn phải nhập lớp Chuỗi trong bố cục kiểu này.

<?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. nối hai chuỗi bằng tài nguyên chuỗi.

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

Trong trường hợp này, hãy đặt một tài nguyên chuỗi vào strings.xml

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

Có thể có nhiều cách khác, hãy chọn một cách bạn cần.


5

Sử dụng Bộ điều hợp ràng buộc .

Mẫu này được viết bằng Kotlin và có tính đến biến ràng buộc có thể là null:

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

sau đó sử dụng bộ điều hợp liên kết trong XML của bạn thay vì thuộc android:texttính

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

Đang gặp rất nhiều khó khăn khi gọi các hàm đã nhập trong liên kết, câu trả lời này hoạt động hoàn hảo đối với tôi và cho phép tôi sử dụng lại các tiện ích mở rộng của mình. Cảm ơn!
Danny Buonocore

Vì, thao tác cơ bản đã được cung cấp bởi Stringlớp từ xml, giải pháp này chỉ tốt khi được sử dụng cho các thao tác Chuỗi nâng cao dựa trên yêu cầu của bạn. Tuy nhiên, nó không phải là không chính xác.
sud007

3

Bản cập nhật 2019, Android studio lên 3.4, Plugin Android Gradle lên 3.4

Không cần nhập nữa

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

cho các hoạt động chuỗi. Vui lòng kiểm tra câu trả lời này .


1

Trong trường hợp bạn không thể thay đổi chuỗi tài nguyên để chứa %sở cuối (ví dụ: vì nó được sử dụng ở nơi khác mà không có hậu tố):

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

Nếu Profile.namekhông thể là null, vậy là đủ. Tuy nhiên, nếu nullxảy ra, nó sẽ bị sập. Bạn phải thêm một lớp khác:

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

(yêu cầu <import type="java.util.Objects"/>để hoạt động.)

Một lần nữa: tất cả công việc bổ sung này chỉ đáng giá nếu bạn có chuỗi tài nguyên được sử dụng ở nơi khác. Lý do thứ hai là khi bạn muốn xử lý nulldưới dạng "chuỗi rỗng" thay vì một chữ "null".


2
Nếu tài nguyên chuỗi được sử dụng ở nơi khác, tại sao không tạo một tài nguyên mới?
Jarett Millard

0

Trong trường hợp nếu bạn muốn nhập văn bản bằng XML, bạn có thể sử dụng dấu ngoặc kép `` .

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

ở những nơi khác bạn cần Kết hợp với Chuỗi hoặc biến , bạn có thể sử dụng

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

nếu bạn muốn kết hợp tài nguyên chuỗi thay vì biến mà bạn có thể làm,

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

0

Chỉ sử dụng +toán tử hoạt động cho tôi:

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

String.xml sẽ là:

<string name="Generic_Text">Hello</string>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.