Referencing a string in a string array resource with xml - android

I have preferences where you can enable/disable what items will show up on the menu. There are 17 items. I made a string array in values/arrays.xml with titles for each of these 17 items.
I have preferences.xml which has the layout for my preferences file, and I would like to reference a single item from the string array to use as the title.
How can I do this?
In the Android developer reference, I see how I can reference a single string with XML, but not how I can reference a string from an array resource in XML.

In short: I don't think you can, but there seems to be a workaround:.
If you take a look into the Android Resource here:
http://developer.android.com/guide/topics/resources/string-resource.html
You see than under the array section (string array, at least), the "RESOURCE REFERENCE" (as you get from an XML) does not specify a way to address the individual items. You can even try in your XML to use "#array/yourarrayhere". I know that in design time you will get the first item. But that is of no practical use if you want to use, let's say... the second, of course.
HOWEVER, there is a trick you can do. See here:
Referencing an XML string in an XML Array (Android)
You can "cheat" (not really) the array definition by addressing independent strings INSIDE the definition of the array. For example, in your strings.xml:
<string name="earth">Earth</string>
<string name="moon">Moon</string>
<string-array name="system">
<item>#string/earth</item>
<item>#string/moon</item>
</string-array>
By using this, you can use "#string/earth" and "#string/moon" normally in your "android:text" and "android:title" XML fields, and yet you won't lose the ability to use the array definition for whatever purposes you intended in the first place.
Seems to work here on my Eclipse. Why don't you try and tell us if it works? :-)

Maybe this would help:
String[] some_array = getResources().getStringArray(R.array.your_string_array)
So you get the array-list as a String[] and then choose any i, some_array[i].

The better option would be to just use the resource returned array as an array,
meaning:
getResources().getStringArray(R.array.your_array)[position]
This is a shortcut approach of other mentioned approaches but does the work in the fashion you want. Otherwise Android doesn't provide direct XML indexing for XML based arrays.

Unfortunately:
It seems you can not reference a single item from an array in values/arrays.xml with XML. Of course you can in Java, but not XML. There's no information on doing so in the Android developer reference, and I could not find any anywhere else.
It seems you can't use an array as a key in the preferences layout. Each key has to be a single value with it's own key name.
What I want to accomplish:
I want to be able to loop through the 17 preferences, check if the item is checked, and if it is, load the string from the string array for that preference name.
Here's the code I was hoping would complete this task:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
ArrayAdapter<String> itemsArrayList = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1);
String[] itemNames = getResources().getStringArray(R.array.itemNames_array);
for (int i = 0; i < 16; i++) {
if (prefs.getBoolean("itemKey[i]", true)) {
itemsArrayList.add(itemNames[i]);
}
}
What I did:
I set a single string for each of the items, and referenced the single strings in the . I use the single string reference for the preferences layout checkbox titles, and the array for my loop.
To loop through the preferences, I just named the keys like key1, key2, key3, etc. Since you reference a key with a string, you have the option to "build" the key name at runtime.
Here's the new code:
for (int i = 0; i < 16; i++) {
if (prefs.getBoolean("itemKey" + String.valueOf(i), true)) {
itemsArrayList.add(itemNames[i]);
}
}

Another way of doing it is defining a resources array in strings.xml like below.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE resources [
<!ENTITY supportDefaultSelection "Choose your issue">
<!ENTITY issueOption1 "Support">
<!ENTITY issueOption2 "Feedback">
<!ENTITY issueOption3 "Help">
]>
and then defining a string array using the above resources
<string-array name="support_issues_array">
<item>&supportDefaultSelection;</item>
<item>&issueOption1;</item>
<item>&issueOption2;</item>
<item>&issueOption3;</item>
</string-array>
You could refer the same string into other xmls too keeping DRY intact.
The advantage I see is, with a single value change it would effect all the references in the code.

