1 /* 2 * Copyright (C) 2006 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.view; 18 19 import android.app.AppGlobals; 20 import android.content.Context; 21 import android.content.res.Configuration; 22 import android.content.res.Resources; 23 import android.os.RemoteException; 24 import android.provider.Settings; 25 import android.util.DisplayMetrics; 26 import android.util.SparseArray; 27 28 /** 29 * Contains methods to standard constants used in the UI for timeouts, sizes, and distances. 30 */ 31 public class ViewConfiguration { 32 /** 33 * Expected bit depth of the display panel. 34 * 35 * @hide 36 */ 37 public static final float PANEL_BIT_DEPTH = 24; 38 39 /** 40 * Minimum alpha required for a view to draw. 41 * 42 * @hide 43 */ 44 public static final float ALPHA_THRESHOLD = 0.5f / PANEL_BIT_DEPTH; 45 /** 46 * @hide 47 */ 48 public static final float ALPHA_THRESHOLD_INT = 0x7f / PANEL_BIT_DEPTH; 49 50 /** 51 * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in 52 * pixels 53 */ 54 private static final int SCROLL_BAR_SIZE = 10; 55 56 /** 57 * Duration of the fade when scrollbars fade away in milliseconds 58 */ 59 private static final int SCROLL_BAR_FADE_DURATION = 250; 60 61 /** 62 * Default delay before the scrollbars fade in milliseconds 63 */ 64 private static final int SCROLL_BAR_DEFAULT_DELAY = 300; 65 66 /** 67 * Defines the length of the fading edges in pixels 68 */ 69 private static final int FADING_EDGE_LENGTH = 12; 70 71 /** 72 * Defines the duration in milliseconds of the pressed state in child 73 * components. 74 */ 75 private static final int PRESSED_STATE_DURATION = 125; 76 77 /** 78 * Defines the default duration in milliseconds before a press turns into 79 * a long press 80 */ 81 private static final int DEFAULT_LONG_PRESS_TIMEOUT = 500; 82 83 /** 84 * Defines the time between successive key repeats in milliseconds. 85 */ 86 private static final int KEY_REPEAT_DELAY = 50; 87 88 /** 89 * Defines the duration in milliseconds a user needs to hold down the 90 * appropriate button to bring up the global actions dialog (power off, 91 * lock screen, etc). 92 */ 93 private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500; 94 95 /** 96 * Defines the duration in milliseconds we will wait to see if a touch event 97 * is a tap or a scroll. If the user does not move within this interval, it is 98 * considered to be a tap. 99 */ 100 private static final int TAP_TIMEOUT = 180; 101 102 /** 103 * Defines the duration in milliseconds we will wait to see if a touch event 104 * is a jump tap. If the user does not complete the jump tap within this interval, it is 105 * considered to be a tap. 106 */ 107 private static final int JUMP_TAP_TIMEOUT = 500; 108 109 /** 110 * Defines the duration in milliseconds between the first tap's up event and 111 * the second tap's down event for an interaction to be considered a 112 * double-tap. 113 */ 114 private static final int DOUBLE_TAP_TIMEOUT = 300; 115 116 /** 117 * Defines the maximum duration in milliseconds between a touch pad 118 * touch and release for a given touch to be considered a tap (click) as 119 * opposed to a hover movement gesture. 120 */ 121 private static final int HOVER_TAP_TIMEOUT = 150; 122 123 /** 124 * Defines the maximum distance in pixels that a touch pad touch can move 125 * before being released for it to be considered a tap (click) as opposed 126 * to a hover movement gesture. 127 */ 128 private static final int HOVER_TAP_SLOP = 20; 129 130 /** 131 * Defines the duration in milliseconds we want to display zoom controls in response 132 * to a user panning within an application. 133 */ 134 private static final int ZOOM_CONTROLS_TIMEOUT = 3000; 135 136 /** 137 * Inset in pixels to look for touchable content when the user touches the edge of the screen 138 */ 139 private static final int EDGE_SLOP = 12; 140 141 /** 142 * Distance a touch can wander before we think the user is scrolling in dips. 143 * Note that this value defined here is only used as a fallback by legacy/misbehaving 144 * applications that do not provide a Context for determining density/configuration-dependent 145 * values. 146 * 147 * To alter this value, see the configuration resource config_viewConfigurationTouchSlop 148 * in frameworks/base/core/res/res/values/config.xml or the appropriate device resource overlay. 149 * It may be appropriate to tweak this on a device-specific basis in an overlay based on 150 * the characteristics of the touch panel and firmware. 151 */ 152 private static final int TOUCH_SLOP = 8; 153 154 /** 155 * Distance a touch can wander before we think the user is attempting a paged scroll 156 * (in dips) 157 * 158 * Note that this value defined here is only used as a fallback by legacy/misbehaving 159 * applications that do not provide a Context for determining density/configuration-dependent 160 * values. 161 * 162 * See the note above on {@link #TOUCH_SLOP} regarding the dimen resource 163 * config_viewConfigurationTouchSlop. ViewConfiguration will report a paging touch slop of 164 * config_viewConfigurationTouchSlop * 2 when provided with a Context. 165 */ 166 private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2; 167 168 /** 169 * Distance between the first touch and second touch to still be considered a double tap 170 */ 171 private static final int DOUBLE_TAP_SLOP = 100; 172 173 /** 174 * Distance a touch needs to be outside of a window's bounds for it to 175 * count as outside for purposes of dismissing the window. 176 */ 177 private static final int WINDOW_TOUCH_SLOP = 16; 178 179 /** 180 * Minimum velocity to initiate a fling, as measured in pixels per second 181 */ 182 private static final int MINIMUM_FLING_VELOCITY = 50; 183 184 /** 185 * Maximum velocity to initiate a fling, as measured in pixels per second 186 */ 187 private static final int MAXIMUM_FLING_VELOCITY = 8000; 188 189 /** 190 * Distance between a touch up event denoting the end of a touch exploration 191 * gesture and the touch up event of a subsequent tap for the latter tap to be 192 * considered as a tap i.e. to perform a click. 193 */ 194 private static final int TOUCH_EXPLORATION_TAP_SLOP = 80; 195 196 /** 197 * Delay before dispatching a recurring accessibility event in milliseconds. 198 * This delay guarantees that a recurring event will be send at most once 199 * during the {@link #SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS} time 200 * frame. 201 */ 202 private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 400; 203 204 /** 205 * The maximum size of View's drawing cache, expressed in bytes. This size 206 * should be at least equal to the size of the screen in ARGB888 format. 207 */ 208 @Deprecated 209 private static final int MAXIMUM_DRAWING_CACHE_SIZE = 480 * 800 * 4; // ARGB8888 210 211 /** 212 * The coefficient of friction applied to flings/scrolls. 213 */ 214 private static final float SCROLL_FRICTION = 0.015f; 215 216 /** 217 * Max distance to overscroll for edge effects 218 */ 219 private static final int OVERSCROLL_DISTANCE = 0; 220 221 /** 222 * Max distance to overfling for edge effects 223 */ 224 private static final int OVERFLING_DISTANCE = 6; 225 226 private final int mEdgeSlop; 227 private final int mFadingEdgeLength; 228 private final int mMinimumFlingVelocity; 229 private final int mMaximumFlingVelocity; 230 private final int mScrollbarSize; 231 private final int mTouchSlop; 232 private final int mPagingTouchSlop; 233 private final int mDoubleTapSlop; 234 private final int mScaledTouchExplorationTapSlop; 235 private final int mWindowTouchSlop; 236 private final int mMaximumDrawingCacheSize; 237 private final int mOverscrollDistance; 238 private final int mOverflingDistance; 239 private final boolean mFadingMarqueeEnabled; 240 241 private boolean sHasPermanentMenuKey; 242 private boolean sHasPermanentMenuKeySet; 243 244 static final SparseArray<ViewConfiguration> sConfigurations = 245 new SparseArray<ViewConfiguration>(2); 246 247 /** 248 * @deprecated Use {@link android.view.ViewConfiguration#get(android.content.Context)} instead. 249 */ 250 @Deprecated 251 public ViewConfiguration() { 252 mEdgeSlop = EDGE_SLOP; 253 mFadingEdgeLength = FADING_EDGE_LENGTH; 254 mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY; 255 mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY; 256 mScrollbarSize = SCROLL_BAR_SIZE; 257 mTouchSlop = TOUCH_SLOP; 258 mPagingTouchSlop = PAGING_TOUCH_SLOP; 259 mDoubleTapSlop = DOUBLE_TAP_SLOP; 260 mScaledTouchExplorationTapSlop = TOUCH_EXPLORATION_TAP_SLOP; 261 mWindowTouchSlop = WINDOW_TOUCH_SLOP; 262 //noinspection deprecation 263 mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE; 264 mOverscrollDistance = OVERSCROLL_DISTANCE; 265 mOverflingDistance = OVERFLING_DISTANCE; 266 mFadingMarqueeEnabled = true; 267 } 268 269 /** 270 * Creates a new configuration for the specified context. The configuration depends on 271 * various parameters of the context, like the dimension of the display or the density 272 * of the display. 273 * 274 * @param context The application context used to initialize this view configuration. 275 * 276 * @see #get(android.content.Context) 277 * @see android.util.DisplayMetrics 278 */ 279 private ViewConfiguration(Context context) { 280 final Resources res = context.getResources(); 281 final DisplayMetrics metrics = res.getDisplayMetrics(); 282 final Configuration config = res.getConfiguration(); 283 final float density = metrics.density; 284 final float sizeAndDensity; 285 if (config.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE)) { 286 sizeAndDensity = density * 1.5f; 287 } else { 288 sizeAndDensity = density; 289 } 290 291 mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f); 292 mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f); 293 mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f); 294 mMaximumFlingVelocity = (int) (density * MAXIMUM_FLING_VELOCITY + 0.5f); 295 mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f); 296 mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f); 297 mScaledTouchExplorationTapSlop = (int) (density * TOUCH_EXPLORATION_TAP_SLOP + 0.5f); 298 mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f); 299 300 // Size of the screen in bytes, in ARGB_8888 format 301 mMaximumDrawingCacheSize = 4 * metrics.widthPixels * metrics.heightPixels; 302 303 mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f); 304 mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f); 305 306 if (!sHasPermanentMenuKeySet) { 307 IWindowManager wm = Display.getWindowManager(); 308 try { 309 sHasPermanentMenuKey = wm.canStatusBarHide() && !wm.hasNavigationBar(); 310 sHasPermanentMenuKeySet = true; 311 } catch (RemoteException ex) { 312 sHasPermanentMenuKey = false; 313 } 314 } 315 316 mFadingMarqueeEnabled = res.getBoolean( 317 com.android.internal.R.bool.config_ui_enableFadingMarquee); 318 mTouchSlop = res.getDimensionPixelSize( 319 com.android.internal.R.dimen.config_viewConfigurationTouchSlop); 320 mPagingTouchSlop = mTouchSlop * 2; 321 } 322 323 /** 324 * Returns a configuration for the specified context. The configuration depends on 325 * various parameters of the context, like the dimension of the display or the 326 * density of the display. 327 * 328 * @param context The application context used to initialize the view configuration. 329 */ 330 public static ViewConfiguration get(Context context) { 331 final DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 332 final int density = (int) (100.0f * metrics.density); 333 334 ViewConfiguration configuration = sConfigurations.get(density); 335 if (configuration == null) { 336 configuration = new ViewConfiguration(context); 337 sConfigurations.put(density, configuration); 338 } 339 340 return configuration; 341 } 342 343 /** 344 * @return The width of the horizontal scrollbar and the height of the vertical 345 * scrollbar in pixels 346 * 347 * @deprecated Use {@link #getScaledScrollBarSize()} instead. 348 */ 349 @Deprecated 350 public static int getScrollBarSize() { 351 return SCROLL_BAR_SIZE; 352 } 353 354 /** 355 * @return The width of the horizontal scrollbar and the height of the vertical 356 * scrollbar in pixels 357 */ 358 public int getScaledScrollBarSize() { 359 return mScrollbarSize; 360 } 361 362 /** 363 * @return Duration of the fade when scrollbars fade away in milliseconds 364 */ 365 public static int getScrollBarFadeDuration() { 366 return SCROLL_BAR_FADE_DURATION; 367 } 368 369 /** 370 * @return Default delay before the scrollbars fade in milliseconds 371 */ 372 public static int getScrollDefaultDelay() { 373 return SCROLL_BAR_DEFAULT_DELAY; 374 } 375 376 /** 377 * @return the length of the fading edges in pixels 378 * 379 * @deprecated Use {@link #getScaledFadingEdgeLength()} instead. 380 */ 381 @Deprecated 382 public static int getFadingEdgeLength() { 383 return FADING_EDGE_LENGTH; 384 } 385 386 /** 387 * @return the length of the fading edges in pixels 388 */ 389 public int getScaledFadingEdgeLength() { 390 return mFadingEdgeLength; 391 } 392 393 /** 394 * @return the duration in milliseconds of the pressed state in child 395 * components. 396 */ 397 public static int getPressedStateDuration() { 398 return PRESSED_STATE_DURATION; 399 } 400 401 /** 402 * @return the duration in milliseconds before a press turns into 403 * a long press 404 */ 405 public static int getLongPressTimeout() { 406 return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT, 407 DEFAULT_LONG_PRESS_TIMEOUT); 408 } 409 410 /** 411 * @return the time before the first key repeat in milliseconds. 412 */ 413 public static int getKeyRepeatTimeout() { 414 return getLongPressTimeout(); 415 } 416 417 /** 418 * @return the time between successive key repeats in milliseconds. 419 */ 420 public static int getKeyRepeatDelay() { 421 return KEY_REPEAT_DELAY; 422 } 423 424 /** 425 * @return the duration in milliseconds we will wait to see if a touch event 426 * is a tap or a scroll. If the user does not move within this interval, it is 427 * considered to be a tap. 428 */ 429 public static int getTapTimeout() { 430 return TAP_TIMEOUT; 431 } 432 433 /** 434 * @return the duration in milliseconds we will wait to see if a touch event 435 * is a jump tap. If the user does not move within this interval, it is 436 * considered to be a tap. 437 */ 438 public static int getJumpTapTimeout() { 439 return JUMP_TAP_TIMEOUT; 440 } 441 442 /** 443 * @return the duration in milliseconds between the first tap's up event and 444 * the second tap's down event for an interaction to be considered a 445 * double-tap. 446 */ 447 public static int getDoubleTapTimeout() { 448 return DOUBLE_TAP_TIMEOUT; 449 } 450 451 /** 452 * @return the maximum duration in milliseconds between a touch pad 453 * touch and release for a given touch to be considered a tap (click) as 454 * opposed to a hover movement gesture. 455 * @hide 456 */ 457 public static int getHoverTapTimeout() { 458 return HOVER_TAP_TIMEOUT; 459 } 460 461 /** 462 * @return the maximum distance in pixels that a touch pad touch can move 463 * before being released for it to be considered a tap (click) as opposed 464 * to a hover movement gesture. 465 * @hide 466 */ 467 public static int getHoverTapSlop() { 468 return HOVER_TAP_SLOP; 469 } 470 471 /** 472 * @return Inset in pixels to look for touchable content when the user touches the edge of the 473 * screen 474 * 475 * @deprecated Use {@link #getScaledEdgeSlop()} instead. 476 */ 477 @Deprecated 478 public static int getEdgeSlop() { 479 return EDGE_SLOP; 480 } 481 482 /** 483 * @return Inset in pixels to look for touchable content when the user touches the edge of the 484 * screen 485 */ 486 public int getScaledEdgeSlop() { 487 return mEdgeSlop; 488 } 489 490 /** 491 * @return Distance a touch can wander before we think the user is scrolling in pixels 492 * 493 * @deprecated Use {@link #getScaledTouchSlop()} instead. 494 */ 495 @Deprecated 496 public static int getTouchSlop() { 497 return TOUCH_SLOP; 498 } 499 500 /** 501 * @return Distance a touch can wander before we think the user is scrolling in pixels 502 */ 503 public int getScaledTouchSlop() { 504 return mTouchSlop; 505 } 506 507 /** 508 * @return Distance a touch can wander before we think the user is scrolling a full page 509 * in dips 510 */ 511 public int getScaledPagingTouchSlop() { 512 return mPagingTouchSlop; 513 } 514 515 /** 516 * @return Distance between the first touch and second touch to still be 517 * considered a double tap 518 * @deprecated Use {@link #getScaledDoubleTapSlop()} instead. 519 * @hide The only client of this should be GestureDetector, which needs this 520 * for clients that still use its deprecated constructor. 521 */ 522 @Deprecated 523 public static int getDoubleTapSlop() { 524 return DOUBLE_TAP_SLOP; 525 } 526 527 /** 528 * @return Distance between the first touch and second touch to still be 529 * considered a double tap 530 */ 531 public int getScaledDoubleTapSlop() { 532 return mDoubleTapSlop; 533 } 534 535 /** 536 * @return Distance between a touch up event denoting the end of a touch exploration 537 * gesture and the touch up event of a subsequent tap for the latter tap to be 538 * considered as a tap i.e. to perform a click. 539 * 540 * @hide 541 */ 542 public int getScaledTouchExplorationTapSlop() { 543 return mScaledTouchExplorationTapSlop; 544 } 545 546 /** 547 * Interval for dispatching a recurring accessibility event in milliseconds. 548 * This interval guarantees that a recurring event will be send at most once 549 * during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame. 550 * 551 * @return The delay in milliseconds. 552 * 553 * @hide 554 */ 555 public static long getSendRecurringAccessibilityEventsInterval() { 556 return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS; 557 } 558 559 /** 560 * @return Distance a touch must be outside the bounds of a window for it 561 * to be counted as outside the window for purposes of dismissing that 562 * window. 563 * 564 * @deprecated Use {@link #getScaledWindowTouchSlop()} instead. 565 */ 566 @Deprecated 567 public static int getWindowTouchSlop() { 568 return WINDOW_TOUCH_SLOP; 569 } 570 571 /** 572 * @return Distance a touch must be outside the bounds of a window for it 573 * to be counted as outside the window for purposes of dismissing that 574 * window. 575 */ 576 public int getScaledWindowTouchSlop() { 577 return mWindowTouchSlop; 578 } 579 580 /** 581 * @return Minimum velocity to initiate a fling, as measured in pixels per second. 582 * 583 * @deprecated Use {@link #getScaledMinimumFlingVelocity()} instead. 584 */ 585 @Deprecated 586 public static int getMinimumFlingVelocity() { 587 return MINIMUM_FLING_VELOCITY; 588 } 589 590 /** 591 * @return Minimum velocity to initiate a fling, as measured in pixels per second. 592 */ 593 public int getScaledMinimumFlingVelocity() { 594 return mMinimumFlingVelocity; 595 } 596 597 /** 598 * @return Maximum velocity to initiate a fling, as measured in pixels per second. 599 * 600 * @deprecated Use {@link #getScaledMaximumFlingVelocity()} instead. 601 */ 602 @Deprecated 603 public static int getMaximumFlingVelocity() { 604 return MAXIMUM_FLING_VELOCITY; 605 } 606 607 /** 608 * @return Maximum velocity to initiate a fling, as measured in pixels per second. 609 */ 610 public int getScaledMaximumFlingVelocity() { 611 return mMaximumFlingVelocity; 612 } 613 614 /** 615 * The maximum drawing cache size expressed in bytes. 616 * 617 * @return the maximum size of View's drawing cache expressed in bytes 618 * 619 * @deprecated Use {@link #getScaledMaximumDrawingCacheSize()} instead. 620 */ 621 @Deprecated 622 public static int getMaximumDrawingCacheSize() { 623 //noinspection deprecation 624 return MAXIMUM_DRAWING_CACHE_SIZE; 625 } 626 627 /** 628 * The maximum drawing cache size expressed in bytes. 629 * 630 * @return the maximum size of View's drawing cache expressed in bytes 631 */ 632 public int getScaledMaximumDrawingCacheSize() { 633 return mMaximumDrawingCacheSize; 634 } 635 636 /** 637 * @return The maximum distance a View should overscroll by when showing edge effects. 638 */ 639 public int getScaledOverscrollDistance() { 640 return mOverscrollDistance; 641 } 642 643 /** 644 * @return The maximum distance a View should overfling by when showing edge effects. 645 */ 646 public int getScaledOverflingDistance() { 647 return mOverflingDistance; 648 } 649 650 /** 651 * The amount of time that the zoom controls should be 652 * displayed on the screen expressed in milliseconds. 653 * 654 * @return the time the zoom controls should be visible expressed 655 * in milliseconds. 656 */ 657 public static long getZoomControlsTimeout() { 658 return ZOOM_CONTROLS_TIMEOUT; 659 } 660 661 /** 662 * The amount of time a user needs to press the relevant key to bring up 663 * the global actions dialog. 664 * 665 * @return how long a user needs to press the relevant key to bring up 666 * the global actions dialog. 667 */ 668 public static long getGlobalActionKeyTimeout() { 669 return GLOBAL_ACTIONS_KEY_TIMEOUT; 670 } 671 672 /** 673 * The amount of friction applied to scrolls and flings. 674 * 675 * @return A scalar dimensionless value representing the coefficient of 676 * friction. 677 */ 678 public static float getScrollFriction() { 679 return SCROLL_FRICTION; 680 } 681 682 /** 683 * Report if the device has a permanent menu key available to the user. 684 * 685 * <p>As of Android 3.0, devices may not have a permanent menu key available. 686 * Apps should use the action bar to present menu options to users. 687 * However, there are some apps where the action bar is inappropriate 688 * or undesirable. This method may be used to detect if a menu key is present. 689 * If not, applications should provide another on-screen affordance to access 690 * functionality. 691 * 692 * @return true if a permanent menu key is present, false otherwise. 693 */ 694 public boolean hasPermanentMenuKey() { 695 return sHasPermanentMenuKey; 696 } 697 698 /** 699 * @hide 700 * @return Whether or not marquee should use fading edges. 701 */ 702 public boolean isFadingMarqueeEnabled() { 703 return mFadingMarqueeEnabled; 704 } 705 } 706