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