使用数组引用作为自定义Android视图的XML属性

36

这个问题已经解决,详见评论。

我正在扩展一个现有的Android View并加载一些自定义属性,如使用XML声明自定义Android UI元素定义自定义属性中所述。

布尔和整数格式的属性工作正常,但当我尝试指定对数组资源的引用时,应用程序在启动时崩溃。我已经在一个XML资源文件中定义了一个整数数组,并尝试将其用作自定义视图的属性。

我可以使用数组资源来设置android Spinner类的“entries”属性而不出错,因此似乎是我的实现存在问题。 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
这个问题已经解决了,原因是我在类构造函数中加载属性的方式出现了错误。之前,我使用了TypedArray的getInt()方法,但实际上应该使用"reference"格式的getResourceId()方法。 - Michael
3个回答

51

我会跟进你的问题,因为如果你在谷歌搜索“数组引用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();
    }
}

随后,当您将自定义视图添加到XML布局文件中时,您应该能够通过android:entries属性引用字符串数组。例如:

<com.example.myapp.MyCustomView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:entries="@array/my_array_of_strings" />

这正是在ListView类中的实现方式(查看源代码,你会看到)。

2
我想将一个可绘制数组作为参数传递..有什么帮助吗? - Dominic D'Souza

20

另一个答案对于字符串数组非常有效。然而,在引用数组上,例如arr.getTextArray(...),则不太适用。

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

将会给你res/drawable/a.png作为CharSequence而不是资源id。

解析引用数组的正确方式如下:

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

你在这里引用的变量"RES"是什么?res.obtainTypedArray(arrayResourceId); - Rich Morey
res只是资源,例如context.getResources()。 - Jin

9
问题是获取一个整数数组,对于我的情况,我需要从一个数组中读取颜色(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

希望这能帮助一些人。

这对于获取颜色资源数组非常完美。 - Harihar Das

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接