Использование ссылки на массив в качестве атрибута XML для пользовательского представления Android - PullRequest
27 голосов
/ 30 октября 2011

Эта проблема была решена, подробности см. В комментариях.

Я расширяю существующее представление Android и загружаю некоторые пользовательские атрибуты, как описано в Объявление пользовательского элемента пользовательского интерфейса Android с использованием XML и Определение пользовательских атрибутов .

Атрибуты с логическим и целочисленным форматами работают нормально, но когда я пытаюсь указать ссылку на ресурс массива, приложение вылетает при запуске.Я определил целочисленный массив в файле ресурсов xml, и я пытаюсь использовать его в качестве атрибута для пользовательского представления.

Я могу использовать ресурс массива для установки атрибута "records" для 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" />

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

Ответы [ 3 ]

42 голосов
/ 03 января 2013

Просто собираюсь прояснить ваш вопрос здесь, так как ваше сообщение появляется первым, если вы что-то вроде Google "например, ссылка на массив, настраиваемое представление атрибута XML", так что кто-то может найти это полезным.* Если вы хотите, чтобы ваш пользовательский вид ссылался на массив строк , вы можете использовать существующий атрибут Android android:entries XML вместо создания совершенно нового пользовательского атрибута.

Просто выполните следующеев 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 (посмотрите в исходном коде, вы увидите).

14 голосов
/ 03 июня 2016

Другой ответ хорошо работает с массивом строк . Однако arr.getTextArray(...) на массиве ссылок , например,

<array name="tmp">
  <item>@drawable/a</item>
  <item>@drawable/b</item>
</array>

даст вам res/drawable/a.png в качестве CharSequence вместо идентификатора ресурса.

Правильный способ анализа массива ссылок:

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();
4 голосов
/ 11 марта 2018

Вопрос в том, чтобы получить массив целых чисел, для моего случая мне нужно прочитать цвета (int) из массива для моего настраиваемого представления, определения, как показано ниже:

<declare-styleable name="ColorPickerView">
        <attr name="colors" format="reference" />
    </declare-styleable>

Затем я используюмой пользовательский вид, как показано ниже:

<com.rainliu.colorpicker.ColorPickerView
    android:id="@+id/rtePalette"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    colorPickerView:colors="@array/colorPickerColors"
    />

Определение цветов выглядит следующим образом:

<resources>
    <color name="colorPrimary">#FF9800</color>
    <array name="colorPickerColors">
        <item>#000000</item>
        <item>#E65100</item>
        <item>@color/colorPrimary</item>
    </array>
</resources>

Так что мне нужно получить цвета в моем пользовательском представлении (ColorPickerView), код, как показано ниже:

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();

Вот распечатка 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

Надеюсь, это поможет некоторым парням.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...