blob: 83d48aa4654237f3abf6350c860e514d42071b02 [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017package android.content.res;
18
Dianne Hackborn1d0b1772013-09-06 14:02:54 -070019import android.content.pm.ActivityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.graphics.drawable.Drawable;
21import android.util.AttributeSet;
22import android.util.DisplayMetrics;
23import android.util.Log;
24import android.util.TypedValue;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080025
26import com.android.internal.util.XmlUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
28import java.util.Arrays;
29
30/**
31 * Container for an array of values that were retrieved with
32 * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
33 * or {@link Resources#obtainAttributes}. Be
34 * sure to call {@link #recycle} when done with them.
35 *
36 * The indices used to retrieve values from this structure correspond to
37 * the positions of the attributes given to obtainStyledAttributes.
38 */
39public class TypedArray {
40 private final Resources mResources;
41 /*package*/ XmlBlock.Parser mXml;
42 /*package*/ int[] mRsrcs;
43 /*package*/ int[] mData;
44 /*package*/ int[] mIndices;
45 /*package*/ int mLength;
Xavier Ducrohet7f9f99ea2011-08-11 10:16:17 -070046 /*package*/ TypedValue mValue = new TypedValue();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047
48 /**
49 * Return the number of values in this array.
50 */
51 public int length() {
52 return mLength;
53 }
54
55 /**
56 * Return the number of indices in the array that actually have data.
57 */
58 public int getIndexCount() {
59 return mIndices[0];
60 }
61
62 /**
63 * Return an index in the array that has data.
64 *
65 * @param at The index you would like to returned, ranging from 0 to
66 * {@link #getIndexCount()}.
67 *
68 * @return The index at the given offset, which can be used with
69 * {@link #getValue} and related APIs.
70 */
71 public int getIndex(int at) {
72 return mIndices[1+at];
73 }
74
75 /**
76 * Return the Resources object this array was loaded from.
77 */
78 public Resources getResources() {
79 return mResources;
80 }
81
82 /**
83 * Retrieve the styled string value for the attribute at <var>index</var>.
84 *
85 * @param index Index of attribute to retrieve.
86 *
87 * @return CharSequence holding string data. May be styled. Returns
88 * null if the attribute is not defined.
89 */
90 public CharSequence getText(int index) {
91 index *= AssetManager.STYLE_NUM_ENTRIES;
92 final int[] data = mData;
93 final int type = data[index+AssetManager.STYLE_TYPE];
94 if (type == TypedValue.TYPE_NULL) {
95 return null;
96 } else if (type == TypedValue.TYPE_STRING) {
97 return loadStringValueAt(index);
98 }
99
100 TypedValue v = mValue;
101 if (getValueAt(index, v)) {
102 Log.w(Resources.TAG, "Converting to string: " + v);
103 return v.coerceToString();
104 }
105 Log.w(Resources.TAG, "getString of bad type: 0x"
106 + Integer.toHexString(type));
107 return null;
108 }
109
110 /**
111 * Retrieve the string value for the attribute at <var>index</var>.
112 *
113 * @param index Index of attribute to retrieve.
114 *
115 * @return String holding string data. Any styling information is
116 * removed. Returns null if the attribute is not defined.
117 */
118 public String getString(int index) {
119 index *= AssetManager.STYLE_NUM_ENTRIES;
120 final int[] data = mData;
121 final int type = data[index+AssetManager.STYLE_TYPE];
122 if (type == TypedValue.TYPE_NULL) {
123 return null;
124 } else if (type == TypedValue.TYPE_STRING) {
125 return loadStringValueAt(index).toString();
126 }
127
128 TypedValue v = mValue;
129 if (getValueAt(index, v)) {
130 Log.w(Resources.TAG, "Converting to string: " + v);
131 CharSequence cs = v.coerceToString();
132 return cs != null ? cs.toString() : null;
133 }
134 Log.w(Resources.TAG, "getString of bad type: 0x"
135 + Integer.toHexString(type));
136 return null;
137 }
138
139 /**
140 * Retrieve the string value for the attribute at <var>index</var>, but
141 * only if that string comes from an immediate value in an XML file. That
142 * is, this does not allow references to string resources, string
143 * attributes, or conversions from other types. As such, this method
144 * will only return strings for TypedArray objects that come from
145 * attributes in an XML file.
146 *
147 * @param index Index of attribute to retrieve.
148 *
149 * @return String holding string data. Any styling information is
150 * removed. Returns null if the attribute is not defined or is not
151 * an immediate string value.
152 */
153 public String getNonResourceString(int index) {
154 index *= AssetManager.STYLE_NUM_ENTRIES;
155 final int[] data = mData;
156 final int type = data[index+AssetManager.STYLE_TYPE];
157 if (type == TypedValue.TYPE_STRING) {
158 final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
159 if (cookie < 0) {
160 return mXml.getPooledString(
161 data[index+AssetManager.STYLE_DATA]).toString();
162 }
163 }
164 return null;
165 }
166
167 /**
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800168 * @hide
169 * Retrieve the string value for the attribute at <var>index</var> that is
170 * not allowed to change with the given configurations.
171 *
172 * @param index Index of attribute to retrieve.
173 * @param allowedChangingConfigs Bit mask of configurations from
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700174 * {@link Configuration}.NATIVE_CONFIG_* that are allowed to change.
175 *
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800176 * @return String holding string data. Any styling information is
177 * removed. Returns null if the attribute is not defined.
178 */
179 public String getNonConfigurationString(int index, int allowedChangingConfigs) {
180 index *= AssetManager.STYLE_NUM_ENTRIES;
181 final int[] data = mData;
182 final int type = data[index+AssetManager.STYLE_TYPE];
183 if ((data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS]&~allowedChangingConfigs) != 0) {
184 return null;
185 }
186 if (type == TypedValue.TYPE_NULL) {
187 return null;
188 } else if (type == TypedValue.TYPE_STRING) {
189 return loadStringValueAt(index).toString();
190 }
191
192 TypedValue v = mValue;
193 if (getValueAt(index, v)) {
194 Log.w(Resources.TAG, "Converting to string: " + v);
195 CharSequence cs = v.coerceToString();
196 return cs != null ? cs.toString() : null;
197 }
198 Log.w(Resources.TAG, "getString of bad type: 0x"
199 + Integer.toHexString(type));
200 return null;
201 }
202
203 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 * Retrieve the boolean value for the attribute at <var>index</var>.
205 *
206 * @param index Index of attribute to retrieve.
207 * @param defValue Value to return if the attribute is not defined.
208 *
209 * @return Attribute boolean value, or defValue if not defined.
210 */
211 public boolean getBoolean(int index, boolean defValue) {
212 index *= AssetManager.STYLE_NUM_ENTRIES;
213 final int[] data = mData;
214 final int type = data[index+AssetManager.STYLE_TYPE];
215 if (type == TypedValue.TYPE_NULL) {
216 return defValue;
217 } else if (type >= TypedValue.TYPE_FIRST_INT
218 && type <= TypedValue.TYPE_LAST_INT) {
219 return data[index+AssetManager.STYLE_DATA] != 0;
220 }
221
222 TypedValue v = mValue;
223 if (getValueAt(index, v)) {
224 Log.w(Resources.TAG, "Converting to boolean: " + v);
225 return XmlUtils.convertValueToBoolean(
226 v.coerceToString(), defValue);
227 }
228 Log.w(Resources.TAG, "getBoolean of bad type: 0x"
229 + Integer.toHexString(type));
230 return defValue;
231 }
232
233 /**
234 * Retrieve the integer value for the attribute at <var>index</var>.
235 *
236 * @param index Index of attribute to retrieve.
237 * @param defValue Value to return if the attribute is not defined.
238 *
239 * @return Attribute int value, or defValue if not defined.
240 */
241 public int getInt(int index, int defValue) {
242 index *= AssetManager.STYLE_NUM_ENTRIES;
243 final int[] data = mData;
244 final int type = data[index+AssetManager.STYLE_TYPE];
245 if (type == TypedValue.TYPE_NULL) {
246 return defValue;
247 } else if (type >= TypedValue.TYPE_FIRST_INT
248 && type <= TypedValue.TYPE_LAST_INT) {
249 return data[index+AssetManager.STYLE_DATA];
250 }
251
252 TypedValue v = mValue;
253 if (getValueAt(index, v)) {
254 Log.w(Resources.TAG, "Converting to int: " + v);
255 return XmlUtils.convertValueToInt(
256 v.coerceToString(), defValue);
257 }
258 Log.w(Resources.TAG, "getInt of bad type: 0x"
259 + Integer.toHexString(type));
260 return defValue;
261 }
262
263 /**
264 * Retrieve the float value for the attribute at <var>index</var>.
265 *
266 * @param index Index of attribute to retrieve.
267 *
268 * @return Attribute float value, or defValue if not defined..
269 */
270 public float getFloat(int index, float defValue) {
271 index *= AssetManager.STYLE_NUM_ENTRIES;
272 final int[] data = mData;
273 final int type = data[index+AssetManager.STYLE_TYPE];
274 if (type == TypedValue.TYPE_NULL) {
275 return defValue;
276 } else if (type == TypedValue.TYPE_FLOAT) {
277 return Float.intBitsToFloat(data[index+AssetManager.STYLE_DATA]);
278 } else if (type >= TypedValue.TYPE_FIRST_INT
279 && type <= TypedValue.TYPE_LAST_INT) {
280 return data[index+AssetManager.STYLE_DATA];
281 }
282
283 TypedValue v = mValue;
284 if (getValueAt(index, v)) {
285 Log.w(Resources.TAG, "Converting to float: " + v);
286 CharSequence str = v.coerceToString();
287 if (str != null) {
288 return Float.parseFloat(str.toString());
289 }
290 }
291 Log.w(Resources.TAG, "getFloat of bad type: 0x"
292 + Integer.toHexString(type));
293 return defValue;
294 }
295
296 /**
297 * Retrieve the color value for the attribute at <var>index</var>. If
298 * the attribute references a color resource holding a complex
299 * {@link android.content.res.ColorStateList}, then the default color from
300 * the set is returned.
301 *
302 * @param index Index of attribute to retrieve.
303 * @param defValue Value to return if the attribute is not defined or
304 * not a resource.
305 *
306 * @return Attribute color value, or defValue if not defined.
307 */
308 public int getColor(int index, int defValue) {
309 index *= AssetManager.STYLE_NUM_ENTRIES;
310 final int[] data = mData;
311 final int type = data[index+AssetManager.STYLE_TYPE];
312 if (type == TypedValue.TYPE_NULL) {
313 return defValue;
314 } else if (type >= TypedValue.TYPE_FIRST_INT
315 && type <= TypedValue.TYPE_LAST_INT) {
316 return data[index+AssetManager.STYLE_DATA];
317 } else if (type == TypedValue.TYPE_STRING) {
318 final TypedValue value = mValue;
319 if (getValueAt(index, value)) {
320 ColorStateList csl = mResources.loadColorStateList(
321 value, value.resourceId);
322 return csl.getDefaultColor();
323 }
324 return defValue;
325 }
326
327 throw new UnsupportedOperationException("Can't convert to color: type=0x"
328 + Integer.toHexString(type));
329 }
330
331 /**
332 * Retrieve the ColorStateList for the attribute at <var>index</var>.
333 * The value may be either a single solid color or a reference to
334 * a color or complex {@link android.content.res.ColorStateList} description.
335 *
336 * @param index Index of attribute to retrieve.
337 *
338 * @return ColorStateList for the attribute, or null if not defined.
339 */
340 public ColorStateList getColorStateList(int index) {
341 final TypedValue value = mValue;
342 if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
343 return mResources.loadColorStateList(value, value.resourceId);
344 }
345 return null;
346 }
347
348 /**
349 * Retrieve the integer value for the attribute at <var>index</var>.
350 *
351 * @param index Index of attribute to retrieve.
352 * @param defValue Value to return if the attribute is not defined or
353 * not a resource.
354 *
355 * @return Attribute integer value, or defValue if not defined.
356 */
357 public int getInteger(int index, int defValue) {
358 index *= AssetManager.STYLE_NUM_ENTRIES;
359 final int[] data = mData;
360 final int type = data[index+AssetManager.STYLE_TYPE];
361 if (type == TypedValue.TYPE_NULL) {
362 return defValue;
363 } else if (type >= TypedValue.TYPE_FIRST_INT
364 && type <= TypedValue.TYPE_LAST_INT) {
365 return data[index+AssetManager.STYLE_DATA];
366 }
367
368 throw new UnsupportedOperationException("Can't convert to integer: type=0x"
369 + Integer.toHexString(type));
370 }
371
372 /**
373 * Retrieve a dimensional unit attribute at <var>index</var>. Unit
374 * conversions are based on the current {@link DisplayMetrics}
375 * associated with the resources this {@link TypedArray} object
376 * came from.
377 *
378 * @param index Index of attribute to retrieve.
379 * @param defValue Value to return if the attribute is not defined or
380 * not a resource.
381 *
382 * @return Attribute dimension value multiplied by the appropriate
383 * metric, or defValue if not defined.
384 *
385 * @see #getDimensionPixelOffset
386 * @see #getDimensionPixelSize
387 */
388 public float getDimension(int index, float defValue) {
389 index *= AssetManager.STYLE_NUM_ENTRIES;
390 final int[] data = mData;
391 final int type = data[index+AssetManager.STYLE_TYPE];
392 if (type == TypedValue.TYPE_NULL) {
393 return defValue;
394 } else if (type == TypedValue.TYPE_DIMENSION) {
395 return TypedValue.complexToDimension(
396 data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
397 }
398
399 throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
400 + Integer.toHexString(type));
401 }
402
403 /**
404 * Retrieve a dimensional unit attribute at <var>index</var> for use
405 * as an offset in raw pixels. This is the same as
406 * {@link #getDimension}, except the returned value is converted to
407 * integer pixels for you. An offset conversion involves simply
408 * truncating the base value to an integer.
409 *
410 * @param index Index of attribute to retrieve.
411 * @param defValue Value to return if the attribute is not defined or
412 * not a resource.
413 *
414 * @return Attribute dimension value multiplied by the appropriate
415 * metric and truncated to integer pixels, or defValue if not defined.
416 *
417 * @see #getDimension
418 * @see #getDimensionPixelSize
419 */
420 public int getDimensionPixelOffset(int index, int defValue) {
421 index *= AssetManager.STYLE_NUM_ENTRIES;
422 final int[] data = mData;
423 final int type = data[index+AssetManager.STYLE_TYPE];
424 if (type == TypedValue.TYPE_NULL) {
425 return defValue;
426 } else if (type == TypedValue.TYPE_DIMENSION) {
427 return TypedValue.complexToDimensionPixelOffset(
428 data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
429 }
430
431 throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
432 + Integer.toHexString(type));
433 }
434
435 /**
436 * Retrieve a dimensional unit attribute at <var>index</var> for use
437 * as a size in raw pixels. This is the same as
438 * {@link #getDimension}, except the returned value is converted to
439 * integer pixels for use as a size. A size conversion involves
440 * rounding the base value, and ensuring that a non-zero base value
441 * is at least one pixel in size.
442 *
443 * @param index Index of attribute to retrieve.
444 * @param defValue Value to return if the attribute is not defined or
445 * not a resource.
446 *
447 * @return Attribute dimension value multiplied by the appropriate
448 * metric and truncated to integer pixels, or defValue if not defined.
449 *
450 * @see #getDimension
451 * @see #getDimensionPixelOffset
452 */
453 public int getDimensionPixelSize(int index, int defValue) {
454 index *= AssetManager.STYLE_NUM_ENTRIES;
455 final int[] data = mData;
456 final int type = data[index+AssetManager.STYLE_TYPE];
457 if (type == TypedValue.TYPE_NULL) {
458 return defValue;
459 } else if (type == TypedValue.TYPE_DIMENSION) {
460 return TypedValue.complexToDimensionPixelSize(
461 data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
462 }
463
464 throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
465 + Integer.toHexString(type));
466 }
467
468 /**
469 * Special version of {@link #getDimensionPixelSize} for retrieving
470 * {@link android.view.ViewGroup}'s layout_width and layout_height
471 * attributes. This is only here for performance reasons; applications
472 * should use {@link #getDimensionPixelSize}.
Dave Burke579e1402012-10-18 20:41:55 -0700473 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 * @param index Index of the attribute to retrieve.
475 * @param name Textual name of attribute for error reporting.
476 *
477 * @return Attribute dimension value multiplied by the appropriate
478 * metric and truncated to integer pixels.
479 */
480 public int getLayoutDimension(int index, String name) {
481 index *= AssetManager.STYLE_NUM_ENTRIES;
482 final int[] data = mData;
483 final int type = data[index+AssetManager.STYLE_TYPE];
484 if (type >= TypedValue.TYPE_FIRST_INT
485 && type <= TypedValue.TYPE_LAST_INT) {
486 return data[index+AssetManager.STYLE_DATA];
487 } else if (type == TypedValue.TYPE_DIMENSION) {
488 return TypedValue.complexToDimensionPixelSize(
489 data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
490 }
491
492 throw new RuntimeException(getPositionDescription()
493 + ": You must supply a " + name + " attribute.");
494 }
495
496 /**
497 * Special version of {@link #getDimensionPixelSize} for retrieving
498 * {@link android.view.ViewGroup}'s layout_width and layout_height
499 * attributes. This is only here for performance reasons; applications
500 * should use {@link #getDimensionPixelSize}.
501 *
502 * @param index Index of the attribute to retrieve.
503 * @param defValue The default value to return if this attribute is not
504 * default or contains the wrong type of data.
505 *
506 * @return Attribute dimension value multiplied by the appropriate
507 * metric and truncated to integer pixels.
508 */
509 public int getLayoutDimension(int index, int defValue) {
510 index *= AssetManager.STYLE_NUM_ENTRIES;
511 final int[] data = mData;
512 final int type = data[index+AssetManager.STYLE_TYPE];
513 if (type >= TypedValue.TYPE_FIRST_INT
514 && type <= TypedValue.TYPE_LAST_INT) {
515 return data[index+AssetManager.STYLE_DATA];
516 } else if (type == TypedValue.TYPE_DIMENSION) {
517 return TypedValue.complexToDimensionPixelSize(
518 data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
519 }
520
521 return defValue;
522 }
523
524 /**
525 * Retrieve a fractional unit attribute at <var>index</var>.
526 *
527 * @param index Index of attribute to retrieve.
528 * @param base The base value of this fraction. In other words, a
529 * standard fraction is multiplied by this value.
530 * @param pbase The parent base value of this fraction. In other
531 * words, a parent fraction (nn%p) is multiplied by this
532 * value.
533 * @param defValue Value to return if the attribute is not defined or
534 * not a resource.
535 *
536 * @return Attribute fractional value multiplied by the appropriate
537 * base value, or defValue if not defined.
538 */
539 public float getFraction(int index, int base, int pbase, float defValue) {
540 index *= AssetManager.STYLE_NUM_ENTRIES;
541 final int[] data = mData;
542 final int type = data[index+AssetManager.STYLE_TYPE];
543 if (type == TypedValue.TYPE_NULL) {
544 return defValue;
545 } else if (type == TypedValue.TYPE_FRACTION) {
546 return TypedValue.complexToFraction(
547 data[index+AssetManager.STYLE_DATA], base, pbase);
548 }
549
550 throw new UnsupportedOperationException("Can't convert to fraction: type=0x"
551 + Integer.toHexString(type));
552 }
553
554 /**
555 * Retrieve the resource identifier for the attribute at
556 * <var>index</var>. Note that attribute resource as resolved when
557 * the overall {@link TypedArray} object is retrieved. As a
558 * result, this function will return the resource identifier of the
559 * final resource value that was found, <em>not</em> necessarily the
560 * original resource that was specified by the attribute.
561 *
562 * @param index Index of attribute to retrieve.
563 * @param defValue Value to return if the attribute is not defined or
564 * not a resource.
565 *
566 * @return Attribute resource identifier, or defValue if not defined.
567 */
568 public int getResourceId(int index, int defValue) {
569 index *= AssetManager.STYLE_NUM_ENTRIES;
570 final int[] data = mData;
571 if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
572 final int resid = data[index+AssetManager.STYLE_RESOURCE_ID];
573 if (resid != 0) {
574 return resid;
575 }
576 }
577 return defValue;
578 }
579
580 /**
581 * Retrieve the Drawable for the attribute at <var>index</var>. This
582 * gets the resource ID of the selected attribute, and uses
583 * {@link Resources#getDrawable Resources.getDrawable} of the owning
584 * Resources object to retrieve its Drawable.
585 *
586 * @param index Index of attribute to retrieve.
587 *
588 * @return Drawable for the attribute, or null if not defined.
589 */
590 public Drawable getDrawable(int index) {
591 final TypedValue value = mValue;
592 if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
593 if (false) {
594 System.out.println("******************************************************************");
595 System.out.println("Got drawable resource: type="
596 + value.type
597 + " str=" + value.string
598 + " int=0x" + Integer.toHexString(value.data)
599 + " cookie=" + value.assetCookie);
600 System.out.println("******************************************************************");
601 }
602 return mResources.loadDrawable(value, value.resourceId);
603 }
604 return null;
605 }
606
607 /**
608 * Retrieve the CharSequence[] for the attribute at <var>index</var>.
609 * This gets the resource ID of the selected attribute, and uses
610 * {@link Resources#getTextArray Resources.getTextArray} of the owning
611 * Resources object to retrieve its String[].
612 *
613 * @param index Index of attribute to retrieve.
614 *
615 * @return CharSequence[] for the attribute, or null if not defined.
616 */
617 public CharSequence[] getTextArray(int index) {
618 final TypedValue value = mValue;
619 if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
620 if (false) {
621 System.out.println("******************************************************************");
622 System.out.println("Got drawable resource: type="
623 + value.type
624 + " str=" + value.string
625 + " int=0x" + Integer.toHexString(value.data)
626 + " cookie=" + value.assetCookie);
627 System.out.println("******************************************************************");
628 }
629 return mResources.getTextArray(value.resourceId);
630 }
631 return null;
632 }
633
634 /**
635 * Retrieve the raw TypedValue for the attribute at <var>index</var>.
636 *
637 * @param index Index of attribute to retrieve.
638 * @param outValue TypedValue object in which to place the attribute's
639 * data.
640 *
641 * @return Returns true if the value was retrieved, else false.
642 */
643 public boolean getValue(int index, TypedValue outValue) {
644 return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
645 }
646
647 /**
648 * Determines whether there is an attribute at <var>index</var>.
649 *
650 * @param index Index of attribute to retrieve.
651 *
652 * @return True if the attribute has a value, false otherwise.
653 */
654 public boolean hasValue(int index) {
655 index *= AssetManager.STYLE_NUM_ENTRIES;
656 final int[] data = mData;
657 final int type = data[index+AssetManager.STYLE_TYPE];
658 return type != TypedValue.TYPE_NULL;
659 }
660
661 /**
662 * Retrieve the raw TypedValue for the attribute at <var>index</var>
663 * and return a temporary object holding its data. This object is only
664 * valid until the next call on to {@link TypedArray}.
665 *
666 * @param index Index of attribute to retrieve.
667 *
668 * @return Returns a TypedValue object if the attribute is defined,
669 * containing its data; otherwise returns null. (You will not
670 * receive a TypedValue whose type is TYPE_NULL.)
671 */
672 public TypedValue peekValue(int index) {
673 final TypedValue value = mValue;
674 if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
675 return value;
676 }
677 return null;
678 }
679
680 /**
681 * Returns a message about the parser state suitable for printing error messages.
682 */
683 public String getPositionDescription() {
684 return mXml != null ? mXml.getPositionDescription() : "<internal>";
685 }
686
687 /**
Scott Main183bf112012-08-13 19:12:13 -0700688 * Give back a previously retrieved array, for later re-use.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 */
690 public void recycle() {
Dianne Hackborn50707cc2013-02-08 15:32:05 -0800691 synchronized (mResources.mAccessLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 TypedArray cached = mResources.mCachedStyledAttributes;
693 if (cached == null || cached.mData.length < mData.length) {
694 mXml = null;
695 mResources.mCachedStyledAttributes = this;
696 }
697 }
698 }
699
700 private boolean getValueAt(int index, TypedValue outValue) {
701 final int[] data = mData;
702 final int type = data[index+AssetManager.STYLE_TYPE];
703 if (type == TypedValue.TYPE_NULL) {
704 return false;
705 }
706 outValue.type = type;
707 outValue.data = data[index+AssetManager.STYLE_DATA];
708 outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
709 outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID];
710 outValue.changingConfigurations = data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS];
Dianne Hackborn0d221012009-07-29 15:41:19 -0700711 outValue.density = data[index+AssetManager.STYLE_DENSITY];
Gilles Debunne75399682010-08-19 11:26:14 -0700712 outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 return true;
714 }
715
716 private CharSequence loadStringValueAt(int index) {
717 final int[] data = mData;
718 final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
719 if (cookie < 0) {
720 if (mXml != null) {
721 return mXml.getPooledString(
722 data[index+AssetManager.STYLE_DATA]);
723 }
724 return null;
725 }
726 //System.out.println("Getting pooled from: " + v);
727 return mResources.mAssets.getPooledString(
728 cookie, data[index+AssetManager.STYLE_DATA]);
729 }
730
731 /*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
732 mResources = resources;
733 mData = data;
734 mIndices = indices;
735 mLength = len;
736 }
737
738 public String toString() {
739 return Arrays.toString(mData);
740 }
Kenny Root15a4d2f2010-03-11 18:20:12 -0800741}