1 /* 2 * Copyright (C) 2007 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 17 package android.util; 18 19 import android.annotation.AnyRes; 20 import android.content.pm.ActivityInfo.Config; 21 22 /** 23 * Container for a dynamically typed data value. Primarily used with 24 * {@link android.content.res.Resources} for holding resource values. 25 */ 26 public class TypedValue { 27 /** The value contains no data. */ 28 public static final int TYPE_NULL = 0x00; 29 30 /** The <var>data</var> field holds a resource identifier. */ 31 public static final int TYPE_REFERENCE = 0x01; 32 /** The <var>data</var> field holds an attribute resource 33 * identifier (referencing an attribute in the current theme 34 * style, not a resource entry). */ 35 public static final int TYPE_ATTRIBUTE = 0x02; 36 /** The <var>string</var> field holds string data. In addition, if 37 * <var>data</var> is non-zero then it is the string block 38 * index of the string and <var>assetCookie</var> is the set of 39 * assets the string came from. */ 40 public static final int TYPE_STRING = 0x03; 41 /** The <var>data</var> field holds an IEEE 754 floating point number. */ 42 public static final int TYPE_FLOAT = 0x04; 43 /** The <var>data</var> field holds a complex number encoding a 44 * dimension value. */ 45 public static final int TYPE_DIMENSION = 0x05; 46 /** The <var>data</var> field holds a complex number encoding a fraction 47 * of a container. */ 48 public static final int TYPE_FRACTION = 0x06; 49 50 /** Identifies the start of plain integer values. Any type value 51 * from this to {@link #TYPE_LAST_INT} means the 52 * <var>data</var> field holds a generic integer value. */ 53 public static final int TYPE_FIRST_INT = 0x10; 54 55 /** The <var>data</var> field holds a number that was 56 * originally specified in decimal. */ 57 public static final int TYPE_INT_DEC = 0x10; 58 /** The <var>data</var> field holds a number that was 59 * originally specified in hexadecimal (0xn). */ 60 public static final int TYPE_INT_HEX = 0x11; 61 /** The <var>data</var> field holds 0 or 1 that was originally 62 * specified as "false" or "true". */ 63 public static final int TYPE_INT_BOOLEAN = 0x12; 64 65 /** Identifies the start of integer values that were specified as 66 * color constants (starting with '#'). */ 67 public static final int TYPE_FIRST_COLOR_INT = 0x1c; 68 69 /** The <var>data</var> field holds a color that was originally 70 * specified as #aarrggbb. */ 71 public static final int TYPE_INT_COLOR_ARGB8 = 0x1c; 72 /** The <var>data</var> field holds a color that was originally 73 * specified as #rrggbb. */ 74 public static final int TYPE_INT_COLOR_RGB8 = 0x1d; 75 /** The <var>data</var> field holds a color that was originally 76 * specified as #argb. */ 77 public static final int TYPE_INT_COLOR_ARGB4 = 0x1e; 78 /** The <var>data</var> field holds a color that was originally 79 * specified as #rgb. */ 80 public static final int TYPE_INT_COLOR_RGB4 = 0x1f; 81 82 /** Identifies the end of integer values that were specified as color 83 * constants. */ 84 public static final int TYPE_LAST_COLOR_INT = 0x1f; 85 86 /** Identifies the end of plain integer values. */ 87 public static final int TYPE_LAST_INT = 0x1f; 88 89 /* ------------------------------------------------------------ */ 90 91 /** Complex data: bit location of unit information. */ 92 public static final int COMPLEX_UNIT_SHIFT = 0; 93 /** Complex data: mask to extract unit information (after shifting by 94 * {@link #COMPLEX_UNIT_SHIFT}). This gives us 16 possible types, as 95 * defined below. */ 96 public static final int COMPLEX_UNIT_MASK = 0xf; 97 98 /** {@link #TYPE_DIMENSION} complex unit: Value is raw pixels. */ 99 public static final int COMPLEX_UNIT_PX = 0; 100 /** {@link #TYPE_DIMENSION} complex unit: Value is Device Independent 101 * Pixels. */ 102 public static final int COMPLEX_UNIT_DIP = 1; 103 /** {@link #TYPE_DIMENSION} complex unit: Value is a scaled pixel. */ 104 public static final int COMPLEX_UNIT_SP = 2; 105 /** {@link #TYPE_DIMENSION} complex unit: Value is in points. */ 106 public static final int COMPLEX_UNIT_PT = 3; 107 /** {@link #TYPE_DIMENSION} complex unit: Value is in inches. */ 108 public static final int COMPLEX_UNIT_IN = 4; 109 /** {@link #TYPE_DIMENSION} complex unit: Value is in millimeters. */ 110 public static final int COMPLEX_UNIT_MM = 5; 111 112 /** {@link #TYPE_FRACTION} complex unit: A basic fraction of the overall 113 * size. */ 114 public static final int COMPLEX_UNIT_FRACTION = 0; 115 /** {@link #TYPE_FRACTION} complex unit: A fraction of the parent size. */ 116 public static final int COMPLEX_UNIT_FRACTION_PARENT = 1; 117 118 /** Complex data: where the radix information is, telling where the decimal 119 * place appears in the mantissa. */ 120 public static final int COMPLEX_RADIX_SHIFT = 4; 121 /** Complex data: mask to extract radix information (after shifting by 122 * {@link #COMPLEX_RADIX_SHIFT}). This give us 4 possible fixed point 123 * representations as defined below. */ 124 public static final int COMPLEX_RADIX_MASK = 0x3; 125 126 /** Complex data: the mantissa is an integral number -- i.e., 0xnnnnnn.0 */ 127 public static final int COMPLEX_RADIX_23p0 = 0; 128 /** Complex data: the mantissa magnitude is 16 bits -- i.e, 0xnnnn.nn */ 129 public static final int COMPLEX_RADIX_16p7 = 1; 130 /** Complex data: the mantissa magnitude is 8 bits -- i.e, 0xnn.nnnn */ 131 public static final int COMPLEX_RADIX_8p15 = 2; 132 /** Complex data: the mantissa magnitude is 0 bits -- i.e, 0x0.nnnnnn */ 133 public static final int COMPLEX_RADIX_0p23 = 3; 134 135 /** Complex data: bit location of mantissa information. */ 136 public static final int COMPLEX_MANTISSA_SHIFT = 8; 137 /** Complex data: mask to extract mantissa information (after shifting by 138 * {@link #COMPLEX_MANTISSA_SHIFT}). This gives us 23 bits of precision; 139 * the top bit is the sign. */ 140 public static final int COMPLEX_MANTISSA_MASK = 0xffffff; 141 142 /* ------------------------------------------------------------ */ 143 144 /** 145 * {@link #TYPE_NULL} data indicating the value was not specified. 146 */ 147 public static final int DATA_NULL_UNDEFINED = 0; 148 /** 149 * {@link #TYPE_NULL} data indicating the value was explicitly set to null. 150 */ 151 public static final int DATA_NULL_EMPTY = 1; 152 153 /* ------------------------------------------------------------ */ 154 155 /** 156 * If {@link #density} is equal to this value, then the density should be 157 * treated as the system's default density value: {@link DisplayMetrics#DENSITY_DEFAULT}. 158 */ 159 public static final int DENSITY_DEFAULT = 0; 160 161 /** 162 * If {@link #density} is equal to this value, then there is no density 163 * associated with the resource and it should not be scaled. 164 */ 165 public static final int DENSITY_NONE = 0xffff; 166 167 /* ------------------------------------------------------------ */ 168 169 /** The type held by this value, as defined by the constants here. 170 * This tells you how to interpret the other fields in the object. */ 171 public int type; 172 173 /** If the value holds a string, this is it. */ 174 public CharSequence string; 175 176 /** Basic data in the value, interpreted according to {@link #type} */ 177 public int data; 178 179 /** Additional information about where the value came from; only 180 * set for strings. */ 181 public int assetCookie; 182 183 /** If Value came from a resource, this holds the corresponding resource id. */ 184 @AnyRes 185 public int resourceId; 186 187 /** 188 * If the value came from a resource, these are the configurations for 189 * which its contents can change. 190 * 191 * <p>For example, if a resource has a value defined for the -land resource qualifier, 192 * this field will have the {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION} bit set. 193 * </p> 194 * 195 * @see android.content.pm.ActivityInfo#CONFIG_MCC 196 * @see android.content.pm.ActivityInfo#CONFIG_MNC 197 * @see android.content.pm.ActivityInfo#CONFIG_LOCALE 198 * @see android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN 199 * @see android.content.pm.ActivityInfo#CONFIG_KEYBOARD 200 * @see android.content.pm.ActivityInfo#CONFIG_KEYBOARD_HIDDEN 201 * @see android.content.pm.ActivityInfo#CONFIG_NAVIGATION 202 * @see android.content.pm.ActivityInfo#CONFIG_ORIENTATION 203 * @see android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT 204 * @see android.content.pm.ActivityInfo#CONFIG_UI_MODE 205 * @see android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE 206 * @see android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE 207 * @see android.content.pm.ActivityInfo#CONFIG_DENSITY 208 * @see android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION 209 * @see android.content.pm.ActivityInfo#CONFIG_COLOR_MODE 210 * 211 */ 212 public @Config int changingConfigurations = -1; 213 214 /** 215 * If the Value came from a resource, this holds the corresponding pixel density. 216 * */ 217 public int density; 218 219 /** 220 * If the Value came from a style resource or a layout resource (set in an XML layout), this 221 * holds the corresponding style or layout resource id against which the attribute was resolved. 222 */ 223 public int sourceResourceId; 224 225 /* ------------------------------------------------------------ */ 226 227 /** Return the data for this value as a float. Only use for values 228 * whose type is {@link #TYPE_FLOAT}. */ getFloat()229 public final float getFloat() { 230 return Float.intBitsToFloat(data); 231 } 232 233 private static final float MANTISSA_MULT = 234 1.0f / (1<<TypedValue.COMPLEX_MANTISSA_SHIFT); 235 private static final float[] RADIX_MULTS = new float[] { 236 1.0f*MANTISSA_MULT, 1.0f/(1<<7)*MANTISSA_MULT, 237 1.0f/(1<<15)*MANTISSA_MULT, 1.0f/(1<<23)*MANTISSA_MULT 238 }; 239 240 /** 241 * Determine if a value is a color. 242 * 243 * This works by comparing {@link #type} to {@link #TYPE_FIRST_COLOR_INT} 244 * and {@link #TYPE_LAST_COLOR_INT}. 245 * 246 * @return true if this value is a color 247 */ isColorType()248 public boolean isColorType() { 249 return (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT); 250 } 251 252 /** 253 * Retrieve the base value from a complex data integer. This uses the 254 * {@link #COMPLEX_MANTISSA_MASK} and {@link #COMPLEX_RADIX_MASK} fields of 255 * the data to compute a floating point representation of the number they 256 * describe. The units are ignored. 257 * 258 * @param complex A complex data value. 259 * 260 * @return A floating point value corresponding to the complex data. 261 */ complexToFloat(int complex)262 public static float complexToFloat(int complex) 263 { 264 return (complex&(TypedValue.COMPLEX_MANTISSA_MASK 265 <<TypedValue.COMPLEX_MANTISSA_SHIFT)) 266 * RADIX_MULTS[(complex>>TypedValue.COMPLEX_RADIX_SHIFT) 267 & TypedValue.COMPLEX_RADIX_MASK]; 268 } 269 270 /** 271 * Converts a complex data value holding a dimension to its final floating 272 * point value. The given <var>data</var> must be structured as a 273 * {@link #TYPE_DIMENSION}. 274 * 275 * @param data A complex data value holding a unit, magnitude, and 276 * mantissa. 277 * @param metrics Current display metrics to use in the conversion -- 278 * supplies display density and scaling information. 279 * 280 * @return The complex floating point value multiplied by the appropriate 281 * metrics depending on its unit. 282 */ complexToDimension(int data, DisplayMetrics metrics)283 public static float complexToDimension(int data, DisplayMetrics metrics) 284 { 285 return applyDimension( 286 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, 287 complexToFloat(data), 288 metrics); 289 } 290 291 /** 292 * Converts a complex data value holding a dimension to its final value 293 * as an integer pixel offset. This is the same as 294 * {@link #complexToDimension}, except the raw floating point value is 295 * truncated to an integer (pixel) value. 296 * The given <var>data</var> must be structured as a 297 * {@link #TYPE_DIMENSION}. 298 * 299 * @param data A complex data value holding a unit, magnitude, and 300 * mantissa. 301 * @param metrics Current display metrics to use in the conversion -- 302 * supplies display density and scaling information. 303 * 304 * @return The number of pixels specified by the data and its desired 305 * multiplier and units. 306 */ complexToDimensionPixelOffset(int data, DisplayMetrics metrics)307 public static int complexToDimensionPixelOffset(int data, 308 DisplayMetrics metrics) 309 { 310 return (int)applyDimension( 311 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, 312 complexToFloat(data), 313 metrics); 314 } 315 316 /** 317 * Converts a complex data value holding a dimension to its final value 318 * as an integer pixel size. This is the same as 319 * {@link #complexToDimension}, except the raw floating point value is 320 * converted to an integer (pixel) value for use as a size. A size 321 * conversion involves rounding the base value, and ensuring that a 322 * non-zero base value is at least one pixel in size. 323 * The given <var>data</var> must be structured as a 324 * {@link #TYPE_DIMENSION}. 325 * 326 * @param data A complex data value holding a unit, magnitude, and 327 * mantissa. 328 * @param metrics Current display metrics to use in the conversion -- 329 * supplies display density and scaling information. 330 * 331 * @return The number of pixels specified by the data and its desired 332 * multiplier and units. 333 */ complexToDimensionPixelSize(int data, DisplayMetrics metrics)334 public static int complexToDimensionPixelSize(int data, 335 DisplayMetrics metrics) 336 { 337 final float value = complexToFloat(data); 338 final float f = applyDimension( 339 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, 340 value, 341 metrics); 342 final int res = (int) ((f >= 0) ? (f + 0.5f) : (f - 0.5f)); 343 if (res != 0) return res; 344 if (value == 0) return 0; 345 if (value > 0) return 1; 346 return -1; 347 } 348 349 /** 350 * @hide Was accidentally exposed in API level 1 for debugging purposes. 351 * Kept for compatibility just in case although the debugging code has been removed. 352 */ 353 @Deprecated complexToDimensionNoisy(int data, DisplayMetrics metrics)354 public static float complexToDimensionNoisy(int data, DisplayMetrics metrics) 355 { 356 return complexToDimension(data, metrics); 357 } 358 359 /** 360 * Return the complex unit type for this value. For example, a dimen type 361 * with value 12sp will return {@link #COMPLEX_UNIT_SP}. Only use for values 362 * whose type is {@link #TYPE_DIMENSION}. 363 * 364 * @return The complex unit type. 365 */ getComplexUnit()366 public int getComplexUnit() 367 { 368 return COMPLEX_UNIT_MASK & (data>>TypedValue.COMPLEX_UNIT_SHIFT); 369 } 370 371 /** 372 * Converts an unpacked complex data value holding a dimension to its final floating 373 * point value. The two parameters <var>unit</var> and <var>value</var> 374 * are as in {@link #TYPE_DIMENSION}. 375 * 376 * @param unit The unit to convert from. 377 * @param value The value to apply the unit to. 378 * @param metrics Current display metrics to use in the conversion -- 379 * supplies display density and scaling information. 380 * 381 * @return The complex floating point value multiplied by the appropriate 382 * metrics depending on its unit. 383 */ applyDimension(int unit, float value, DisplayMetrics metrics)384 public static float applyDimension(int unit, float value, 385 DisplayMetrics metrics) 386 { 387 switch (unit) { 388 case COMPLEX_UNIT_PX: 389 return value; 390 case COMPLEX_UNIT_DIP: 391 return value * metrics.density; 392 case COMPLEX_UNIT_SP: 393 return value * metrics.scaledDensity; 394 case COMPLEX_UNIT_PT: 395 return value * metrics.xdpi * (1.0f/72); 396 case COMPLEX_UNIT_IN: 397 return value * metrics.xdpi; 398 case COMPLEX_UNIT_MM: 399 return value * metrics.xdpi * (1.0f/25.4f); 400 } 401 return 0; 402 } 403 404 /** 405 * Return the data for this value as a dimension. Only use for values 406 * whose type is {@link #TYPE_DIMENSION}. 407 * 408 * @param metrics Current display metrics to use in the conversion -- 409 * supplies display density and scaling information. 410 * 411 * @return The complex floating point value multiplied by the appropriate 412 * metrics depending on its unit. 413 */ getDimension(DisplayMetrics metrics)414 public float getDimension(DisplayMetrics metrics) 415 { 416 return complexToDimension(data, metrics); 417 } 418 419 /** 420 * Converts a complex data value holding a fraction to its final floating 421 * point value. The given <var>data</var> must be structured as a 422 * {@link #TYPE_FRACTION}. 423 * 424 * @param data A complex data value holding a unit, magnitude, and 425 * mantissa. 426 * @param base The base value of this fraction. In other words, a 427 * standard fraction is multiplied by this value. 428 * @param pbase The parent base value of this fraction. In other 429 * words, a parent fraction (nn%p) is multiplied by this 430 * value. 431 * 432 * @return The complex floating point value multiplied by the appropriate 433 * base value depending on its unit. 434 */ complexToFraction(int data, float base, float pbase)435 public static float complexToFraction(int data, float base, float pbase) 436 { 437 switch ((data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK) { 438 case COMPLEX_UNIT_FRACTION: 439 return complexToFloat(data) * base; 440 case COMPLEX_UNIT_FRACTION_PARENT: 441 return complexToFloat(data) * pbase; 442 } 443 return 0; 444 } 445 446 /** 447 * Return the data for this value as a fraction. Only use for values whose 448 * type is {@link #TYPE_FRACTION}. 449 * 450 * @param base The base value of this fraction. In other words, a 451 * standard fraction is multiplied by this value. 452 * @param pbase The parent base value of this fraction. In other 453 * words, a parent fraction (nn%p) is multiplied by this 454 * value. 455 * 456 * @return The complex floating point value multiplied by the appropriate 457 * base value depending on its unit. 458 */ getFraction(float base, float pbase)459 public float getFraction(float base, float pbase) 460 { 461 return complexToFraction(data, base, pbase); 462 } 463 464 /** 465 * Regardless of the actual type of the value, try to convert it to a 466 * string value. For example, a color type will be converted to a 467 * string of the form #aarrggbb. 468 * 469 * @return CharSequence The coerced string value. If the value is 470 * null or the type is not known, null is returned. 471 */ coerceToString()472 public final CharSequence coerceToString() 473 { 474 int t = type; 475 if (t == TYPE_STRING) { 476 return string; 477 } 478 return coerceToString(t, data); 479 } 480 481 private static final String[] DIMENSION_UNIT_STRS = new String[] { 482 "px", "dip", "sp", "pt", "in", "mm" 483 }; 484 private static final String[] FRACTION_UNIT_STRS = new String[] { 485 "%", "%p" 486 }; 487 488 /** 489 * Perform type conversion as per {@link #coerceToString()} on an 490 * explicitly supplied type and data. 491 * 492 * @param type The data type identifier. 493 * @param data The data value. 494 * 495 * @return String The coerced string value. If the value is 496 * null or the type is not known, null is returned. 497 */ coerceToString(int type, int data)498 public static final String coerceToString(int type, int data) 499 { 500 switch (type) { 501 case TYPE_NULL: 502 return null; 503 case TYPE_REFERENCE: 504 return "@" + data; 505 case TYPE_ATTRIBUTE: 506 return "?" + data; 507 case TYPE_FLOAT: 508 return Float.toString(Float.intBitsToFloat(data)); 509 case TYPE_DIMENSION: 510 return Float.toString(complexToFloat(data)) + DIMENSION_UNIT_STRS[ 511 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK]; 512 case TYPE_FRACTION: 513 return Float.toString(complexToFloat(data)*100) + FRACTION_UNIT_STRS[ 514 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK]; 515 case TYPE_INT_HEX: 516 return "0x" + Integer.toHexString(data); 517 case TYPE_INT_BOOLEAN: 518 return data != 0 ? "true" : "false"; 519 } 520 521 if (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT) { 522 return "#" + Integer.toHexString(data); 523 } else if (type >= TYPE_FIRST_INT && type <= TYPE_LAST_INT) { 524 return Integer.toString(data); 525 } 526 527 return null; 528 } 529 setTo(TypedValue other)530 public void setTo(TypedValue other) 531 { 532 type = other.type; 533 string = other.string; 534 data = other.data; 535 assetCookie = other.assetCookie; 536 resourceId = other.resourceId; 537 density = other.density; 538 } 539 toString()540 public String toString() 541 { 542 StringBuilder sb = new StringBuilder(); 543 sb.append("TypedValue{t=0x").append(Integer.toHexString(type)); 544 sb.append("/d=0x").append(Integer.toHexString(data)); 545 if (type == TYPE_STRING) { 546 sb.append(" \"").append(string != null ? string : "<null>").append("\""); 547 } 548 if (assetCookie != 0) { 549 sb.append(" a=").append(assetCookie); 550 } 551 if (resourceId != 0) { 552 sb.append(" r=0x").append(Integer.toHexString(resourceId)); 553 } 554 sb.append("}"); 555 return sb.toString(); 556 } 557 }; 558 559