4

Я пытаюсь получить несколько атрибутов стиля пространства имен android из моего кода. Здесь я прилагаю соответствующий экстракт. AttributeSet attrs - это параметр, который передается любому производителю TextView.Получить несколько атрибутов стиля с помощью getStyledAttributes

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?

ответ

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 

Как вы видите, это почти, как будто ожидая, что массив будет отсортирован, только с несколькими недопустимыми. Я думаю, что это ошибка в API Android, поскольку документация obtainStyledAttributes, не указывает, ожидать какого-либо упорядочения идентификаторов атрибутов.

+0

Интересно, что я пришел к такому же выводу. Странно, что это поведение не документировано или не описано в другом месте. – miha

1

У меня такая же проблема, пытаясь получить 4 атрибута с 3 различными типами. Всегда только один тип атрибута переходит к массиву, и это всегда было первым из них. Например, если вы объявляете атрибуты, как {INT, String, цвет}:

private static final int[] ATTRS = new int[] { android.R.attr.textSize, 
    android.R.attr.text, android.R.attr.textColor } 

Метод obtainStyledAttributes переходит к вашему TypedArray только междунару атрибуты, остальное будет нулевым.

Если изменить порядок {String, Color, Int}:

private static final int[] ATTRS = new int[] {android.R.attr.text, android.R.attr.textColor, android.R.attr.textSize } 

вы получите только Струнный атрибуты вашего 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(); 

    } 
+1

Пробовал ли вы сортировать атрибуты, потому что в моем случае, по крайней мере, мне не нужно было отделять массивы ... –

+0

Вы правы, его просто нужно сортировать ... – Warcello

+0

Это как раз то, что говорят мои эксперименты :) Подумайте о том, чтобы поддержать предложенный мной solutino. –

0

Я удивлен, что кто-то просто был такой же вывод со мной. Я решил использовать только один массив элементов для полученияStyledAttributes, так что мне не нужно беспокоиться о порядке.

http://androidxref.com/2.2.3/xref/frameworks/base/core/jni/android_util_AssetManager.cpp#911 Я не рассматривал этот источник близко, но я предполагаю, что андроид выполняет итерацию AttributeSet только один раз в порядке возрастания по эффективности.

+0

Я не думаю, что это так просто, итерация только один раз в порядке возрастания - некоторые из результатов, которые я получил, когда итерация всех перестановок не соответствует этому –

0

Я думаю, что это может быть потому, что ИНТ [], как правило, пришли из XML и будет отсортирован, когда он был «составлен», например, проверить случай использования здесь:

How to: Define theme (style) item for custom widget

где массив происходит от R.styleable.CustomImageButton, а не от руки.

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

0

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

Примечание 2 вещи:

  1. INT [] ATTRS массив ценности имена сортируются в алфавитном порядке
  2. мы называем obtainStyledAttributes (AttributeSet, 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(); 
    
+0

Благодарим за подтверждение. Однако я скорее рекомендую сортировать атрибуты, а не жестко кодировать определенные значения. –

+0

Ну, ключ в том, что его нужно сортировать. И разработчик должен решить, хочет ли он это автоматически, с помощью служебного метода или жесткого кодирования. Hardcoded отлично подходит для моего дела – AAverin

Смежные вопросы