Использование ссылки массива в качестве атрибута XML для пользовательского вида Android
Эта проблема решена, см. комментарии для деталей.
Я расширяю существующий Android View и загружаю некоторые пользовательские атрибуты, как описано в Объявление пользовательского элемента пользовательского интерфейса Android с использованием XML и Определение пользовательских атрибутов.
Атрибуты с логическими и целочисленными форматами работают нормально, но когда я пытаюсь указать ссылку на ресурс массива, приложение запускается при запуске. Я определил целочисленный массив внутри файла ресурсов xml, и я пытаюсь использовать его как атрибут для пользовательского представления.
Я могу использовать ресурс массива, чтобы установить атрибут "entries" класса Android Spinner без ошибок, поэтому, похоже, это проблема в моей реализации. Сообщения logcat, похоже, не содержат никакой конкретной информации о сбое, но я все еще смотрю, поэтому я буду обновлять, если найду что-то.
Атрибуты объявляются (в attrs.xml):
<declare-styleable name="CustomView">
<attr name="values" format="reference"/>
<attr name="isActive" format="boolean"/>
</declare-styleable>
Массив определяется как (в файле arrays.xml):
<integer-array name="nums">
<item>1</item>
<item>2</item>
<item>3</item>
</integer-array>
И я ссылаюсь на массив по:
<com.test.CustomView cv:values="@array/nums" />
И это приводит к сбою приложения немедленно. Кроме того, если я ссылаюсь на ресурс цвета вместо массива, то приложение не сбой. Кто-нибудь знает, как справиться с этой проблемой?
Ответы
Ответ 1
Просто перейдем к вашему вопросу здесь, так как ваше сообщение появляется сначала, если у вас Google что-то вроде "настраиваемого вида атрибута XML-атрибута массива", поэтому кто-то может найти это полезным.
Если вы хотите, чтобы ваше пользовательское представление ссылалось на массив строк, вы можете использовать существующий XML-атрибут android:entries
для Android, вместо создания абсолютно нового настраиваемого атрибута.
В res/values/attrs.xml
выполните следующие действия:
<resources>
<declare-styleable name="MyCustomView">
<attr name="android:entries" />
</declare-styleable>
</resources>
Затем сделайте это в своем пользовательском конструкторе вида:
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();
}
}
И тогда вы должны иметь возможность ссылаться на массив строк с помощью атрибута android:entries
, когда вы добавляете свой собственный вид в файл макета XML. Пример:
<com.example.myapp.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/my_array_of_strings" />
Именно это делается в классе ListView (смотрите в исходном коде, как вы увидите).
Ответ 2
Поздний ответ, другой ответ хорошо работает, если массив представляет собой строковый массив. Однако arr.getTextArray(...)
, когда массив представляет собой массив ссылок, например
<array name="tmp">
<item>@drawable/a</item>
<item>@drawable/b</item>
</array>
даст вам res/drawable/a.png
как charsequence вместо идентификатора ресурса.
Правильный способ анализа массива ссылок выглядит следующим образом:
final TypedArray arr = c.obtainStyledAttributes(attrs, R.styleable.CustomView);
final int arrayResourceId = arr.getResourceId(
R.styleabe.CustomView_CustomAttr, 0);
if (arrayResourceId != 0) {
final TypedArray resourceArray = res.obtainTypedArray(arrayResourceId);
for (int i = 0; i < resourceArray.length(); i++) {
final int resourceId = resourceArray.getResourceId(i, 0);
// do stuff with resourceId, such as res.getDrawable(resourceId)
}
resourceArray.recycle();
}
arr.recycle();