Reputation: 361
This problem has been solved, see comments for details.
I am extending an existing Android View and loading some custom attributes, as described in Declaring a custom android UI element using XML and Defining custom attrs.
Attributes with boolean and integer formats work fine, but when I try to specify a reference to an array resource, the application crashes at launch. I have defined an integer array inside an xml resource file and I'm trying to use it as an attribute for the custom view.
I can use the array resource to set the "entries" attribute of the android Spinner class with no errors, so it seems to be a problem in my implementation. The logcat messages don't seem to supply any specific information about the crash, but I'm still looking so I will update if I find something.
The attributes are declared by (in attrs.xml):
<declare-styleable name="CustomView">
<attr name="values" format="reference"/>
<attr name="isActive" format="boolean"/>
</declare-styleable>
The array is defined as (in arrays.xml):
<integer-array name="nums">
<item>1</item>
<item>2</item>
<item>3</item>
</integer-array>
And I am referencing the array by:
<com.test.CustomView cv:values="@array/nums" />
And this causes the application to crash immediately. In addition, if I reference a color resource instead of an array then the application does not crash. Does anybody know how to deal with this problem?
Upvotes: 36
Views: 21280
Reputation: 6145
The other answer works well with array of strings. However, arr.getTextArray(...)
on array of references, e.g.
<array name="tmp">
<item>@drawable/a</item>
<item>@drawable/b</item>
</array>
will give you res/drawable/a.png
as the CharSequence instead of the resource id.
The proper way to parse an array of references is this:
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
int arrayResourceId = typedArray.getResourceId(R.styleable.CustomView_CustomAttr, 0);
if (arrayResourceId != 0) {
final TypedArray resourceArray = getResources().obtainTypedArray(arrayResourceId);
for (int i = 0; i < resourceArray.length(); i++) {
final int resourceId = resourceArray.getResourceId(i, 0);
// do stuff with resourceId, such as getResources().getDrawable(resourceId)
}
resourceArray.recycle();
}
typedArray.recycle();
Upvotes: 20
Reputation: 1326
The question is about obtain an integer array, for my case, I need to read the colors(int) from an array for my custom view, styeable definition as below:
<declare-styleable name="ColorPickerView">
<attr name="colors" format="reference" />
</declare-styleable>
Then I use my custom view like below:
<com.rainliu.colorpicker.ColorPickerView
android:id="@+id/rtePalette"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
colorPickerView:colors="@array/colorPickerColors"
/>
The colors definition is as below:
<resources>
<color name="colorPrimary">#FF9800</color>
<array name="colorPickerColors">
<item>#000000</item>
<item>#E65100</item>
<item>@color/colorPrimary</item>
</array>
</resources>
So I need to obtain the colors in my custom view (ColorPickerView), code as below:
TypedArray ta = context.obtainStyledAttributes(attributeSet, R.styleable.ColorPickerView);
int colorsId = ta.getResourceId(R.styleable.ColorPickerView_colors, 0);
int[] colorsArray = ta.getResources().getIntArray(colorsId);
for (int a : colorsArray) {
Log.e("AA", "color == " + a);
}
ta.recycle();
Here is the print of colorsArray:
03-11 14:25:53.894 15300-15300/com.chinalwb.are E/AA: color == -16777216
03-11 14:25:53.894 15300-15300/com.chinalwb.are E/AA: color == -1683200
03-11 14:25:53.894 15300-15300/com.chinalwb.are E/AA: color == -1683200
Hope this will help some guys.
Upvotes: 10
Reputation: 22404
Just going to piggyback off your question here, since your post shows up first if you google something like "array reference XML attribute custom view", so someone might find this helpful.
If you want your custom view to reference an array of strings, you can use Android's existing android:entries
XML attribute, instead of creating a totally new custom attribute.
Just do the following in res/values/attrs.xml
:
<resources>
<declare-styleable name="MyCustomView">
<attr name="android:entries" />
</declare-styleable>
</resources>
Then do this in your custom View's constructor:
public MyCustomView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
try
{
CharSequence[] entries = a.getTextArray(R.styleable.MyCustomView_android_entries);
if (entries != null)
{
//do something with the array if you want
}
}
finally
{
a.recycle();
}
}
And then you should be able to reference a string array via the android:entries
attribute when you add your custom View to an XML layout file. Example:
<com.example.myapp.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/my_array_of_strings" />
This is exactly how it is done in the ListView class (look in the source, you'll see).
Upvotes: 52