我试图从我的代码中获取android
命名空间的几个样式属性。在这里,我附上相关的摘录。 AttributeSet attrs
是传递给任何自定义TextView
的参数。
private static final int[] ATTRS = new int[] { android.R.attr.textSize,
android.R.attr.text, android.R.attr.textColor,
android.R.attr.gravity };
private void processAndroidAttributes(final Context context,
final AttributeSet attrs) {
final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
try {
final String text = a.getString(1);
myTextView.setText(text);
final float textSize = a.getDimensionPixelSize(0, DEFAULT_TEXT_SIZE);
myTextView.setTextSize(textSize);
}
我的问题是我想阅读int[]
ATTRS
中描述的4个属性。如您所见,我已将textSize
作为此数组的第一个元素。原因很简单 - 如果我将它换成数组中的第二位,则其值无法正确读取(而是加载提供的默认值)。另一方面,文本正确地加载到我放置的ATTRS
数组中的任何位置。我不敢尝试gravity
和textColor
的排名首选项,但是这种排列方式不起作用。
有人可以解释为什么获得属性的不稳定行为吗?
答案 0 :(得分:10)
这似乎是API中的一个错误。我对4个属性进行了测试:gravity
,text
,textSize
和textColor
。这是我使用的代码:
private void processAndroidAttributes(final Context context, final AttributeSet attrs) {
ATTRS = new Integer[] {
android.R.attr.textSize, android.R.attr.text,
android.R.attr.textColor, android.R.attr.gravity };
Arrays.sort(ATTRS);
do {
printPermutation(ATTRS);
tryApplyingStyles(context, attrs, ATTRS);
ATTRS = nextPermutation(ATTRS);
} while ((ATTRS = nextPermutation(ATTRS)) != null);
}
方法processAndroidAttributes
尝试应用所有列出的属性,并检查它们是否已应用或使用了默认值。对于每次迭代,我打印数组ATTRS
内容以及是否使用了实际值(标记为1
)或使用了默认值(标记为0
)。以下是我运行上面代码后得到的结果(每次迭代打印几行):
[16842901,16842904,16842927,16843087]
1111
[16842901,16842904,16843087,16842927]
1110
[16842901,16842927,16842904,16843087]
1101
[16842901,16842927,16843087,16842904]
1101
[16842901,16843087,16842904,16842927]
1100
[16842901,16843087,16842927,16842904]
1100
[16842904,16842901,16842927,16843087]
1011
[16842904,16842901,16843087,16842927]
1010
[16842904,16842927,16842901,16843087]
1011
[16842904,16842927,16843087,16842901]
1011
[16842904,16843087,16842901,16842927]
1010
[16842904,16843087,16842927,16842901]
1010
[16842927,16842901,16842904,16843087]
1001
[16842927,16842901,16843087,16842904]
1001
[16842927,16842904,16842901,16843087]
1001
[16842927,16842904,16843087,16842901]
1001
[16842927,16843087,16842901,16842904]
1001
[16842927,16843087,16842904,16842901]
1001
[16843087,16842901,16842904,16842927]
1000
[16843087,16842901,16842927,16842904]
1000
[16843087,16842904,16842901,16842927]
1000
[16843087,16842904,16842927,16842901]
1000
[16843087,16842927,16842901,16842904]
1000
[16843087,16842927,16842904,16842901]
1000
如您所见,这几乎就像期望对数组进行排序一样,只有几个异常值。我认为这是Android API中的一个错误,因为obtainStyledAttributes
的文档没有指定期望任何属性ID的排序。
答案 1 :(得分:0)
尝试使用3种不同类型获取4个属性时遇到同样的问题。始终只有一种类型的属性传递给数组,而这始终是第一种。 例如,如果声明{int,String,Color}之类的属性:
private static final int[] ATTRS = new int[] { android.R.attr.textSize,
android.R.attr.text, android.R.attr.textColor }
方法obtainStyledAttributes
将只传递给你的TypedArray
int属性,其余的将为null。
如果您将订单更改为{String,Color,int}:
private static final int[] ATTRS = new int[] {android.R.attr.text, android.R.attr.textColor, android.R.attr.textSize }
您将只获得TypedArray
的String属性,其余为null。
看起来TypedArray
只能包含一个Type,因此您需要声明更多的TypeArrays - 每种类型的属性都有一个。
像这样:
private static final int[] stringAttrs = new int[] {android.R.attr.text};
private static final int[] intAttrs = new int[] {android.R.attr.textSize};
private static final int[] colorAttrs = new int[] {android.R.attr.textColor, android.R.attr.background};
private void processAndroidAttributes(final Context context,
final AttributeSet attrs) {
final TypedArray stringA = context.obtainStyledAttributes(attrs, stringAttrs);
final TypedArray intA = context.obtainStyledAttributes(attrs, intAttrs);
final TypedArray colorA = context.obtainStyledAttributes(attrs, colorAttrs);
myTextView.setText(stringA.getString(0));
myTextView.setTextSize(intA.getDimensionPixelSize(0, DEFAULT_TEXT_SIZE));
myTextView.setTextColor(colorA.getColor(0, Color.WHITE));
myTextView.setBackgroundColor(colorA.getColor(1, Color.WHITE));
stringA.recycle();
intA.recycle();
colorA.recycle();
}
答案 2 :(得分:0)
我很惊讶有人和我有同样的结论。 我已决定为obtainStyledAttributes使用一个唯一的项数组,这样我就不必担心订单了。
http://androidxref.com/2.2.3/xref/frameworks/base/core/jni/android_util_AssetManager.cpp#911 我没有密切关注这个来源,但我想android只按升序顺序迭代一次AttributeSet。
答案 3 :(得分:0)
我认为这可能是因为int []通常来自xml,并且会在“编译”时进行排序,例如检查用例:
How to: Define theme (style) item for custom widget
其中数组来自R.styleable.CustomImageButton而不是手工制作。
我可以理解它们使用和期望排序数组,因为在编译时优化xml资源有很多工作要做,以便在运行时有效地使用它们。
答案 4 :(得分:0)
我确认讨论的问题,添加一个简单的解决方案以供将来参考。有关详细信息,请参阅其他答案。
注意2件事:
我们调用obtainStyledAttributes(AttributeSet,int [],int int)
public static int[] getCommonStyledAttributes() {
return new int[] {
R.attr.bottom, //0
R.attr.height, //1
R.attr.layout, //2
R.attr.left, //3
R.attr.paddings, //4
R.attr.right, //5
R.attr.top, //6
R.attr.width //7
};
}
TypedArray a = context.getTheme().obtainStyledAttributes(paramAttributeSet, getCommonStyledAttributes(), 0, 0);
this.mWidth = a.getInt(7, 0);
this.mHeight = a.getInt(1, 0);
this.left = a.getInt(3, 0);
this.top = a.getInt(6, 0);
this.right = a.getInt(5, 0);
this.bottom = a.getInt(0, 0);
this.type = a.getInt(2, 0);
a.recycle();