问题
I am creating a custom view in Android. In it's constructor I am obtaining some of the attributes that are set in the XML layout file. The code is like this:
public LabeledEditText(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray styledAttrs = context.getTheme().obtainStyledAttributes(attrs, new int[] { android.R.attr.id, android.R.attr.digits, android.R.attr.padding, android.R.attr.inputType }, 0, 0);
try {
int id = styledAttrs.getResourceId(styledAttrs.getIndex(0), -1);
String digits = styledAttrs.getString(styledAttrs.getIndex(1));
float padding = styledAttrs.getDimension(styledAttrs.getIndex(2), 0.1f);
int inputType = styledAttrs.getInt(styledAttrs.getIndex(3), -1);
} finally {
styledAttrs.recycle();
}
}
The problem is that obtainStyledAttributes does not obtain all the attributes, even though they exist in the attribute set. What's even stranger, is that if I change the ordering of the ids in the int array I get different results. For example, if I use the following ordering
new int[] { android.R.attr.id, android.R.attr.digits, android.R.attr.padding, android.R.attr.inputType }
I get back 3 attributes, but if I use the following ordering
new int[] {android.R.attr.digits, android.R.attr.padding, android.R.attr.inputType, android.R.attr.id }
I get back 2. I'm including 2 screenshots of the watches window of these 2 cases. The breakpoint is set just after the try statement.
In any case if I obtain the attributes one at a time, it works for all of them. How does obtainStyledAttributes works? Also I'm not sure if I should use the styledAttrs.getIndex(i) function or not, but that is a problem after the current one is solved.
回答1:
Although it is not documented, obtainStyledAttributes
expects a sorted array, and its code is optimized with that assumption.
So you need to provide your styledAttrs
array with the elements sorted in ascending order according to their id values.
There are several ways you can determine the correct order:
- based on their relative position in the resources
- by checking their relative values and changing the array to match
- or by sorting the array elements programmatically
If you choose to sort the array programmatically at run time, make sure you use the appropriate (sorted) index when calling getString()
etc.
Another common workaround is to only get a single value with obtainStyledAttributes
at a time. (An array with one element is already sorted.)
Also I'm not sure if I should use the styledAttrs.getIndex(i) function or not
I believe that's only necessary if you're looping through the TypedArray
and its possible some of the elements may not have values; it basically "hides" the null elements for you as though it were a sparse array. In general I don't think it's necessary unless you're accessing styled resources in certain ways, for example when implementing a custom view.
Most of the time I use custom theme attributes that aren't related to a view at all, and in those cases I've always found TypedArray.getIndex()
to be redundant.
来源:https://stackoverflow.com/questions/32273576/android-custom-view-obtain-multiple-attributes