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