let's say i have this Multidimensional Array :
myArray = new String[][]{{"Hello","World"},{"I Love","Android"},{"something","Random"}};
and in my app , i'm dealing with it like this :
for (int i=0; i<myArray.length; i++) {
for (int x=0; x<myArray[i].length; x++) {
// set textview or something
}
}
I want to do this Multidimensional Array by XML resource file.
i tried this way but did not work for me :
<string-array name="myArray">
<item><item>Hello</item><item>World</item></item>
<item><item>I Love</item><item>Android</item></item>
<item><item>something</item><item>Random</item></item>
</string-array>
I know I can do normal string-array in the XML file and make it look like Multidimensional Array by Java but I just want to know if it's possible to do it in XML directly
You can maintain your xml for array like this:
<resources>
<array name="categories_0">
<item>1</item>
<item>Pizza</item>
</array>
<array name="categories_1">
<item>2</item>
<item>Burger</item>
</array>
<array name="categories_2">
<item>3</item>
<item>Maggie</item>
</array>
Now each category is an array with a key/value pair for it’s properties. What ties it with other categories is the integer suffix. Now we can use this dandy static method to grab them:
Than, we can define global reference for index of the array:
public class ResourceHelper {
public static List<TypedArray> getMultiTypedArray(Context context, String key) {
List<TypedArray> array = new ArrayList<>();
try {
Class<R.array> res = R.array.class;
Field field;
int counter = 0;
do {
field = res.getField(key + "_" + counter);
array.add(context.getResources().obtainTypedArray(field.getInt(null)));
counter++;
} while (field != null);
} catch (Exception e) {
e.printStackTrace();
} finally {
return array;
}
}
}
This is dynamically retrieving the resources programmatically, with an incremented counter to find the next object until there isn’t one left. Now this can be consumed throughout your code base like this:
for (TypedArray item : ResourceHelper.getMultiTypedArray(this, "categories")) {
Category category = new Category();
category.ID = item.getInt(0, 0);
category.title = item.getString(1);
mCategories.add(category);
}
Here you may face error in encapsulating class or method. You can just add #SuppressWarnings("ResourceType") to that method or class.
This example will work for you.
It's impossible. You can put Json String inside
<item>{"dummy":"dummy"} </item> and then parse it.
Related
I have string array that looks like this:
<string-array name="USA">
<item name="NY">001</item>
<item name="LA">002</item>
<item name="WA">003</item>
</string-array>
I can get those numbers by:
Resources res = getResources();
int arryid = res.getIdentifier("USA", "array", getPackageName());
String[] numbers = res.getStringArray(arryid);
But how can I also get the names (NY,LA,WA)?
Note that I have a lot of counties... Maybe use different approach?
In the documentation there is no name attribute for an <item>.
So I don't think there will be any way to get those keys.
However, if you want to get name of string or string-array, you can get it programmatically but not for the <item>.
As "001" is just the index, why not simply use that?
<string-array name="USA">
<item>NY</item>
<item>LA</item>
</string-array>
Then just use index + 1 for the position:
String[] usaStates = getResources().getStringArray(R.array.USA);
int index = 0;
String firstStateName = usaStates[index];
int firstStatePosition = (index + 1);
That aside, you can use two arrays and merge them into a HashMap:
<string-array name="USA">
<item>NY</item>
<item>LA</item>
</string-array>
<string-array name="USA_pos">
<item>001</item>
<item>002</item>
</string-array>
String[] usaStates = getResources().getStringArray(R.array.USA);
String[] usaStatePositions = getResources().getStringArray(R.array.USA_pos);
Map <String, String> map = new HashMap<>(usaStates.length);
for (int i = 0; i < usaStates.length; i++) {
map.put(usaStates[i], usaStatePositions[i]);
}
String[] numbers = getResources().getStringArray(R.array.USA);
to get data from array use.
numbers[id]
add array like this.
<string-array name="USA">
<item>NY</item>
<item>LA</item>
<item>WA</item>
</string-array>
I have a spinner in my app where the user chooses whether he wants to search by "Contains" "Starts with" "Ends with" or "Equals", The option user selects is stored into a json with other information and sent to server to retrieve results. Now I'm using:
String searchtypeval=searchtype.getSelectedItem().toString();
and adding searchtypeval into my json.
The String-array in the spinner is
<string-array name="search_options">
<item>Starts With</item>
<item>Equals</item>
<item>Ends With</item>
<item>Contains</item>
</string-array>
But now I'm adding language support so in values-fr/strings.xml the string array for that spinner is
<string-array name="search_options">
<item>Commence par </item>
<item>Égal </item>
<item>Se termine par </item>
<item>Contient </item>
</string-array>
Now if the user selects equals in french , Egal is stored into the JSON which of course the server doesn't accept. Is there any way I can make a connection between the french and the english strings.xml? All I can think of now is to use searchtype.getSelectedItemPosition()
and hard code the value into String searchtypeval since I know which option is which position, but this seems very cumbersome, is there any method to solve this issue that is more elegant?
You can send to the server index of a selected element, but this isn't a good way, cause of index is not informated. The better way is sending readable string key to the server. See the following code:
1) create file nontranslatable_string.xml in res/values
<resources>
<string-array name="search_options_keys">
<item>Starts With</item>
<item>Equals</item>
<item>Ends With</item>
<item>Contains</item>
</string-array>
</resources>
2) create your Item class like SpinnerItem
public class SpinnerItem {
public final String key;
public final String value;
private SpinnerItem(String key, String value) {
this.key = key;
this.value = value;
}
public static SpinnerItem create(String key, String value) {
return new SpinnerItem(key, value);
}
#Override
public String toString() {
return value;
}
}
3) fill your adapter with values
String[] keys = context.getResources().getStringArray(R.id.search_options_keys);
String[] values = context.getResources().getStringArray(R.id.search_options);
List<SpinnerItem> items = new ArrayList<SpinnerItem>();
for (int i = 0; i < keys.length; i++) {
items.add(SpinnerItem.create(keys[i], values[i]));
}
spinner.setAdapter(new ArrayAdapter<SpinnerItem>(context, android.R.layout.simple_spinner_item, android.R.id.text1, items));
4) select your value
String valueForSendingToServer = ((SpinnerItem) spinner.getSelectedItem()).key;
UPDATE
Or you can use another way and get neccessary value for any location you use:
Configuration config = context.getResources().getConfiguration();
// Save originla location
Locale originalLocal = config.locale;
// Set new one for single using
config.locale = new Locale("en");
context.getResources().updateConfiguration(config, null);
// Get search_options array for english values
String[] searchOptionsEn = getResources().getStringArray(R.array.search_options);
// Set previous location back
config.locale = originalLocal;
getResources().updateConfiguration(config, null);
String valueForSendingToServer = searchOptionsEn[spinner.getSelectedItemPosition()];
You can reference string resources in the string-array for localization.
<string-array name="search_options">
<item>#string/starts_with</item>
<item>#string/equals</item>
<item>#string/ends_with</item>
</string-array>
and then in res/values/strings.xml:
<string name="starts_with">Starts with </string>
and in res/values-fr/string.xml:
<string name="starts_with">Commence par </string>
I just can't figure out how to accomplish the following;
I'd like to display the "human readable form" (refresh_interval_entries), for example in a Log.d(), corresponding to what has been selected in refresh_interval_values.
I have two arrays defined in values\arrays.xml:
<string-array name="refresh_interval_entries" translatable="false">
<item>1 minute</item>
<item>2 minutes</item>
<item>3 minutes</item>
</string-array>
<string-array name="refresh_interval_values" translatable="false">
<item>60</item>
<item>120</item>
<item>180</item>
</string-array>
I save the selected value from refresh_interval_values in a ListPreference.
First I was thinking of doing something like;
String[] mEntries = getResources().getStringArray(R.array.refresh_interval_entries);
But I don't think that will work since I can't get the correct index for mEntries[index], since i can't use the values in refresh_interval_values.
I am not trying to display this in an Activity that extends PreferenceActivity, just in a normal Activity.
Any ideas how to do this?
How about on start of your application, you make a HashMap out of the two arrays:
HashMap<String, String> dictionary = new HashMap<String, String>();
String[] mEntries = getResources().getStringArray(R.array.refresh_interval_entries);
String[] mValues = getResources().getStringArray(R.array.refresh_interval_values);
for (int i = 0; i < mEntries.length; i++) {
dictionary.put(mValues[i], mEntries[i]);
}
and use it like:
String entry = dictionary.get("60");
Do something like this:
{
...
String[] mEntries = getResources().getStringArray(R.array.refresh_interval_entries);
String[] mValues = getResources().getStringArray(R.array.refresh_interval_values);
Log.d(TAG, "120=" + getEntryFromValue("120", mEntries, mValues));
}
private String getEntryFromValue(String value, String[] mEntries, String[] mValues) {
for (int i=0; i < mValues.length; i++) {
if (value.equals(mValues[i])) {
// check mEntries length
return mEntries[i];
}
}
return "NOT FOUND";
}
I have a class like
public class CountryVO {
private String countryCode;
private String countryName;
private Drawable countryFlag;
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public Drawable getCountryFlag() {
return countryFlag;
}
public void setCountryFlag(Drawable countryFlag) {
this.countryFlag = countryFlag;
}
}
and want to store objects of this class in an TypeArray xml of android like
<resources>
<array name="custom_arr">
<item>
<countryName>Albania</countryName>
<countryCode>al</countryCode>
<countryFlag>#drawable/al</countryFlag>
</item>
<item>
<countryName>Algeria</countryName>
<countryCode>dz</countryCode>
<countryFlag>#drawable/dz</countryFlag>
</item>
<item>
<countryName>American Samoa</countryName>
<countryCode>as</countryCode>
<countryFlag>#drawable/as</countryFlag>
</item>
<item>
<countryName>India</countryName>
<countryCode>in</countryCode>
<countryFlag>#drawable/in</countryFlag>
</item>
<item>
<countryName>South Africa</countryName>
<countryCode>sa</countryCode>
<countryFlag>#drawable/sa</countryFlag>
</item>
</array>
</resources>
how i want to access this array in my Activty class like
TypedArray customArr = getResources().obtainTypedArray(R.array.country_arr);
CountryVO vo = new CountryVO();
vo.setCountryName(**value from array come here for first element's countryName attribute**);
vo.setCountryCode(**value from array come here for first element's countryCode attribute**);
vo.setCountryFlag(**value from array come here for first element's countryFlag attribute**);
But i don't to how to achieve this.
I tried customArr.getString(0); but it gives me everything as string like
Albania al #drawable/al
Please help me to solve this problem.
Thanks a lot in advance,
With best regards,
Ishan
Here is example. Read it and look at the methods of TypedArray like get...() for example getDrawable(int index). I would suggest to keep items of the same type in separated arrays.
<array name="country">
<item>Albania</item>
<item>Algeria</item>
<item>American Samoa</item>
</array>
<array name="code">
<item>al</item>
<item>dz</item>
<item>as</item>
</array>
<array name="flag">
<item>#drawable/dz</item>
<item>#drawable/al</item>
<item>#drawable/as</item>
</array>
EDIT:
public CountryVO getCountryVO(int index){
Resources resources = getResources();
TypedArray country = resources.obtainTypedArray(R.array.country);
TypedArray code = resources.obtainTypedArray(R.array.code);
TypedArray flag = resources.obtainTypedArray(R.array.flag);
CountryVO vo = new CountryVO(country.getString(index), code.getString(index), flag.getDrawable(index));
country.recycle();
code.recycle();
flag.recycle();
return vo;
}
When I need custom objects that can be edited outside code i generally use json which is easier to read for both humans and (possibly) machines ;)
You can also have more complex objects than with simple arrays.
Once you create a json file (e.g. countries.json) in the /res/raw folder like this:
{ "countries" : [
{"country" : "Albania", "countryCode" : "al" },
{"country" : "Algeria", "countryCode" : "dz"},
{"country" : "American Samoa", "countryCode" : "as"},
{"country" : "India", "countryCode" : "in"},
{"country" : "South Africa", "countryCode" : "sa"}
]}
you can load the data like this:
InputStream jsonStream = context.getResources().openRawResource(R.raw.countries);
JSONObject jsonObject = new JSONObject(Strings.convertStreamToString(jsonStream));
JSONArray jsonContries = jsonObject.getJSONArray("countries");
List<CountryVO> countries = new ArrayList<CountryVO>();
for (int i = 0, m = countries.length(); i < m; i++) {
JSONObject jsonCountry = countries.getJSONObject(i);
CountryVO country = new CountryVO();
country.setCountryName(jsonCountry.getString("country"));
String co = jsonCountry.getString("countryCode");
country.setCountryCode(co);
try {
Class<?> drawableClass = com.example.R.drawable.class; // replace package
Field drawableField = drawableClass.getField(co);
int drawableId = (Integer)drawableField.get(null);
Drawable drawable = getResources().getDrawable(drawableId);
country.setCountryFlag(drawable);
} catch (Exception e) {
// report exception
}
countries.add(country);
}
If you don't want to do the parsing manually you can also use gson which helps you to pass the objects and then load the drawables in a lazy fashion... ;)
Edit: Added utility class
public String convertStreamToString(InputStream is) {
Scanner s = new Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
Hope it helps
You need to parse the xml before trying to store it in your class. I would recommend that you use the SAX API, you can find a tutorial on it here. Hope this helps!
I have an integer array in an xml file as follows
<integer-array name="myArray">
<item>#drawable/pic1</item>
<item>#drawable/pic2</item>
<item>#drawable/pic3</item>
<item>#drawable/pic4</item>
</integer-array>
In the code, I am trying to load this array
int[] picArray = getResources().getIntArray(R.array.myArray);
The expected result is
R.drawable.pic1, R.drawable.pic2,R.drawable.pic3
but instead it is coming with an array with all values as zero
Can anyone tell me what is wrong?
Found this solution:
TypedArray ar = context.getResources().obtainTypedArray(R.array.myArray);
int len = ar.length();
int[] picArray = new int[len];
for (int i = 0; i < len; i++)
picArray[i] = ar.getResourceId(i, 0);
ar.recycle();
// Do stuff with resolved reference array, resIds[]...
for (int i = 0; i < len; i++)
Log.v (TAG, "Res Id " + i + " is " + Integer.toHexString(picArray[i]));
And resources xml file could be:
<resources>
<integer-array name="myArray">
<item>#drawable/pic1</item>
<item>#drawable/pic2</item>
<item>#drawable/pic3</item>
<item>#drawable/pic4</item>
</integer-array>
</resources>
It looks like you might be talking about typed arrays?
if so a typed array should look like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="icons">
<item>#drawable/home</item>
<item>#drawable/settings</item>
<item>#drawable/logout</item>
</array>
<array name="colors">
<item>#FFFF0000</item>
<item>#FF00FF00</item>
<item>#FF0000FF</item>
</array>
</resources>
Can you show us your actual xml file so we can help you?
EDIT: Yeah those are not integers. make it a resource array if you want to store resources.
You need to get an array with id's of your images.
Probably this article helps you. And so the code you probably need:
int[] picArray = new int[4];
for (int i = 1; i <=4; i++)
{
try
{
Class res = R.drawable.class;
Field field = res.getField("pic"+i);
picArray[i-1] = field.getInt(null);
}
catch (Exception e)
{
Log.e("MyTag", "Failure to get drawable id.", e);
}
}
Just make it a normal resource array. You could do it like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="icons">
<item>#drawable/home</item>
<item>#drawable/settings</item>
<item>#drawable/logout</item>
</array>
</resources>
Then don't make a int[] just make a TypedArray like this:
TypedArray icons = getResources().obtainTypedArray(R.array.icons);
and get it with:
imageview.setImageDrawable(mIcons.getDrawable(position));