For our current app, almost all of our resources are themed. For the most part this works, but I can't figure out how to parse themed resources out of a resource array.
The code we have for parsing color arrays looks something like this:
TypedArray ca = getResources().obtainTypedArray(id);
int[] colors = new int[ca.length()];
for (int i = 0; i < colors.length; i++)
{
colors[i] = ca.getColor(i, 0);
}
ca.recycle();
That works fine as long as the array looks something like this:
<array name="color_array_foo">
<item>#123456</item>
<item>#789ABC</item>
</array>
But if the array looks like this:
<array name="color_array_foo">
<item>?attr/color_nothing</item>
<item>?attr/color_1</item>
</array>
with the necessary stuff elsewhere in resources like:
<attr name="color_1" format="color"/>
...
<style name="Base" parent="#android:style/Theme.NoTitleBar">
<item name="color_1">#123456</item>
...
</style>
then it throws this exception:
java.lang.UnsupportedOperationException: Can't convert to color: type=0x2
at android.content.res.TypedArray.getColor(TypedArray.java:327)
I've looked around at the various methods of TypedArray, like peekValue() and getResourceId(), but I can't figure out anything that will let me dereference the themed attribute to the actual color value. How do I do that?
Edit: This smells like it's closer, but still isn't right:
TypedArray ca = getResources().obtainTypedArray(id);
int [] c = new int[ca.length()];
for (int i=0; i<c.length; i++)
{
if (ca.peekValue(i).type == TypedValue.TYPE_REFERENCE ||
ca.peekValue(i).type == TypedValue.TYPE_ATTRIBUTE)
{
// FIXME: Probably need to split the above if, and for
// TYPE_ATTRIBUTE, do some additional dereferencing?
c[i] = ca.getResources().getColor(ca.peekValue(i).data);
}
else
{
c[i] = ca.getColor(i, 0);
}
}
ca.recycle();
Use method public boolean resolveAttribute (int resid, TypedValue outValue, boolean resolveRefs)
TypedArray ca = getResources().obtainTypedArray(id);
int[] c = new int[ca.length()];
for (int i = 0; i < c.length; i++) {
if (ca.peekValue(i).type == TypedValue.TYPE_ATTRIBUTE) {
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(ca.peekValue(i).data, typedValue, true);
c[i] = typedValue.data;
} else {
c[i] = ca.getColor(i, 0);
}
}
ca.recycle();
it works for
<resources>
<attr name="color_2" format="color"/>
<color name="color_2">#002</color>
<color name="color_3">#003</color>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="color_2">#color/color_2</item>
</style>
<array name="color_array_foo">
<item>#001</item>
<item>?attr/color_2</item>
<item>#color/color_3</item>
</array>
</resources>
Related
I'm trying to extract the value set on this attribut <item name="android:textStyle">bold</item>
According to the documentation the return values for this attribut are
Normal: 0
Bold: 1
Italic: 2
But I'm always getting 0 for styleVal no matter what is passed in the textStyle!
Everything in the code seems correcet and I can't debug the error
private void getTextViewStyleValue() {
int[] AttrSet = {
android.R.attr.textColor,
android.R.attr.textStyle,
android.R.attr.fontFamily,
};
TypedArray a = context.obtainStyledAttributes(style, AttrSet);
textColor = a.getColor(0, DEFAULT_TEXT_COLOR);
int styleVal = a.getInt(1, 0);
font = Typeface.createFromAsset(context.getAssets(), a.getString(2));
a.recycle();
}
This is what is written about android.R.attr.textStyle's value
I have the following items stored in an array-string in String.xml file
<string-array name="cr">
<item name="x"> 20</item>
<item name="y"> 40</item>
<item name="z"> 60</item>
<item name="k"> 80</item>
<item name="i"> 100</item>
<item name="l"> 120</item>
</string-array>
how can i get the value (eg 80) using the item name in mainactivity.java file?
int index =Arrays.asList(getResources().getStringArray(R.array.cr)).indexOf(..); I tried this but it doesn't work
You can use two array(one for key, one for value) and then put them into Hashmap object.
Example:
String[] mobileArray = getResources().getStringArray(R.array.mobile);
String[] priceArray = getResources().getStringArray(R.array.price);
Map<String, String> map = new HashMap<>();
for (int i = 0; i < mobileArray.length; i++) {
map.put(mobileArray[i], priceArray[i]);
}
strings.xml
<string-array name="mobile">
<item>Samsung</item>
<item>Lenevo</item>
<item>Karbon</item>
<item>Moto</item>
<item>Xperia</item>
<item>Micromax</item>
<item>Lava</item>
<item>Xiomi</item>
</string-array>
<string-array name="price">
<item>10000</item>
<item>12000</item>
<item>10000</item>
<item>12000</item>
<item>10000</item>
<item>12000</item>
<item>10000</item>
<item>12000</item>
</string-array>
I think you need something like this
String[] yourArray = getResources().getStringArray(R.array. cr);
String yourString = yourArray[3];
hope this is what you need
TL;DR I looking for an implementation of public static Drawable getDrawableFromAttribute(Context context, String attrName).
I'm searching for a way, to load dynamic drawables, which are defined in my style with custom attributes. That's my configuration
attr.xml
<resources>
<attr name="custom_image" type="reference">
</resources>
styles.xml
<resources>
<style name="demo">
<item name="custom_image">#drawable/fancy_picture</item>
</style>
</resources>
The fancy_picture is a named /res/drawables/fancy_pictures.xml.
Now, I want someone to enter the string "custom" and "image" and the ImageView should show the fancy_picture in it.
What is the best way to do this? If I use a XML-Layout file, I could write
<ImageView
...
android:src="?custom_image"
...
/>
I didn't use declare-styleable in my style xml and I would like to ignore them completely, if possible.
I found a solution for this
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static Drawable getAttrDrawable(Context context, #AttrRes int attrRes) {
Drawable drawable = null;
TypedValue value = new TypedValue();
if (context.getTheme().resolveAttribute(attrRes, value, true)) {
String[] data = String.valueOf(value.string).split("/");
int resId = context.getResources().getIdentifier(data[2].substring(0, data[2].length() - 4), "drawable", context.getPackageName());
if (resId != 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
drawable = context.getDrawable(resId);
} else {
drawable = context.getResources().getDrawable(resId);
}
}
}
return drawable;
}
public static Drawable getAttrDrawable(Context context, String attr) {
int attrRes = context.getResources().getIdentifier(attr, "attr", context.getPackageName());
if (attrRes != 0) {
return getAttrDrawable(context, attrRes);
}
return null;
}
and it worked well for attr -> xml and attr -> png.
I have this array.xml
<resources>
<string-array name="Abarth">
<item name="id">1</item><item name="title">500</item>
<item name="id">2</item><item name="title">Grande Punto</item>
<item name="id">3</item><item name="title">Punto Evo</item>
<item name="id">4</item><item name="title">500c</item>
<item name="id">5</item><item name="title">695</item>
<item name="id">6</item><item name="title">Punto</item>
</string-array>
<string-array name="Alfa_Romeo">
<item name="id">1</item><item name="title">155</item>
<item name="id">2</item><item name="title">156</item>
<item name="id">3</item><item name="title">159</item>
<item name="id">4</item><item name="title">164</item>
<item name="id">5</item><item name="title">145</item>
<item name="id">6</item><item name="title">147</item>
<item name="id">7</item><item name="title">146</item>
<item name="id">8</item><item name="title">Gtv</item>
<item name="id">9</item><item name="title">Spider</item>
<item name="id">10</item><item name="title">166</item>
<item name="id">11</item><item name="title">Gt</item>
<item name="id">12</item><item name="title">Crosswagon</item>
<item name="id">13</item><item name="title">Brera</item>
<item name="id">14</item><item name="title">90</item>
<item name="id">15</item><item name="title">75</item>
<item name="id">16</item><item name="title">33</item>
<item name="id">17</item><item name="title">Giulietta</item>
<item name="id">18</item><item name="title">Sprint</item>
<item name="id">19</item><item name="title">Mito</item>
</string-array>
<array name="marcas">
<item>#array/Abarth</item>
<item>#array/Alfa_Romeo</item>
</array>
</resources>
I want to get the content of the array marcas and the name of the subarrays, like "Abarth" or "Alfa_Romeo".
How can I do this? In other post I have read the next code, but it is for obtain the entire array, not only a part of the array.
Resources res = getResources();
TypedArray ta = res.obtainTypedArray(R.array.marcas);
int n = ta.length();
String[][] car = new String[n][];
for (int i = 0; i < n; ++i) {
int id = ta.getResourceId(i, 0);
if (id > 0) {
car[i] = res.getStringArray(id);
} else {
// Error en el XML
}
}
Thank you.
I want to get the content of the array marcas and the name of the
subarrays, like "Abarth" or "Alfa_Romeo".
I don't know if i correctly understood your question but to obtain name of arrays you can use this:
TypedArray parent = getResources().obtainTypedArray(R.array.marcas);
List<String> childs = new ArrayList<String>();
for (int i = 0; i < parent.length(); i++) {
int id = parent.getResourceId(i, 0);
if (id > 0) {
childs.add(getResources().getResourceEntryName(id));
}
}
parent.recycle();
Output:
Abarth
Alfa_Romeo
You have done everything well, To get the TypedArray resource name you need to use getResourceEntryName. Add the following code to get the resourceEntryName, to get what you looking for.
getResources().getResourceEntryName(id);
This will give you the output "Abarth" and "Alfa_Romeo".
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));