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