The answer is quite easy to implement.
String[] arrayName = getResources().getStringArray(R.array.your_string_array);
and now you can access any element of the array by index (let suppose i'th index), then you can access it by arrayName[i]
I hope you understand this

Related

ListView and R string directory

I have a project (meaning an android app) created and used a custom ListView with three TextView UI for each column. But the app is also designed to support multi-language (at least three) using strings.xml file to fetch the selected language when user selects. Thus, the case here is, I have to write for the ListView String [] example {"a", "b", "c"} in java. I tried to do something like this String [] example {R.string.a, R.string. b, R.string. c} but the compiler says Error " illegal array ".
Now my question: Is it possible to reference the String [] { } of the ListView to strings.XML files.
Thank in advance and any example code or link I'm appreciated.
If your elements of the array are constant, you can make string array in strings.xml and access that array in code.
Put the following in strings.xml
<string-array name="example">
<item>a</item>
<item>b</item>
<item>c</item>
</string-array>
Access this array in code as:
String examples[] = getResources().getStringArray(R.array.example);
you can not use the direct reference to the String array, you have to get the value of String resource via getString()
like this
String[] example = {
getString(R.string.a), getString(R.string.b), getString(R.string.c)
};

Get a specific string from a stringarray in Android Studio

I have an array of strings (in strings.xml), in which I collect all my games
<string-array name="games">
<item name="select" translatable="false">...</item>
<item name="game_fortnite" translatable="false">Fortnite</item>
<item name="game_csgo" translatable="false">CounterStrike: Global Offensive</item>
<item name="game_minecraft_minigames" translatable="false">Minecraft Minigames</item>
</string-array>
I am now trying to get a specific item (In this case the first one, but I will need others later) from this array. Since i can give the items names, without Android Studio underlining it for me, I thought maybe i can refer to the strings by names, which does not work in any way I tried it.
In this case I am trying to find out wheter my string variable "game" has the same value as the array item I have named "select". I have tried all of the following:
if(game.equals(R.array.games.select)){
}
if(game.equals(R.string.games.select)){
}
if(game.equals(R.array.games[0])){
}
if(game.equals(R.array.select)){
}
I heve tried, as you can see, using an index (didn't work), but I'd like a possibility to refer to them by their name property.
This will reach your xml string and then you can use java string,
String gamesArr[] = getResources().getStringArray(R.array.games);
After doing this, create a list view and fill the list view items with that array.
And below code will give you selected item on the list view.
myList.getSelectedItem();
As per android documentation, the item tag for string-array does not have any attribute available.
https://developer.android.com/guide/topics/resources/string-resource#StringArray

Android get list of string resources from special file

For example, i have my_string.xml file with strings:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="my_string">My string</string>
<string name="another_string">Another string</string>
{...}
</resources>
Is it possible to get this strings to list/hashmap programmatically? Yeh, i know that i can take it by name or something like this. But i need to get it dynamically programmatically, for example, to HashMap<String, String>
Or all string resources will merge together after building and it's not possible to separate it?
If you want to access all the Strings from the strings.xml file you could use reflection on the R.string class.
Field[] fields = R.strings.class.getFields();
String[] allStringsNames = new String[fields.length];
for (int i =0; i < fields.length; i++) {
allStringsNames[i] = fields[i].getName();
}
You can then store them in Hashmap or wherever you want
Put the file in the raw folder. Then you have to open the file
InputStream in = getResources().openRawResource(R.raw.yourfile);
and parse the content manually, for instance save the list as xml or json and parse it and build your desired HashMap or whatever you like. Keep in mind that this may be a blocking operation and should not run on the main UI thread, run it async, but it depends on the length of the file you try to parse, but in general you should run that in an async thread
---- Update
You could do something like this:
int stringRes[] = {R.string.my_string, R.string.another_string}
List<String> myStrings = new ArrayList<String>();
for (int id : stringRes){
String str = getResources().getString(id);
// TODO do some if check if you want to keep that string or whatever you want to ...
myStrings.add(str);
}
you could store them into a HashMap(but getResources().getString() acts already like a HashMap ) or List
The whole point of the XML file is to act as a "hashmap" kind of... you can always get a string by using context and the R.string reference. I'm assuming you are aware of this, so then you must be trying to create a simplified reference to this?
Creating a HashMap requires either static references (which are not available for XML) or a runtime creation of the list. You can create the list in the Application class, but I would caution against that. You may have trouble referencing the context but again, you can use the Application constructor to make sure you have a reference to context.
Beyond that, you should check into the StringArray resource. It does not allow you to reference a string using another string because it is an array. Here are the docs:
http://developer.android.com/guide/topics/resources/string-resource.html#StringArray
If it's super-important to use a HashMap then you should probably not use XML and should just create a static class. The XML resource files are primarily used for centralized data (to ease modifications to static strings) and, more so, multi-lingual purposes. Static HashMaps are not the proper use-case.

Get resources automatically - Android

I'd like to know a better approach to improve performance of my program. The objective is to load resources automatically, I'm using names of string or string-array elements. For example, if I have the next resources:
<string name="temperature">temperature</string>
<string name="pressure">pressure</string>
<string name="velocity">velocity</string>
...
<string-array name="measures">
<item>#string/temperature</item>
<item>#string/pressure</item>
<item>#string/velocity</item>
...
</string-array>
<string name="name_temperature">Temperature</string>
<string name="name_pressure">Pressure</string>
<string name="name_velocity">Velocity</string>
...
<string-array
name="name_measures">
<item>#string/name_temperature</item>
<item>#string/name_pressure</item>
<item>#string/name_velocity</item>
...
</string-array>
<string-array name="units_temperature">
<item>K</item>
<item>°C</item>
<item>°F</item>
<item>R</item>
</string-array>
I'm loading resources this way:
measuresMap = new HashMap<String, String>();
String[] measures = getResources().getStringArray(R.array.measures);
for(int i = 0; i < measures.length; i++){
measuresMap.put(measures[i], getResources().getString(getResources().getIdentifier("name_" + measures[i], "string", getActivity().getPackageName())).toString());
}
i.e. I'm mapping the string-array values from 'measures' to it's corresponding string 'name_<>'.
I'm using a Spinner to select the measure, for example, 'Temperature':
measureSpinner = (Spinner) view.findViewById( R.id.spinnerConverter );
setSpinner(measureSpinner, R.array.name_measures, android.R.layout.simple_spinner_item, android.R.layout.simple_spinner_dropdown_item);
When an item is selected, a method retrieves the key from the Map depending on the item's string of the Spinner (getKeyByValueFromMap from here):
String[] units = getResources().getStringArray(getResources().getIdentifier("units_" + getKeyByValueFromMap(measuresMap, measureSpinner.getSelectedItem().toString()), "array", getActivity().getPackageName()));
public <T, E> T getKeyByValueFromMap(Map<T, E> map, E value) {
for (Map.Entry<T, E> entry : map.entrySet()) {
if (value.equals(entry.getValue())) {
return entry.getKey();
}
}
return null;
}
I need to do this to populate a NumberPicker:
String[] units = getResources().getStringArray(getResources().getIdentifier("units_" + getKeyByValueFromMap(measuresMap, measureSpinner.getSelectedItem().toString()), "array", getActivity().getPackageName()));
I think this is somehow inefficient. I read something about loading arrays with a TypedArray. I thought of a multidimensional String array. The objective is the same: load resources automatically (driven by the for loop to populate the Map). Is a HashMap the best option? It would be easier if a resource name could be defined with another resource string:
<string name="#string/temp">Temperature</string>
Every time I read a question about performance, a bell rings in my mind asking if there is really a performance issue. If you work with a small quantity of values, you won't really notice any bad performance. And if you work with lots of data, you should probably use sqlite instead.
If you won't be using #string/name_temperature per se, it can go directly on the array and make it similar to the example on the documentation
And yes, you can make use of TypedArray:
TypedArray measures = context.getResources().obtainTypedArray(R.array.name_measures);
It understands length() and getString(index).
Back to your code, I don't really understand your need of a map here, unless you are really worried of putting the strings directly in your arrays instead of the IDs.
Also, I see you use the name to generate the id of the Spinner; in this context, it doesn't help the performance and, more important, it does not make the code clearer either.
So the real answer:
I would take the references to the Spinners somewhere accessible. It might be nice to reify the need of a different key, and make a sublclass of Spinner that can convert indexed positions to the strings I want. In other words, delegate to the Spinner the responsibility of storing and converting positions to strings.
Since here I do need to map positions to the strings (instead of just the IDs), I could use a simple String[] and then, onItemSelected just access the position, geting the desired String, or setting it as selected (then when you ask your Spinner which value it has, you can just ask for its selected value, remember you now have it's reference on some attribute).

Storing strings in android XML resource file and referencing them

I'm wondering if I should use a resource XML file for to store all the possible recipes for me rather than using an ArrayList that is hardcoded, the problem is that I don't know how to call from a resource file using the method i have...
Here is a cut down version of what I want:
int recipeNumber = b.getInt("RECIPE"); //This is taken from another activity
final TextView rowTextView = new TextView(this); //Create a textview
rowTextView.setText(R.string.recipeNumber); //This is what i am struggling with
howToLinearLayout.addView(rowTextView); //Add textview to linearlayout
I don't know what to put in the part that references my resource file. I know I need:
rowTextView.setText(R. but I'm not sure what would come after that.
Im storing strings that would be for example:
<string name="1">One part Vodka, One part Coke</string>
<string name="2">One part Vodka, One part Lemonade</string>
This list will be quite long so id appreciate any other suggestions on storage, bare in mind I'm pretty new to this.
The recipeNumber int is what string will be called in to the textview.
Thanks for any help
I recommend storing the values outside your code, for example in XML or JSON (quicker and easier to work with). I would go with JSON. Really easy to load a list into an array, or other collection, and work with it anyway you want.
http://www.vogella.com/articles/AndroidJSON/article.html
You can then maintain your recipes, add new ones, maintain it etc without having to touch the code. Simply replace the XML or JSON (or whatever you choose) and rebuild your app.
Strings.xml is intended for pieces of text in your UI and code which you might want to localise and to avoid hard coding strings. It's not really intended for storing data.
To get string resources in code, use getResources().
rowTextView.setText(getResources().getString(R.string.recipeNumber));
To get an unknown resource identifier, but a known resource name, you can use the following method.
int identifier = getResources().getIdentifier("" + recipeNumber, "string", "com.your.package.name");
rowTextView.setText(getResources().getString(identifier));

Categories

Resources