Search code examples
androidandroid-custom-viewandroid-custom-attributes

Get multiple style attributes with obtainStyledAttributes


I am trying to obtain several of the style attributes of the android namespace from my code. Here I enclose the relevant extract. AttributeSet attrs is the parameter that is passed in to any custom 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);
}

My issue is that I want to read 4 attributes, described in the int[] ATTRS. As you see I have put textSize as first element of this array. The reason for that is simple - if I swapped it for second place in the array its value is not read correctly (instead the provided default value is loaded). On the other hand the text loads correctly on whichever position in the array of ATTRS I place it. I do not dare experimenting with the position preferences of the gravity and the textColor, but with this permutation they do not work.

Can somebody explain why the ustable behavior of obtaining the attrbutes?


Solution

  • It seems this is a bug in the API. I did tests for 4 attributes: gravity, text, textSize and textColor. Here is the code I used:

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

    The method processAndroidAttributes tries applying all the listed attributes and checks if they were applied or defaults were used. For each iteration I print the array ATTRS contents and whether the real value was used (flagged with 1) or default was used (flagged with 0). Here is what I get after I run the above code (every iteration prints couple of lines):

    [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
    

    As you see this is almost as if expecting the array to be sorted, with only several outliers. I think it is a bug in the Android API as the documentation of obtainStyledAttributes, does not specify to expect any ordering of the attribute ids.