Czy można mieć symbole zastępcze w wartościach ciągów, string.xml
którym można przypisywać wartości w czasie wykonywania?
Przykład:
jakiś ciąg PLACEHOLDER1 trochę więcej
Czy można mieć symbole zastępcze w wartościach ciągów, string.xml
którym można przypisywać wartości w czasie wykonywania?
Przykład:
jakiś ciąg PLACEHOLDER1 trochę więcej
Odpowiedzi:
Tak, zapoznaj się z następującymi materiałami z zasobów ciągów: Formatowanie i stylowanie
Jeśli musisz sformatować ciągi za pomocą
String.format(String, Object...)
, możesz to zrobić, umieszczając argumenty formatu w zasobie ciągu. Na przykład z następującym zasobem:<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
W tym przykładzie ciąg formatu ma dwa argumenty:
%1$s
jest ciągiem i%2$d
jest liczbą dziesiętną. Możesz sformatować ciąg za pomocą argumentów z aplikacji w następujący sposób:Resources res = getResources(); String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);
Zauważ, że getString
występuje przeciążenie, które wykorzystuje ciąg jako ciąg formatu:
String text = res.getString(R.string.welcome_messages, username, mailCount);
Jeśli potrzebujesz obsługi liczby mnogiej, użyj tego:
<plurals name="welcome_messages">
<item quantity="one">Hello, %1$s! You have a new message.</item>
<item quantity="other">Hello, %1$s! You have %2$d new messages.</item>
</plurals>
Pierwszy mailCount
parametr służy do decydowania, którego formatu użyć (pojedynczego lub mnogiego), pozostałe parametry to twoje podstawienia:
Resources res = getResources();
String text = res.getQuantityString(R.plurals.welcome_messages, mailCount, username, mailCount);
Aby uzyskać więcej informacji, zobacz Zasoby łańcuchowe: Liczba mnoga .
Kiedy po raz pierwszy zobaczyłem %1$s
i %2$d
w przyjętej odpowiedzi, nie miało to sensu. Oto trochę więcej wyjaśnień.
Nazywa się je specyfikatorami formatu. W ciągu xml mają one postać
%[parameter_index$][format_type]
1$
, 2$
i 3$
. Kolejność umieszczania ich w łańcuchu zasobów nie ma znaczenia, tylko kolejność dostarczania parametrów.typ formatu : Istnieje wiele sposobów formatowania rzeczy ( patrz dokumentacja ). Oto kilka typowych:
s
strunowyd
dziesiętna liczba całkowitaf
liczba zmiennoprzecinkowaUtworzymy następujący sformatowany ciąg, w którym szare części są wstawiane programowo.
Moja siostra
Mary
ma12
lata.
string.xml
<string name="my_xml_string">My sister %1$s is %2$d years old.</string>
MyActivity.java
String myString = "Mary";
int myInt = 12;
String formatted = getString(R.string.my_xml_string, myString, myInt);
getString
ponieważ byłem w działaniu. Możesz użyć, context.getResources().getString(...)
jeśli nie jest dostępne.String.format()
sformatuje również ciąg.1$
I 2$
warunki nie muszą być stosowane w tej kolejności. To znaczy, 2$
może przyjść wcześniej 1$
. Jest to przydatne podczas internacjonalizacji aplikacji dla języków, które używają innej kolejności słów.%1$s
wiele razy w pliku XML, jeśli chcesz go powtórzyć.%%
aby uzyskać rzeczywistą %
postać.Jeśli chcesz użyć parametru z rzeczywistego pliku strings.xml bez użycia kodu Java:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
<!ENTITY appname "WhereDat">
<!ENTITY author "Oded">
]>
<resources>
<string name="app_name">&appname;</string>
<string name="description">The &appname; app was created by &author;</string>
</resources>
Nie działa to w przypadku plików zasobów, tzn. Zmienne należy skopiować do każdego pliku XML, który ich potrzebuje.
<!DOCTYPE... ]>
części w oddzielnym pliku i włączenia jej do wielu plików zasobów? Jakaś sztuczka, aby to osiągnąć?
Szukałem tego samego i wreszcie znalazłem następujące bardzo proste rozwiązanie. Najlepsze: działa od razu po wyjęciu z pudełka.
1. zmień zasób swojego ciągu:
<string name="welcome_messages">Hello, <xliff:g name="name">%s</xliff:g>! You have
<xliff:g name="count">%d</xliff:g> new messages.</string>
2. użyj podstawienia łańcucha:
c.getString(R.string.welcome_messages,name,count);
gdzie c jest kontekstem, nazwa jest zmienną łańcuchową i policz zmienną int
Musisz uwzględnić
<resources xmlns:xliff="http://schemas.android.com/apk/res-auto">
w twoim res / strings.xml. Pracuje dla mnie. :)
xliff
tagów wokół specyfikatorów formatu? Jaką dodatkową wartość dodają, a nie tylko same używają specyfikatorów %s
i %d
?
W Kotlin wystarczy ustawić wartość ciągu w następujący sposób:
<string name="song_number_and_title">"%1$d ~ %2$s"</string>
Utwórz widok tekstu w swoim układzie:
<TextView android:id="@+id/song_number_and_title"/>
Zrób to w kodzie, jeśli używasz Anko:
val song = database.use { // get your song from the database }
song_number_and_title.setText(resources.getString(R.string.song_number_and_title, song.number, song.title))
Może być konieczne pobranie zasobów z kontekstu aplikacji.
Jednak powinieneś także przeczytać odpowiedź Eliasa Mårtensona na liczbę mnogą w Androidzie dotyczącą „zero” . Występuje problem z interpretacją niektórych wartości, takich jak „zero”.
w res / wartości / string.xml
<resources>
<string name="app_name">Hello World</string>
<string name="my_application">Application name: %s, package name: %s</string>
</resources>
w kodzie java
String[] args = new String[2];
args[0] = context.getString(R.string.app_name);
args[1] = context.getPackageName();
String textMessage = context.getString(R.string.my_application,(Object[]) args);
Możesz użyć MessageFormat
:
<string name="customer_address">Wellcome: {0} {1}</string>
W kodzie Java:
String text = MessageFormat(R.string.customer_address).format("Name","Family");
Poziom API 1:
https://developer.android.com/reference/java/text/MessageFormat.html
Jeśli chcesz zapisać procent (%), skopiuj go:
<string name="percent">%1$d%%</string>
label.text = getString(R.string.percent, 75) // Output: 75%.
Jeśli piszesz po prostu %1$d%
, otrzymasz błąd: Format string 'percent' is not a valid format string so it should not be passed to String.format
.
Tak! możesz to zrobić bez pisania kodu Java / Kotlin, tylko XML, korzystając z tej małej biblioteki, którą utworzyłem, która robi to w czasie kompilacji, więc nie wpłynie to na twoją aplikację: https://github.com/LikeTheSalad/android -string-referencja
Stosowanie
Twoje sznurki:
<resources>
<string name="app_name">My App Name</string>
<string name="template_welcome_message">Welcome to ${app_name}</string>
</resources>
Wygenerowany ciąg po zbudowaniu:
<!--resolved.xml-->
<resources>
<string name="welcome_message">Welcome to My App Name</string>
</resources>
Bezpośrednie rozwiązanie problemu przez Kotlin:
strings.xml
<string name="customer_message">Hello, %1$s!\nYou have %2$d Products in your cart.</string>
kotlinActivityORFragmentFile.kt:
val username = "Andrew"
val products = 1000
val text: String = String.format(
resources.getString(R.string.customer_message), username, products )
Użyj tego w swoim pliku łańcuchowym
<string name="redeem_point"> You currently have %s points(%s points = 1 %s)</string>
I w swoim kodzie użyj odpowiednio
coinsTextTV.setText(String.format(getContext().getString(R.string.redeem_point), rewardPoints.getReward_points()
, rewardPoints.getConversion_rate(), getString(R.string.rs)));
Wersja zaakceptowanej odpowiedzi Kotlin ...
val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)
resources.getString(int, ... args)
metody z argumentami zamiast String.format
. W tym kodzie nie ma też szczegółów kotlin, oprócz val
słów kluczowych. Zobacz odpowiedź msbodw001