Я пытаюсь получить некоторые из атрибутов стиля пространства имен 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); }
Моя проблема в том, что я хочу читать 4 атрибута, описанных в int[]
ATTRS
. Как вы видите, я поместил textSize
качестве первого элемента этого массива. Причина этого проста – если я поменял ее на второе место в массиве, ее значение не будет правильно прочитано (вместо этого будет загружено заданное значение по умолчанию). С другой стороны, текст правильно загружается в зависимости от того, какое место в массиве ATTRS
я его размещаю. Я не смею экспериментировать с позиционными предпочтениями gravity
и textColor
, но с этой перестановкой они не работают.
Может ли кто-нибудь объяснить, почему мы наблюдаем поведение получения attrbutes?
Кажется, это ошибка в API. Я тестировал 4 атрибута: gravity
, text
, textSize
и text
. Вот код, который я использовал:
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
содержимое массива 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
Как вы видите, это почти похоже на ожидание сортировки массива с несколькими выбросами. Я думаю, что это ошибка в API Android, поскольку документация obtainStyledAttributes
не указывает, чтобы ожидать какого-либо упорядочения идентификаторов атрибутов.
У меня такая же проблема, пытаясь получить 4 атрибута с 3 различными типами. Всегда только один тип атрибута переходит к массиву, и это всегда было первым из них. Например, если вы объявляете такие атрибуты, как {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 }
Вы получите только атрибуты String для вашего TypedArray
, остальные будут TypedArray
.
Похоже, что TypedArray
может содержать только один тип, поэтому вам нужно объявить больше 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(); }
Я удивлен, что у кого-то был такой же вывод со мной. Я решил использовать только один массив элементов для getStyledAttributes, так что мне не нужно беспокоиться о порядке.
http://androidxref.com/2.2.3/xref/frameworks/base/core/jni/android_util_AssetManager.cpp#911 Я не смотрел на этот источник близко, но я предполагаю, что андроид выполняет итерацию AttributeSet только один раз в порядке возрастания эффективность.
Я думаю, это может быть потому, что int [], как правило, исходил из xml и сортировался, когда он был «скомпилирован», например, здесь можно проверить вариант использования:
Как определить тему (стиль) для настраиваемого виджета
Где массив поступает из R.styleable.CustomImageButton, а не создается вручную.
Я могу понять их использование и ожидание сортированных массивов, так как в процессе компиляции очень много работы по оптимизации ресурсов xml, чтобы они могли эффективно использоваться во время выполнения.
Я подтверждаю обсуждаемый вопрос, добавив простое решение для дальнейшего использования. Для получения дополнительной информации см. Другие ответы.
Обратите внимание на 2 вещи:
Мы вызываем getStyledAttributes (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();