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 pixels 143 */ 144 private static final int TOUCH_SLOP = 16; 145 146 /** 147 * Distance a touch can wander before we think the user is attempting a paged scroll 148 * (in dips) 149 */ 150 private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2; 151 152 /** 153 * Distance between the first touch and second touch to still be considered a double tap 154 */ 155 private static final int DOUBLE_TAP_SLOP = 100; 156 157 /** 158 * Distance a touch needs to be outside of a window's bounds for it to 159 * count as outside for purposes of dismissing the window. 160 */ 161 private static final int WINDOW_TOUCH_SLOP = 16; 162 163 /** 164 * Minimum velocity to initiate a fling, as measured in pixels per second 165 */ 166 private static final int MINIMUM_FLING_VELOCITY = 50; 167 168 /** 169 * Maximum velocity to initiate a fling, as measured in pixels per second 170 */ 171 private static final int MAXIMUM_FLING_VELOCITY = 8000; 172 173 /** 174 * Distance between a touch up event denoting the end of a touch exploration 175 * gesture and the touch up event of a subsequent tap for the latter tap to be 176 * considered as a tap i.e. to perform a click. 177 */ 178 private static final int TOUCH_EXPLORATION_TAP_SLOP = 80; 179 180 /** 181 * Delay before dispatching a recurring accessibility event in milliseconds. 182 * This delay guarantees that a recurring event will be send at most once 183 * during the {@link #SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS} time 184 * frame. 185 */ 186 private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 400; 187 188 /** 189 * The maximum size of View's drawing cache, expressed in bytes. This size 190 * should be at least equal to the size of the screen in ARGB888 format. 191 */ 192 @Deprecated 193 private static final int MAXIMUM_DRAWING_CACHE_SIZE = 480 * 800 * 4; // ARGB8888 194 195 /** 196 * The coefficient of friction applied to flings/scrolls. 197 */ 198 private static final float SCROLL_FRICTION = 0.015f; 199 200 /** 201 * Max distance to overscroll for edge effects 202 */ 203 private static final int OVERSCROLL_DISTANCE = 0; 204 205 /** 206 * Max distance to overfling for edge effects 207 */ 208 private static final int OVERFLING_DISTANCE = 6; 209 210 private final int mEdgeSlop; 211 private final int mFadingEdgeLength; 212 private final int mMinimumFlingVelocity; 213 private final int mMaximumFlingVelocity; 214 private final int mScrollbarSize; 215 private final int mTouchSlop; 216 private final int mPagingTouchSlop; 217 private final int mDoubleTapSlop; 218 private final int mScaledTouchExplorationTapSlop; 219 private final int mWindowTouchSlop; 220 private final int mMaximumDrawingCacheSize; 221 private final int mOverscrollDistance; 222 private final int mOverflingDistance; 223 private final boolean mFadingMarqueeEnabled; 224 225 private boolean sHasPermanentMenuKey; 226 private boolean sHasPermanentMenuKeySet; 227 228 static final SparseArray<ViewConfiguration> sConfigurations = 229 new SparseArray<ViewConfiguration>(2); 230 231 /** 232 * @deprecated Use {@link android.view.ViewConfiguration#get(android.content.Context)} instead. 233 */ 234 @Deprecated ViewConfiguration()235 public ViewConfiguration() { 236 mEdgeSlop = EDGE_SLOP; 237 mFadingEdgeLength = FADING_EDGE_LENGTH; 238 mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY; 239 mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY; 240 mScrollbarSize = SCROLL_BAR_SIZE; 241 mTouchSlop = TOUCH_SLOP; 242 mPagingTouchSlop = PAGING_TOUCH_SLOP; 243 mDoubleTapSlop = DOUBLE_TAP_SLOP; 244 mScaledTouchExplorationTapSlop = TOUCH_EXPLORATION_TAP_SLOP; 245 mWindowTouchSlop = WINDOW_TOUCH_SLOP; 246 //noinspection deprecation 247 mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE; 248 mOverscrollDistance = OVERSCROLL_DISTANCE; 249 mOverflingDistance = OVERFLING_DISTANCE; 250 mFadingMarqueeEnabled = true; 251 } 252 253 /** 254 * Creates a new configuration for the specified context. The configuration depends on 255 * various parameters of the context, like the dimension of the display or the density 256 * of the display. 257 * 258 * @param context The application context used to initialize this view configuration. 259 * 260 * @see #get(android.content.Context) 261 * @see android.util.DisplayMetrics 262 */ ViewConfiguration(Context context)263 private ViewConfiguration(Context context) { 264 final Resources res = context.getResources(); 265 final DisplayMetrics metrics = res.getDisplayMetrics(); 266 final Configuration config = res.getConfiguration(); 267 final float density = metrics.density; 268 final float sizeAndDensity; 269 if (config.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE)) { 270 sizeAndDensity = density * 1.5f; 271 } else { 272 sizeAndDensity = density; 273 } 274 275 mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f); 276 mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f); 277 mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f); 278 mMaximumFlingVelocity = (int) (density * MAXIMUM_FLING_VELOCITY + 0.5f); 279 mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f); 280 mTouchSlop = (int) (sizeAndDensity * TOUCH_SLOP + 0.5f); 281 mPagingTouchSlop = (int) (sizeAndDensity * PAGING_TOUCH_SLOP + 0.5f); 282 mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f); 283 mScaledTouchExplorationTapSlop = (int) (density * TOUCH_EXPLORATION_TAP_SLOP + 0.5f); 284 mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f); 285 286 // Size of the screen in bytes, in ARGB_8888 format 287 mMaximumDrawingCacheSize = 4 * metrics.widthPixels * metrics.heightPixels; 288 289 mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f); 290 mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f); 291 292 if (!sHasPermanentMenuKeySet) { 293 IWindowManager wm = Display.getWindowManager(); 294 try { 295 sHasPermanentMenuKey = wm.canStatusBarHide() && !wm.hasNavigationBar(); 296 sHasPermanentMenuKeySet = true; 297 } catch (RemoteException ex) { 298 sHasPermanentMenuKey = false; 299 } 300 } 301 302 mFadingMarqueeEnabled = res.getBoolean( 303 com.android.internal.R.bool.config_ui_enableFadingMarquee); 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 */ get(Context context)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 pixels 329 * 330 * @deprecated Use {@link #getScaledScrollBarSize()} instead. 331 */ 332 @Deprecated getScrollBarSize()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 */ getScaledScrollBarSize()341 public int getScaledScrollBarSize() { 342 return mScrollbarSize; 343 } 344 345 /** 346 * @return Duration of the fade when scrollbars fade away in milliseconds 347 */ getScrollBarFadeDuration()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 */ getScrollDefaultDelay()355 public static int getScrollDefaultDelay() { 356 return SCROLL_BAR_DEFAULT_DELAY; 357 } 358 359 /** 360 * @return the length of the fading edges in pixels 361 * 362 * @deprecated Use {@link #getScaledFadingEdgeLength()} instead. 363 */ 364 @Deprecated getFadingEdgeLength()365 public static int getFadingEdgeLength() { 366 return FADING_EDGE_LENGTH; 367 } 368 369 /** 370 * @return the length of the fading edges in pixels 371 */ getScaledFadingEdgeLength()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 */ getPressedStateDuration()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 */ getLongPressTimeout()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 */ getKeyRepeatTimeout()396 public static int getKeyRepeatTimeout() { 397 return getLongPressTimeout(); 398 } 399 400 /** 401 * @return the time between successive key repeats in milliseconds. 402 */ getKeyRepeatDelay()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 */ getTapTimeout()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 */ getJumpTapTimeout()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 */ getDoubleTapTimeout()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 */ getHoverTapTimeout()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 */ getHoverTapSlop()450 public static int getHoverTapSlop() { 451 return HOVER_TAP_SLOP; 452 } 453 454 /** 455 * @return Inset in pixels 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 getEdgeSlop()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 */ getScaledEdgeSlop()469 public int getScaledEdgeSlop() { 470 return mEdgeSlop; 471 } 472 473 /** 474 * @return Distance a touch can wander before we think the user is scrolling in pixels 475 * 476 * @deprecated Use {@link #getScaledTouchSlop()} instead. 477 */ 478 @Deprecated getTouchSlop()479 public static int getTouchSlop() { 480 return TOUCH_SLOP; 481 } 482 483 /** 484 * @return Distance a touch can wander before we think the user is scrolling in pixels 485 */ getScaledTouchSlop()486 public int getScaledTouchSlop() { 487 return mTouchSlop; 488 } 489 490 /** 491 * @return Distance a touch can wander before we think the user is scrolling a full page 492 * in dips 493 */ getScaledPagingTouchSlop()494 public int getScaledPagingTouchSlop() { 495 return mPagingTouchSlop; 496 } 497 498 /** 499 * @return Distance between the first touch and second touch to still be 500 * considered a double tap 501 * @deprecated Use {@link #getScaledDoubleTapSlop()} instead. 502 * @hide The only client of this should be GestureDetector, which needs this 503 * for clients that still use its deprecated constructor. 504 */ 505 @Deprecated getDoubleTapSlop()506 public static int getDoubleTapSlop() { 507 return DOUBLE_TAP_SLOP; 508 } 509 510 /** 511 * @return Distance between the first touch and second touch to still be 512 * considered a double tap 513 */ getScaledDoubleTapSlop()514 public int getScaledDoubleTapSlop() { 515 return mDoubleTapSlop; 516 } 517 518 /** 519 * @return Distance between a touch up event denoting the end of a touch exploration 520 * gesture and the touch up event of a subsequent tap for the latter tap to be 521 * considered as a tap i.e. to perform a click. 522 * 523 * @hide 524 */ getScaledTouchExplorationTapSlop()525 public int getScaledTouchExplorationTapSlop() { 526 return mScaledTouchExplorationTapSlop; 527 } 528 529 /** 530 * Interval for dispatching a recurring accessibility event in milliseconds. 531 * This interval guarantees that a recurring event will be send at most once 532 * during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame. 533 * 534 * @return The delay in milliseconds. 535 * 536 * @hide 537 */ getSendRecurringAccessibilityEventsInterval()538 public static long getSendRecurringAccessibilityEventsInterval() { 539 return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS; 540 } 541 542 /** 543 * @return Distance a touch must be outside the bounds of a window for it 544 * to be counted as outside the window for purposes of dismissing that 545 * window. 546 * 547 * @deprecated Use {@link #getScaledWindowTouchSlop()} instead. 548 */ 549 @Deprecated getWindowTouchSlop()550 public static int getWindowTouchSlop() { 551 return WINDOW_TOUCH_SLOP; 552 } 553 554 /** 555 * @return Distance a touch must be outside the bounds of a window for it 556 * to be counted as outside the window for purposes of dismissing that 557 * window. 558 */ getScaledWindowTouchSlop()559 public int getScaledWindowTouchSlop() { 560 return mWindowTouchSlop; 561 } 562 563 /** 564 * @return Minimum velocity to initiate a fling, as measured in pixels per second. 565 * 566 * @deprecated Use {@link #getScaledMinimumFlingVelocity()} instead. 567 */ 568 @Deprecated getMinimumFlingVelocity()569 public static int getMinimumFlingVelocity() { 570 return MINIMUM_FLING_VELOCITY; 571 } 572 573 /** 574 * @return Minimum velocity to initiate a fling, as measured in pixels per second. 575 */ getScaledMinimumFlingVelocity()576 public int getScaledMinimumFlingVelocity() { 577 return mMinimumFlingVelocity; 578 } 579 580 /** 581 * @return Maximum velocity to initiate a fling, as measured in pixels per second. 582 * 583 * @deprecated Use {@link #getScaledMaximumFlingVelocity()} instead. 584 */ 585 @Deprecated getMaximumFlingVelocity()586 public static int getMaximumFlingVelocity() { 587 return MAXIMUM_FLING_VELOCITY; 588 } 589 590 /** 591 * @return Maximum velocity to initiate a fling, as measured in pixels per second. 592 */ getScaledMaximumFlingVelocity()593 public int getScaledMaximumFlingVelocity() { 594 return mMaximumFlingVelocity; 595 } 596 597 /** 598 * The maximum drawing cache size expressed in bytes. 599 * 600 * @return the maximum size of View's drawing cache expressed in bytes 601 * 602 * @deprecated Use {@link #getScaledMaximumDrawingCacheSize()} instead. 603 */ 604 @Deprecated getMaximumDrawingCacheSize()605 public static int getMaximumDrawingCacheSize() { 606 //noinspection deprecation 607 return MAXIMUM_DRAWING_CACHE_SIZE; 608 } 609 610 /** 611 * The maximum drawing cache size expressed in bytes. 612 * 613 * @return the maximum size of View's drawing cache expressed in bytes 614 */ getScaledMaximumDrawingCacheSize()615 public int getScaledMaximumDrawingCacheSize() { 616 return mMaximumDrawingCacheSize; 617 } 618 619 /** 620 * @return The maximum distance a View should overscroll by when showing edge effects. 621 */ getScaledOverscrollDistance()622 public int getScaledOverscrollDistance() { 623 return mOverscrollDistance; 624 } 625 626 /** 627 * @return The maximum distance a View should overfling by when showing edge effects. 628 */ getScaledOverflingDistance()629 public int getScaledOverflingDistance() { 630 return mOverflingDistance; 631 } 632 633 /** 634 * The amount of time that the zoom controls should be 635 * displayed on the screen expressed in milliseconds. 636 * 637 * @return the time the zoom controls should be visible expressed 638 * in milliseconds. 639 */ getZoomControlsTimeout()640 public static long getZoomControlsTimeout() { 641 return ZOOM_CONTROLS_TIMEOUT; 642 } 643 644 /** 645 * The amount of time a user needs to press the relevant key to bring up 646 * the global actions dialog. 647 * 648 * @return how long a user needs to press the relevant key to bring up 649 * the global actions dialog. 650 */ getGlobalActionKeyTimeout()651 public static long getGlobalActionKeyTimeout() { 652 return GLOBAL_ACTIONS_KEY_TIMEOUT; 653 } 654 655 /** 656 * The amount of friction applied to scrolls and flings. 657 * 658 * @return A scalar dimensionless value representing the coefficient of 659 * friction. 660 */ getScrollFriction()661 public static float getScrollFriction() { 662 return SCROLL_FRICTION; 663 } 664 665 /** 666 * Report if the device has a permanent menu key available to the user. 667 * 668 * <p>As of Android 3.0, devices may not have a permanent menu key available. 669 * Apps should use the action bar to present menu options to users. 670 * However, there are some apps where the action bar is inappropriate 671 * or undesirable. This method may be used to detect if a menu key is present. 672 * If not, applications should provide another on-screen affordance to access 673 * functionality. 674 * 675 * @return true if a permanent menu key is present, false otherwise. 676 */ hasPermanentMenuKey()677 public boolean hasPermanentMenuKey() { 678 return sHasPermanentMenuKey; 679 } 680 681 /** 682 * @hide 683 * @return Whether or not marquee should use fading edges. 684 */ isFadingMarqueeEnabled()685 public boolean isFadingMarqueeEnabled() { 686 return mFadingMarqueeEnabled; 687 } 688 } 689