Is it possible to show the floating point part in a string resource if it exists and hide it if it doesn't?
So, if this is my string resource:
<string name="liter">%.1f liter</string>
This will always show the floating point part:
getString(R.string.liter, 1.0) // 1.0 liter (I need this to be "1 liter", without the .0 part)
getString(R.string.liter, 1.5) // 1.5 liter
Can this be achieved?
As per your requirement, you can simply achieve this by typecasting. remove the template from string resources.
fun getLiterString(value : Float) : String
{
if(value.toInt().toFloat() == value)
{
return getString(R.string.liter_d, value.toInt())
}
else
{
return getString(R.string.liter_f, value)
}
}
string.xml
<string name="liter_d">%d liter</string>
<string name="liter_f">%.1f liter</string>
If you want to keep string resources,
You can make two templates for liter or else you have to replace ".0" from the output.
Example : https://pl.kotl.in/3poIS2lLJ
Related
I'm trying to create a line chart in Android using MPAndroidChart Library and as entries I have values like 1200.10, 1300.70 and so on, but on my chart the values are rounded (1200, 1301), and I want to display the original values. How can I do that? I tried different solutions but couldn't solve the problem yet. I'm using the Kotlin language. Thanks!
for (item in reversedCashList) {
if (i <= daysNmb) {
var cashValue: String = transformDataForChart(item.value!!)
dataValsEntries.add(Entry(i, cashValue.toFloat()))
i++
}
}
Also, I'm using this formatter Class to format my values because the initial format is like 120.200,10 and I changed them to 120200.10 but this values is displayed as 120200. My Formatter Class:
private fun transformDataForChart(totalValue: String): String {
return if (totalValue.contains(".")) {
val test = totalValue.replace(".", "")
test.replace(",", ".")
} else {
totalValue.replace(",", ".")
}
}
You can try with BigDecimal, something like BigDecimal.valueOf(X).setScale(decimalPlace(usually 2), BigDecimal.ROUND_HALF_UP).floatValue()
The idea is that float cannot hold so many values as the Double, I've encountered this issue as some point as well, and I had to change everything to Double just to make it more easier to maintain... Therefor I don't think is a straight-forward method to keep everything you need in the float format.
Hello I have a really simple qestion, in my app I have an EditText and what I would like for instance is this:
If I write 1/2 I would like 0.5 in the field.
How can I do this?
only add any dight/any other digit or any text with this fraction?
need info
Why you "dont want to split the string and then covert to individual strings to numbers and then divide them to have result"?
I am not aware of any built-in function to do that so the simplest solution:
double parse(String ratio) {
if (ratio.contains("/")) {
String[] rat = ratio.split("/");
return Double.parseDouble(rat[0]) / Double.parseDouble(rat[1]);
} else {
return Double.parseDouble(ratio);
}
}
It also covers the case where you have integer representation of ratio
parse("1/2") => 0.5
parse("3/7") => 0.42857142857142855
parse("1") => 1.0
I am setting text using setText() by following way.
prodNameView.setText("" + name);
prodOriginalPriceView.setText("" + String.format(getString(R.string.string_product_rate_with_ruppe_sign), "" + new BigDecimal(price).setScale(2, RoundingMode.UP)));
In that First one is simple use and Second one is setting text with formatting text.
Android Studio is so much interesting, I used Menu Analyze -> Code Cleanup and i got suggestion on above two lines like.
Do not concatenate text displayed with setText. Use resource string
with placeholders. less... (Ctrl+F1)
When calling TextView#setText:
Never call Number#toString() to format numbers; it will not handle fraction separators and locale-specific digits properly. Consider
using String#format with proper format specifications (%d or %f)
instead.
Do not pass a string literal (e.g. "Hello") to display text. Hardcoded text can not be properly translated to other languages.
Consider using Android resource strings instead.
Do not build messages by concatenating text chunks. Such messages can not be properly translated.
What I can do for this? Anyone can help explain what the thing is and what should I do?
Resource has the get overloaded version of getString which takes a varargs of type Object: getString(int, java.lang.Object...). If you setup correctly your string in strings.xml, with the correct place holders, you can use this version to retrieve the formatted version of your final String. E.g.
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
using getString(R.string.welcome_message, "Test", 0);
android will return a String with
"Hello Test! you have 0 new messages"
About setText("" + name);
Your first Example, prodNameView.setText("" + name); doesn't make any sense to me. The TextView is able to handle null values. If name is null, no text will be drawn.
Don't get confused with %1$s and %2$d in the accepted answer.Here is a few extra information.
The format specifiers can be of the following syntax:
%[argument_index$]format_specifier
The optional argument_index is specified as a number ending with a “$” after the “%” and selects the specified argument in the argument list. The first argument is referenced by "1$", the second by "2$", etc.
The required format specifier is a character indicating how the argument should be formatted. The set of valid conversions for a given argument depends on the argument's data type.
Example
We will create the following formatted string where the gray parts are inserted programmatically.
Hello Test! you have 0 new messages
Your string resource:
< string name="welcome_messages">Hello, %1$s! You have %2$d new
messages< /string >
Do the string substitution as given below:
getString(R.string.welcome_message, "Test", 0);
Note:
%1$s will be substituted by the string "Test"
%2$d will be substituted by the string "0"
I ran into the same lint error message and solved it this way.
Initially my code was:
private void displayQuantity(int quantity) {
TextView quantityTextView = (TextView) findViewById(R.id.quantity_text_view);
quantityTextView.setText("" + quantity);
}
I got the following error
Do not concatenate text displayed with setText. Use resource string with placeholders.
So, I added this to strings.xml
<string name="blank">%d</string>
Which is my initial "" + a placeholder for my number(quantity).
Note: My quantity variable was previously defined and is what I wanted to append to the string. My code as a result was
private void displayQuantity(int quantity) {
TextView quantityTextView = (TextView) findViewById(R.id.quantity_text_view);
quantityTextView.setText(getString(R.string.blank, quantity));
}
After this, my error went away. The behavior in the app did not change and my quantity continued to display as I wanted it to now without a lint error.
Do not concatenate text inside your setText() method, Concatenate what ever you want in a String and put that String value inside your setText() method.
ex: correct way
int min = 120;
int sec = 200;
int hrs = 2;
String minutes = String.format("%02d", mins);
String seconds = String.format("%02d", secs);
String newTime = hrs+":"+minutes+":"+seconds;
text.setText(minutes);
Do not concatenate inside setText() like
text.setText(hrs+":"+String.format("%02d", mins)+":"+String.format("%02d", secs));
You should check this thread and use a placeholder like his one (not tested)
<string name="string_product_rate_with_ruppe_sign">Price : %1$d</string>
String text = String.format(getString(R.string.string_product_rate_with_ruppe_sign),new BigDecimal(price).setScale(2, RoundingMode.UP));
prodOriginalPriceView.setText(text);
Don't Mad, It's too Simple.
String firstname = firstname.getText().toString();
String result = "hi "+ firstname +" Welcome Here";
mytextview.setText(result);
the problem is because you are appending "" at the beginning of every string.
lint will scan arguments being passed to setText and will generate warnings, in your case following warning is relevant:
Do not build messages by
concatenating text chunks. Such messages can not be properly
translated.
as you are concatenating every string with "".
remove this concatenation as the arguments you are passing are already text. Also, you can use .toString() if at all required anywhere else instead of concatenating your string with ""
I fixed it by using String.format
befor :
textViewAddress.setText("Address"+address+"\n"+"nCountry"+"\n"+"City"+"city"+"\n"+"State"+"state")
after :
textViewAddress.setText(
String.format("Address:%s\nCountry:%s\nCity:%s\nState:%s", address, country, city, state));
You can use this , it works for me
title.setText(MessageFormat.format("{0} {1}", itemList.get(position).getOppName(), itemList.get(position).getBatchNum()));
If you don't need to support i18n, you can disable this lint check in Android Studio
File -> Settings -> Editor -> Inspections -> Android -> Lint -> TextView Internationalization(uncheck this)
prodNameView.setText("" + name); //this produce lint error
val nameStr="" + name;//workaround for quick warning fix require rebuild
prodNameView.setText(nameStr);
I know I am super late for answering this but I think you can store the data in a varible first then you can provide the variable name. eg:-
// Java syntax
String a = ("" + name);
String b = "" + String.format(getString(R.string.string_product_rate_with_ruppe_sign);
String c = "" + new BigDecimal(price).setScale(2, RoundingMode.UP));
prodNameView.setText(a);
prodOriginalPriceView.setText(b, c);
if it is textView you can use like that : myTextView.text = ("Hello World")
in editText you can use myTextView.setText("Hello World")
I'm writing an app in which I want to display a string, describing an object in my model, to the user. I've started thinking about localization and I'm a bit stumped as to the best approach to deal with the difference in grammar between languages.
Imagine if in my model I have a verb an object and a quantity (pseudocode):
int _quantity = 6;
String _object = "#string/object";
String _verb = "#string/verb";
This should render in English as _verb + _quantity + _object (i.e. "eat 6 eggs", whereas in German it should render as _quantity + _object + _verb (i.e. "6 eggs eat" (but, obviously, using German word tokens rather than English :) ))
Is there a standard approach to this type of problem in Android?
Thanks.
OK, I've come up with a solution which, based on what I know, is the best I can find. If anyone has a better solution, please post!
1) In strings.xml, define any bits of text needed (for me, these equated to the localised names for enumeration members and for the string used to build natural language strings (more on this in a bit))
Example:
<resources>
...
<string name="verb_ate">ate</string>
<string name="verb_threw">threw</string>
...
<string name="modelobject_naturallanguagedescription">I {0} {1} {2}</string>
...
</resources>
2) In any enumerations, decorate them with the resource ids of the strings they are to use for display
Example:
public enum VerbType
Ate(R.string.verb_ate),
Threw(R.string.verb_threw);
private final int _stringID;
private VerbType(int stringID) {
_stringID = stringID;
}
public int getStringID() {
return _stringID;
}
}
3) Make a helper function which will take the model object and the context and will piece together the required natural language string (using java.text.MessageFormat), plus a helper function for each enumeration:
Example (assume that ModelObject has _verb, _quantity, _object and relevant getters):
public static String getVerb(VerbType v, Context c) {
return c.getResources().getString(v.getStringID());
}
public static String getNaturalLanguageString(ModelObject o, Context c) {
MessageFormat mf = new MessageFormat(c.getResources().getString(R.string.modelobject_naturallanguagedescription);
return mf.format(new Object[] {getVerb(o.getVerb(),c), o.getQuantity(), o.getObject()});
}
So, having done all of this, it's easy enough to define another strings file for a different language (German for example (I don't know German, so the language won't be correct)):
<resources>
...
<string name="verb_ate">gegessen</string>
<string name="verb_threw">gethrown</string>
...
<string name="modelobject_naturallanguagedescription">Ich haben {1} {2} {0}</string>
...
</resources>
So, in an english locale getNaturalLanguageString might return:
I ate 6 eggs
whereas in a German locale it might return:
Ich haben 6 eggs gegessen
i have a multilingual android app, where i have put the different translations in the strings.xml in the respective directory.
now i also have a custom xml file, where i would like to reference texts like this:
<?xml version="1.0" encoding="UTF-8"?>
<rooms>
<room title="#+string/localizedtext" />
</rooms>
now when i read the title attribute in my code, i obviously get the unresolved string "#+string/localizedtext" like it is.
is it possible to somehow resolve this link to the localized text automatically?
thanks!
Almost a year later:
public static String getStringResource(Context context, String thingie) {
try {
String[] split = thingie.split("/");
String pack = split[0].replace("#", "");
String name = split[1];
int id = context.getResources().getIdentifier(name, pack, context.getPackageName());
return context.getResources().getString(id);
} catch (Exception e) {
return thingie;
}
}
That'll do it.
This might seem like a broad answer but I believe it'll clarify a lot of things for people who spent hours looking for it (I'm one of them).
The short answer is yes, you can use references in custom XML, not just for strings, but that's the example I use, for ease of understanding.
Considering the context:
res/values/strings.xml
(Default strings, usually en-US for convenience but that's up to the developer)
<resources>
<string name="sample_string">This is a sample string.</string>
</resources>
res/values-fr/strings.xml
(Localized french strings)
<resources>
<string name="sample_string">Ceci est un exemple de chaîne</string>
</resources>
res/xml/test.xml
(Custom XML file)
<!-- #string/sample_string identifies both
the default and french localized strings,
the system settings determine which is used at runtime.
-->
<test>
<sample name="sampleName" text="#string/sample_string"/>
</test>
src/com/example/app/TestXmlParser.java
//Omitted imports for clarity.
public class testXmlParser {
public static final String ns = null;
public int parse(XmlResourceParser parser) throws XmlPullParserException,
IOException{
while(parser.next() != XmlPullParser.END_DOCUMENT){
if(parser.getEventType() == XmlPullParser.START_TAG){
if(parser.getName().equalsIgnoreCase("sample")){
// This is what matters, we're getting a
// resource identifier and returning it.
return parser.getAttributeResourceValue(ns, "text", -1);
}
}
}
return -1;
}
Use String getText(int id) to obtain the string corresponding to id (localized, if available).
Using the example above it would amount to replace :
//Return the resource id
return parser.getAttributeResourceValue(ns, "text", -1);
with :
//Return the localized string corresponding to the id.
int id = parser.getAttributeResourceValue(ns, "text", -1);
return getString(id);
The way you tried is not possible.
You might get similar functionality with <string-array> resource:
<resources>
<string-array name="room">
<item>#string/localizedText</item>
<item>#string/otherLocalizedText</item>
</string-array>
</resources>
then you would use it like this :
String[] room = getResources().getStringArray(R.array.room);
String localizedText = room[0];
String otherLocalizedText = room[1];
Localization in Android is done with resource identifiers. Check out this Android tutorial.
http://developer.android.com/resources/tutorials/localization/index.html
See discussion below.
Great answer kyis, shame I still don't have enough brownie points to rate it. To answer Nick's question, just change the last bit of code to:
int id = parser.getAttributeResourceValue(ns, "text", 0);
return (id != 0) ? getString(id) : parser.getAttributeValue(ns, "text");
Note that I used 0 for the default value of the resource as this is guaranteed never to be a real resource value. -1 would have done also.