Подтвердить что ты не робот

Использование ссылки массива в качестве атрибута 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" />

И это приводит к сбою приложения немедленно. Кроме того, если я ссылаюсь на ресурс цвета вместо массива, то приложение не сбой. Кто-нибудь знает, как справиться с этой проблемой?

4b9b3361

Ответ 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();