Change value of R.string programmatically? - android

I'm looking for a way to change the value of a string resource dynamically. I have tried to use reflection but it claims 'invalid value for field'.
I use the strings for values within the layout, but need to swap them out for different languages.
Please see the attached code below.
public class Lang{
public static void langInit(){
java.lang.reflect.Field[] langStringFields = R.string.class.getFields();
Log.d(Global.TAG,"--> Lang Listing: " + langStringFields.length);
Log.d(Global.TAG,"--> Pref for language:");
String prefInLang = Prefs.cPrefsGet.getString("in_lang","en");
String fieldName = null;
String fieldValue = null;
String newFieldName = null;
String tmpA = "one";
for (int i=0; i<langStringFields.length; i++){
java.lang.reflect.Field field = langStringFields[i];
fieldName = field.getName();
try {
fieldValue = Global.gActivity.getString(field.getInt(R.string.class));
} catch (Exception e) {
e.printStackTrace();
}
if (fieldName.substring(0,2).equals("lo")){
try {
newFieldName = R.string.class.getField(prefInLang + "_" + fieldName.substring(3)).getName();
} catch (Exception e) {
e.printStackTrace();
}
Log.d(Global.TAG,"--> Field: " + fieldName + "value: " + fieldValue + "new field:" + newFieldName);
try {
java.lang.reflect.Field field2 = Class.forName(R.string.class.getName()).getDeclaredField(newFieldName);
field2.setAccessible(true);
field2.set(R.string.class,tmpA.toString());
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

Use built-in mechanism of localization, introduced in android. You don't need to change anything. You just need to specify the new strings.xml for each locale.

If you want to change current language for you app you can do it by using standard built-in localization features and changing locale programatically.

you should rather add a locale value to your resources and duplicate them : one for each language, thus letting the device choose the right one according to it's settings : check it there http://developer.android.com/resources/tutorials/localization/index.html

I believe using Android's built-in localization features is preferable to implementing it by hand. Here's a guide you can refer to:
http://developer.android.com/guide/topics/resources/localization.html
Unless, of course, we misunderstood your use case, but it does really sound like you are trying to do standard localization :-)
Bruno Oliveira, Developer Programs Engineer, Google

Related

Add another Word in TextView Android

I have one sentence with 3 TextView in my RecyclerView. The picture is like below :
In that picture, I have one sentence in 3 TextView, there are "1" "HOT, MORE CHILLI" and "Pizza". This is my RecyclerView Binding code :
try {
view.txtArticlesName.setText(/*orderList.getJSONObject(position).getString("quantityValue") +*/
/*orderList.getJSONObject(position).getString("spesial-request").replaceAll("[\\\"\\[\\]]", "") + */
orderList.getJSONObject(position).getString("bezeich"));
view.txtQty.setText(orderList.getJSONObject(position).getString("quantityValue"));
view.txtReqList.setText(orderList.getJSONObject(position).getString("spesial-request").replaceAll("[\\\"\\[\\]]", ""));
} catch (JSONException e) {
e.printStackTrace();
}
I want to Join all of TextView with only one 'TextView` dynamicly. I'll try this :
view.txtArticlesName.setText(/*orderList.getJSONObject(position).getString("quantityValue") +*/
/*orderList.getJSONObject(position).getString("spesial-request").replaceAll("[\\\"\\[\\]]", "") + */
orderList.getJSONObject(position).getString("bezeich"));
But its not work, its not bind the data, so the TextView just show the default text "Hello World". Can TextView do this? I read about Spannable too but i dont know how its work to add new word in one TextView. Or there is another way to do this? Any suggest and answer will helpfull for me. Thanks before.
Simply concat the Strings in your TextView.
String string1 = "Hello", string2 = "HOT CHILLI", string3 = "PIZZA";
TextView textView = (TextView) findViewById(R.id.your_textView);
textView.setText(string1.concat(string2).concat(string3));
Or you could also append it to the existing TextView's text.
textView.setText(textView.getText().toString.concat(string2));
EDIT:
Collect the data from the server in String variables, and then pass those variables to the TextView.
String string1, string2, string3;
try {
string1 = orderList.getJSONObject(position).getString("quantityValue");
string2 = orderList.getJSONObject(position).getString("spesial-request").replaceAll("[\\\"\\[\\]]", "");
string3 = orderList.getJSONObject(position).getString("bezeich"));
String final = string1.concat(string2).concat(string3);
view.txtView.setText(final);
} catch (JSONException e) {
e.printStackTrace();
}
Use '+' operator or StringBuilder to join 2 or more strings and set the resultant string into a single textview.
If you want to have some part of text with different font, color, size, bold etc, you can use Spannable string or Html.fromHtml()
you can make and use spannable String like below :
private void addSpannableString(){
//"1" "HOT, MORE CHILLI" and "Pizza"
String one= "1";
String two= "HOT, MORE CHILLI";
String three= "Pizza";
String mergeString= one + two + three;
Spannable spannable = new SpannableString( mergeString );
StyleSpan boldSpan = new StyleSpan( Typeface.BOLD );
spannable.setSpan( boldSpan, mergeString.indexOf(two), mergeString.indexOf(three), Spannable.SPAN_INCLUSIVE_INCLUSIVE );
textview.setText(mergeString);
}
There are many methods are available to make Spans including colors and Typefaces
Use TextView.append(CharSequence text) to add more text to it.
Append the specified text to the TextView's display buffer, upgrading
it to BufferType.EDITABLE if it was not already editable
The Difference between GetString And OptString is:
From Documentation
OptString returns the empty string ("") if the key you specify doesn't
exist. GetString on the other hand throws a JSONException.
Use getString if it's an error for the data to be missing, or optString if you're not sure if it will be there.
I solved this with a little disappointed . Here my final code :
try {
view.txtArticlesName.setText(orderList.getJSONObject(position).getString("quantityValue") + " " +
orderList.getJSONObject(position).optString("spesial-request").replaceAll("[\\\"\\[\\]]", "") + " " +
orderList.getJSONObject(position).getString("bezeich"));
} catch (JSONException e) {
e.printStackTrace();
}
with getString :
with optString :
I change getString with optString and operator + work now. I'm not fully undertand why getString not work but optString work.
Thank you very much for all anwser, +1 from me

android: can I find view by its text?

In my program I have dynamic buttons each representing a letter and I need to find a button that
has a specific letter. Since the buttons' text change from time to time, I cannot use findViewById method, instead i need a way of finding view by its text. Is there one?
If not, suppose the button that has the letter I am searching for has id = B12 and I can get the number 12 in my program. How do I convert number 12 into R.id.B12 ?
I think you are looking for "find resource by name" functionality
String mButtonName = "button" + 12;
int resID = getResources().getIdentifier(mButtonName , "id", getPackageName());
That's the way you get in int(id) from string, but you can do the same using reflection which is supposed to be way faster.
public static int getId(String resourceName, Class<?> c) {
try {
Field idField = c.getDeclaredField(resourceName);
return idField.getInt(idField);
} catch (Exception e) {
throw new RuntimeException("No resource ID found for: "
+ variableName + " / " + c, e);
}
}
And you use it like this:
getId("button" + 12, R.id.class);
Hope it Helps!
Regards!

android: how do I format number as phone with parentheses

I have a number that I need to format as a telephone number. If I do
PhoneNumberUtils.formatNumber(numStr);
Then I get
888-555-1234
But what I need to get is
(888) 555-1234
How do I get the second one? Is there a standard android way?
If you know the country for which you want to do it, you can use Google's open source library libphonenumber . Here is how you can format it:
String numberStr = "8885551234"
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
PhoneNumber numberProto = phoneUtil.parse(numberStr, "US");
//Since you know the country you can format it as follows:
System.out.println(phoneUtil.format(numberProto, PhoneNumberFormat.NATIONAL));
} catch (NumberParseException e) {
System.err.println("NumberParseException was thrown: " + e.toString());
}
If you don't know the country then for numberStr use E.164 format phone number and in place of country code use null.
Don't know if you found what you were looking for, but I ended up writing a little method that takes the length of a string (since the phone numbers I get come from a web service and can be a variety of formats). I believe it should work (so far all my test cases have been with the first two options -- haven't tested the other two yet).
public static String FormatStringAsPhoneNumber(String input) {
String output;
switch (input.length()) {
case 7:
output = String.format("%s-%s", input.substring(0,3), input.substring(3,7));
break;
case 10:
output = String.format("(%s) %s-%s", input.substring(0,3), input.substring(3,6), input.substring(6,10));
break;
case 11:
output = String.format("%s (%s) %s-%s", input.substring(0,1) ,input.substring(1,4), input.substring(4,7), input.substring(7,11));
break;
case 12:
output = String.format("+%s (%s) %s-%s", input.substring(0,2) ,input.substring(2,5), input.substring(5,8), input.substring(8,12));
break;
default:
return null;
}
return output;
}
If you have the String "888-555-1234" - by using PhoneNumberUtils.formatNumber(numStr); you can simply do this:
String numStr = "888-555-1234";
numStr = "(" + numStr.substring(0,3) + ") " + numStr.substring(4);
System.out.print(numStr); // (888) 555-1234
However, this is hard coded. You would need to make sure the String had a full 10 digits before doing so.
You simply use this and get you want :
new PhoneNumberFormattingTextWatcher()
or Have look at this url :
http://developer.android.com/reference/android/telephony/PhoneNumberFormattingTextWatcher.html
Try to use regex. This will help you. As for me, i use this:
var result = "+1 888-555-1234"
if (Pattern.compile("^\\+[\\d]+\\s[\\d]{1,3}\\s[\\d]+").matcher(result).find()) {
result = result.replaceFirst(" ", "(").replaceFirst(" ", ")").replace(" ","-")
}
if(Pattern.compile("^\\+[\\d]+\\s[\\d]{1,3}-[\\d]+").matcher(result).find()){
result = result.replaceFirst(" ", "(").replaceFirst("-", ")")
}
Timber.d("$result")
output: +1(888)555-1234
Working solution in 2020:
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String countryIso = telephonyManager.getNetworkCountryIso().toUpperCase();
phoneNumberTextView.setText(PhoneNumberUtils.formatNumber("3473214567", countryIso));

Android: Currently Displayed Layout(s) file name(s)

How to get the name of the currently used Layout(s) file name(s) ?
for example it could be res/layout/main.xml or something like that.
Also, the code which require this information is not part of the app that contains this layout, it's kind of a testing code.
You don't. Internally Android doesn't refer to them by filenames, it refers to them by id- an integer. You can see the integer it uses in your generated R file. And that information isn't stored, it inflates the proper file then forgets about it.
i assume, you can go with reflection and lots of iteration.
First you want all your statics in the R.layout class - then you obtain their values and compare them to the View.getId() and in a last step you retrieve the fields name.
but: the name will only contain layout-files name (in your example main) and not the full path to it, even though you could have duplicate layouts with the same name, e.g. for landscape/portrait mode etc
I never tried something like that and I'm not sure if this works out, because i don't know if your testenvironment can access your R file without errors, but that's the way you could go
edit: just adding some sample code that should do the job, works from within the app - as said i'm unsure about your framework and the way you access r
R.layout layout = new R.layout();
Map<Integer, String> id2name = new HashMap<Integer, String>();
for (Field f : layout.getClass().getDeclaredFields()) {
try {
id2name.put(f.getInt(layout), f.getName());
Log.i("Layout", f.getInt(layout) + "," + f.getName());
}
catch (IllegalArgumentException e) {
//oops
Log.e("Layout", "", e);
}
catch (IllegalAccessException e) {
//oops
Log.e("Layout", "", e);
}
}
for (Entry<Integer, String> e:id2name.entrySet()) {
if (findViewById(e.getKey()) != null) {
Log.i("Layout:", "found: " + e.getValue() + ";" + e.getKey());
}else {
Log.i("Layout:", "not found: " + e.getValue()+ ";" + e.getKey());
}
}
note that there will be no view found unless layouting is done (findViewById() is null if you call to early)
of course you can go the other way around and search down the view tree by checking if a layout is instance of a ViewGroup and iterate over its childviews and compare each's id to the ids in the map

User's language dependent float representation

I am fighting with making my app language dependent. The user needs to enter a float. I am using a EditText to display the current value and allow editing.
To prepare I coded:
st = String.format("%.2f", myFloat);
edTxt = (EditText) findViewById(R.id.myEditText);
edTxt.setText(st, TextView.BufferType.EDITABLE);
edTxt.selectAll();
Now the user is presented the value. If in Settings of my device, I set my language to Deutsch (German) an float value of 2.80 is displayed as 2,80. On onPause of the activity I retrieve the value and convert it from string to float - and get a NumberFormatException error because of the comma.
Should be easy I thought, I just need to replace the comma by a dot, and coded:
String st ="";
st = edTxt.getText().toString();
st.replace(",", ".");
try{
float minV = Float.valueOf(st);
} catch (NumberFormatException nfe){
mShowAToast("NumberFormatException: " + st);
}
And surprise: The app runs into the catch and the toast shows st as "2,80" instead of "2.80", st.replace didn't do its job.
(probably it did, but)
Do I oversee anything?
If you have an float value that use ',' as decimal separator. You can parse it using a Locale class. Check the following code.
public static void main(String[] args) {
try {
// Number and NumberFormat are in java.text.*;
Number numberG = NumberFormat.getNumberInstance(java.util.Locale.GERMAN).parse("-1.234,56");
if (numberG instanceof Double) {
System.out.println(">" + numberG.doubleValue());
}
} catch (ParseException e) {
e.printStackTrace();
}
}
It will print:
>-1234.56
So instead of use java.util.Locale.GERMAN you can use the defaul locale: java.util.Locale.getDefault() of your JVM.
About the replace function of String I have compared the specfication of Android API and Oracle JDK and both are the same. So I think it must return what you expected. Just in case I have tried the folowing in my JDK:
String value = "-1.234,56";
System.out.println(value.replace(',', '.'));
System.out.println(value.replace(",", "."));
And both are printing: -1.234.56

Categories

Resources