I had a similar requirement, and I solved it in a way that is more powerful than the current solutions.
First create a resource that is an array of country arrays:
<array name="countries_array_of_arrays">
<item>@array/es</item>
<item>@array/it</item>
</array>
Then for each country add an array with the country info:
<array name="es">
<item>ES</item>
<item>ESPAÑA</item>
</array>
<array name="it">
<item>IT</item>
<item>ITALIA</item>
</array>
Some notes:
The name
values (es, it) on each country array must match the ones in countries_array_of_arrays
(you'll get an error if it doesn't).
The order of the items on each array must be the same for all the arrays. So always put the country code first, and the country name second, for example.
You can have any number of strings for each country, not just the country code and name.
To load the strings on your code do this:
TypedArray countriesArrayOfArrays = getResources().obtainTypedArray(R.array.countries_array_of_arrays);
int size = countriesArrayOfArrays.length();
List<String> countryCodes = new ArrayList<>(size);
List<String> countryNames = new ArrayList<>(size);
TypedArray countryTypedArray = null;
for (int i = 0; i < size; i++) {
int id = countriesArrayOfArrays.getResourceId(i, -1);
if (id == -1) {
throw new IllegalStateException("R.array.countries_array_of_arrays is not valid");
}
countryTypedArray = getResources().obtainTypedArray(id);
countryCodes.add(countryTypedArray.getString(0));
//noinspection ResourceType
countryNames.add(countryTypedArray.getString(1));
}
if (countryTypedArray != null) {
countryTypedArray.recycle();
}
countriesArrayOfArrays.recycle();
Here I'm loading the resources to 2 List
but you can use a Map
if you want.
Why is this more powerful?
It allows you to use string resources and hence translate the country names for different languages.
It allows you associate any type of resource to each country, not just strings. For example, you can associate a @drawable
with a country flag or an <string-array>
that contains provinces/states for the country.
Advanced example:
<array name="it">
<item>IT</item>
<item>ITALIA</item>
<item>@drawable/flag_italy</item>
<item>@array/provinces_italy</item>
</array>
Note that I haven't tried this but I've seen it in other questions. In such case you would use countryTypedArray.getDrawable(2)
to get the drawable, for example.
Simplification:
If you are only using strings for the country array, you can use an <string-array
(instead of an <array>
) like this:
<string-array name="it">
<item>IT</item>
<item>ITALIA</item>
</string-array>
And you can simplify a bit the for-loop code by directly getting an String[]
instead of a TypedArray
:
String[] countryArray = getResources().getStringArray(id);
countryCodes.add(countryArray[0]);
countryNames.add(countryArray[1]);
A note on having 2 <string-array>
:
Initially I was thinking of having 2 <string-array>
(one for the country code and another for the country name) as mentioned on another answer. However, with 2 <string-array>
you have to make sure that the number and order of the items match. With this solution you don't. It's safer in this regard. Note that, as I've said, the order of the items on each country array matters: always put the country code and country name in the same order!