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