1/*
2 * Copyright (C) 2011 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.support.v4.view;
18
19import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20
21import android.animation.ValueAnimator;
22import android.content.ClipData;
23import android.content.Context;
24import android.content.res.ColorStateList;
25import android.graphics.Matrix;
26import android.graphics.Paint;
27import android.graphics.PorterDuff;
28import android.graphics.Rect;
29import android.graphics.drawable.Drawable;
30import android.os.Build;
31import android.os.Bundle;
32import android.support.annotation.FloatRange;
33import android.support.annotation.IdRes;
34import android.support.annotation.IntDef;
35import android.support.annotation.NonNull;
36import android.support.annotation.Nullable;
37import android.support.annotation.RequiresApi;
38import android.support.annotation.RestrictTo;
39import android.support.v4.os.BuildCompat;
40import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
41import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
42import android.util.Log;
43import android.view.Display;
44import android.view.MotionEvent;
45import android.view.PointerIcon;
46import android.view.VelocityTracker;
47import android.view.View;
48import android.view.ViewConfiguration;
49import android.view.ViewGroup;
50import android.view.ViewParent;
51import android.view.WindowInsets;
52import android.view.WindowManager;
53import android.view.accessibility.AccessibilityEvent;
54import android.view.accessibility.AccessibilityNodeProvider;
55
56import java.lang.annotation.Retention;
57import java.lang.annotation.RetentionPolicy;
58import java.lang.reflect.Field;
59import java.lang.reflect.InvocationTargetException;
60import java.lang.reflect.Method;
61import java.util.Collection;
62import java.util.WeakHashMap;
63
64/**
65 * Helper for accessing features in {@link View} introduced after API
66 * level 4 in a backwards compatible fashion.
67 */
68public class ViewCompat {
69    private static final String TAG = "ViewCompat";
70
71    /** @hide */
72    @RestrictTo(LIBRARY_GROUP)
73    @IntDef({View.FOCUS_LEFT, View.FOCUS_UP, View.FOCUS_RIGHT, View.FOCUS_DOWN,
74            View.FOCUS_FORWARD, View.FOCUS_BACKWARD})
75    @Retention(RetentionPolicy.SOURCE)
76    public @interface FocusDirection {}
77
78    /** @hide */
79    @RestrictTo(LIBRARY_GROUP)
80    @IntDef({View.FOCUS_LEFT, View.FOCUS_UP, View.FOCUS_RIGHT, View.FOCUS_DOWN})
81    @Retention(RetentionPolicy.SOURCE)
82    public @interface FocusRealDirection {}
83
84    /** @hide */
85    @RestrictTo(LIBRARY_GROUP)
86    @IntDef({View.FOCUS_FORWARD, View.FOCUS_BACKWARD})
87    @Retention(RetentionPolicy.SOURCE)
88    public @interface FocusRelativeDirection {}
89
90    @IntDef({OVER_SCROLL_ALWAYS, OVER_SCROLL_IF_CONTENT_SCROLLS, OVER_SCROLL_NEVER})
91    @Retention(RetentionPolicy.SOURCE)
92    private @interface OverScroll {}
93
94    /**
95     * Always allow a user to over-scroll this view, provided it is a
96     * view that can scroll.
97     * @deprecated Use {@link View#OVER_SCROLL_ALWAYS} directly. This constant will be removed in
98     * a future release.
99     */
100    @Deprecated
101    public static final int OVER_SCROLL_ALWAYS = 0;
102
103    /**
104     * Allow a user to over-scroll this view only if the content is large
105     * enough to meaningfully scroll, provided it is a view that can scroll.
106     * @deprecated Use {@link View#OVER_SCROLL_IF_CONTENT_SCROLLS} directly. This constant will be
107     * removed in a future release.
108     */
109    @Deprecated
110    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
111
112    /**
113     * Never allow a user to over-scroll this view.
114     * @deprecated Use {@link View#OVER_SCROLL_NEVER} directly. This constant will be removed in
115     * a future release.
116     */
117    @Deprecated
118    public static final int OVER_SCROLL_NEVER = 2;
119
120    @IntDef({
121            IMPORTANT_FOR_ACCESSIBILITY_AUTO,
122            IMPORTANT_FOR_ACCESSIBILITY_YES,
123            IMPORTANT_FOR_ACCESSIBILITY_NO,
124            IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
125    })
126    @Retention(RetentionPolicy.SOURCE)
127    private @interface ImportantForAccessibility {}
128
129    /**
130     * Automatically determine whether a view is important for accessibility.
131     */
132    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
133
134    /**
135     * The view is important for accessibility.
136     */
137    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
138
139    /**
140     * The view is not important for accessibility.
141     */
142    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
143
144    /**
145     * The view is not important for accessibility, nor are any of its
146     * descendant views.
147     */
148    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
149
150    @IntDef({
151            ACCESSIBILITY_LIVE_REGION_NONE,
152            ACCESSIBILITY_LIVE_REGION_POLITE,
153            ACCESSIBILITY_LIVE_REGION_ASSERTIVE
154    })
155    @Retention(RetentionPolicy.SOURCE)
156    private @interface AccessibilityLiveRegion {}
157
158    /**
159     * Live region mode specifying that accessibility services should not
160     * automatically announce changes to this view. This is the default live
161     * region mode for most views.
162     * <p>
163     * Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}.
164     */
165    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
166
167    /**
168     * Live region mode specifying that accessibility services should announce
169     * changes to this view.
170     * <p>
171     * Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}.
172     */
173    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
174
175    /**
176     * Live region mode specifying that accessibility services should interrupt
177     * ongoing speech to immediately announce changes to this view.
178     * <p>
179     * Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}.
180     */
181    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
182
183    @IntDef({View.LAYER_TYPE_NONE, View.LAYER_TYPE_SOFTWARE, View.LAYER_TYPE_HARDWARE})
184    @Retention(RetentionPolicy.SOURCE)
185    private @interface LayerType {}
186
187    /**
188     * Indicates that the view does not have a layer.
189     *
190     * @deprecated Use {@link View#LAYER_TYPE_NONE} directly.
191     */
192    @Deprecated
193    public static final int LAYER_TYPE_NONE = 0;
194
195    /**
196     * <p>Indicates that the view has a software layer. A software layer is backed
197     * by a bitmap and causes the view to be rendered using Android's software
198     * rendering pipeline, even if hardware acceleration is enabled.</p>
199     *
200     * <p>Software layers have various usages:</p>
201     * <p>When the application is not using hardware acceleration, a software layer
202     * is useful to apply a specific color filter and/or blending mode and/or
203     * translucency to a view and all its children.</p>
204     * <p>When the application is using hardware acceleration, a software layer
205     * is useful to render drawing primitives not supported by the hardware
206     * accelerated pipeline. It can also be used to cache a complex view tree
207     * into a texture and reduce the complexity of drawing operations. For instance,
208     * when animating a complex view tree with a translation, a software layer can
209     * be used to render the view tree only once.</p>
210     * <p>Software layers should be avoided when the affected view tree updates
211     * often. Every update will require to re-render the software layer, which can
212     * potentially be slow (particularly when hardware acceleration is turned on
213     * since the layer will have to be uploaded into a hardware texture after every
214     * update.)</p>
215     *
216     * @deprecated Use {@link View#LAYER_TYPE_SOFTWARE} directly.
217     */
218    @Deprecated
219    public static final int LAYER_TYPE_SOFTWARE = 1;
220
221    /**
222     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
223     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
224     * OpenGL hardware) and causes the view to be rendered using Android's hardware
225     * rendering pipeline, but only if hardware acceleration is turned on for the
226     * view hierarchy. When hardware acceleration is turned off, hardware layers
227     * behave exactly as {@link View#LAYER_TYPE_SOFTWARE software layers}.</p>
228     *
229     * <p>A hardware layer is useful to apply a specific color filter and/or
230     * blending mode and/or translucency to a view and all its children.</p>
231     * <p>A hardware layer can be used to cache a complex view tree into a
232     * texture and reduce the complexity of drawing operations. For instance,
233     * when animating a complex view tree with a translation, a hardware layer can
234     * be used to render the view tree only once.</p>
235     * <p>A hardware layer can also be used to increase the rendering quality when
236     * rotation transformations are applied on a view. It can also be used to
237     * prevent potential clipping issues when applying 3D transforms on a view.</p>
238     *
239     * @deprecated Use {@link View#LAYER_TYPE_HARDWARE} directly.
240     */
241    @Deprecated
242    public static final int LAYER_TYPE_HARDWARE = 2;
243
244    @IntDef({
245            LAYOUT_DIRECTION_LTR,
246            LAYOUT_DIRECTION_RTL,
247            LAYOUT_DIRECTION_INHERIT,
248            LAYOUT_DIRECTION_LOCALE})
249    @Retention(RetentionPolicy.SOURCE)
250    private @interface LayoutDirectionMode {}
251
252    @IntDef({
253            LAYOUT_DIRECTION_LTR,
254            LAYOUT_DIRECTION_RTL
255    })
256    @Retention(RetentionPolicy.SOURCE)
257    private @interface ResolvedLayoutDirectionMode {}
258
259    /**
260     * Horizontal layout direction of this view is from Left to Right.
261     */
262    public static final int LAYOUT_DIRECTION_LTR = 0;
263
264    /**
265     * Horizontal layout direction of this view is from Right to Left.
266     */
267    public static final int LAYOUT_DIRECTION_RTL = 1;
268
269    /**
270     * Horizontal layout direction of this view is inherited from its parent.
271     * Use with {@link #setLayoutDirection}.
272     */
273    public static final int LAYOUT_DIRECTION_INHERIT = 2;
274
275    /**
276     * Horizontal layout direction of this view is from deduced from the default language
277     * script for the locale. Use with {@link #setLayoutDirection}.
278     */
279    public static final int LAYOUT_DIRECTION_LOCALE = 3;
280
281    /**
282     * Bits of {@link #getMeasuredWidthAndState} and
283     * {@link #getMeasuredWidthAndState} that provide the actual measured size.
284     *
285     * @deprecated Use {@link View#MEASURED_SIZE_MASK} directly.
286     */
287    @Deprecated
288    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
289
290    /**
291     * Bits of {@link #getMeasuredWidthAndState} and
292     * {@link #getMeasuredWidthAndState} that provide the additional state bits.
293     *
294     * @deprecated Use {@link View#MEASURED_STATE_MASK} directly.
295     */
296    @Deprecated
297    public static final int MEASURED_STATE_MASK = 0xff000000;
298
299    /**
300     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
301     * for functions that combine both width and height into a single int,
302     * such as {@link #getMeasuredState} and the childState argument of
303     * {@link #resolveSizeAndState(int, int, int)}.
304     *
305     * @deprecated Use {@link View#MEASURED_HEIGHT_STATE_SHIFT} directly.
306     */
307    @Deprecated
308    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
309
310    /**
311     * Bit of {@link #getMeasuredWidthAndState} and
312     * {@link #getMeasuredWidthAndState} that indicates the measured size
313     * is smaller that the space the view would like to have.
314     *
315     * @deprecated Use {@link View#MEASURED_STATE_TOO_SMALL} directly.
316     */
317    @Deprecated
318    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
319
320    /**
321     * @hide
322     */
323    @IntDef(value = {SCROLL_AXIS_NONE, SCROLL_AXIS_HORIZONTAL, SCROLL_AXIS_VERTICAL}, flag = true)
324    @Retention(RetentionPolicy.SOURCE)
325    @RestrictTo(LIBRARY_GROUP)
326    public @interface ScrollAxis {}
327
328    /**
329     * Indicates no axis of view scrolling.
330     */
331    public static final int SCROLL_AXIS_NONE = 0;
332
333    /**
334     * Indicates scrolling along the horizontal axis.
335     */
336    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
337
338    /**
339     * Indicates scrolling along the vertical axis.
340     */
341    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
342
343    /**
344     * @hide
345     */
346    @IntDef({TYPE_TOUCH, TYPE_NON_TOUCH})
347    @Retention(RetentionPolicy.SOURCE)
348    @RestrictTo(LIBRARY_GROUP)
349    public @interface NestedScrollType {}
350
351    /**
352     * Indicates that the input type for the gesture is from a user touching the screen.
353     */
354    public static final int TYPE_TOUCH = 0;
355
356    /**
357     * Indicates that the input type for the gesture is caused by something which is not a user
358     * touching a screen. This is usually from a fling which is settling.
359     */
360    public static final int TYPE_NON_TOUCH = 1;
361
362    /** @hide */
363    @RestrictTo(LIBRARY_GROUP)
364    @Retention(RetentionPolicy.SOURCE)
365    @IntDef(flag = true,
366            value = {
367                    SCROLL_INDICATOR_TOP,
368                    SCROLL_INDICATOR_BOTTOM,
369                    SCROLL_INDICATOR_LEFT,
370                    SCROLL_INDICATOR_RIGHT,
371                    SCROLL_INDICATOR_START,
372                    SCROLL_INDICATOR_END,
373            })
374    public @interface ScrollIndicators {}
375
376    /**
377     * Scroll indicator direction for the top edge of the view.
378     *
379     * @see #setScrollIndicators(View, int)
380     * @see #setScrollIndicators(View, int, int)
381     * @see #getScrollIndicators(View)
382     */
383    public static final int SCROLL_INDICATOR_TOP = 0x1;
384
385    /**
386     * Scroll indicator direction for the bottom edge of the view.
387     *
388     * @see #setScrollIndicators(View, int)
389     * @see #setScrollIndicators(View, int, int)
390     * @see #getScrollIndicators(View)
391     */
392    public static final int SCROLL_INDICATOR_BOTTOM = 0x2;
393
394    /**
395     * Scroll indicator direction for the left edge of the view.
396     *
397     * @see #setScrollIndicators(View, int)
398     * @see #setScrollIndicators(View, int, int)
399     * @see #getScrollIndicators(View)
400     */
401    public static final int SCROLL_INDICATOR_LEFT = 0x4;
402
403    /**
404     * Scroll indicator direction for the right edge of the view.
405     *
406     * @see #setScrollIndicators(View, int)
407     * @see #setScrollIndicators(View, int, int)
408     * @see #getScrollIndicators(View)
409     */
410    public static final int SCROLL_INDICATOR_RIGHT = 0x8;
411
412    /**
413     * Scroll indicator direction for the starting edge of the view.
414     *
415     * @see #setScrollIndicators(View, int)
416     * @see #setScrollIndicators(View, int, int)
417     * @see #getScrollIndicators(View)
418     */
419    public static final int SCROLL_INDICATOR_START = 0x10;
420
421    /**
422     * Scroll indicator direction for the ending edge of the view.
423     *
424     * @see #setScrollIndicators(View, int)
425     * @see #setScrollIndicators(View, int, int)
426     * @see #getScrollIndicators(View)
427     */
428    public static final int SCROLL_INDICATOR_END = 0x20;
429
430    static class ViewCompatBaseImpl {
431        private static Field sMinWidthField;
432        private static boolean sMinWidthFieldFetched;
433        private static Field sMinHeightField;
434        private static boolean sMinHeightFieldFetched;
435        private static WeakHashMap<View, String> sTransitionNameMap;
436        private Method mDispatchStartTemporaryDetach;
437        private Method mDispatchFinishTemporaryDetach;
438        private boolean mTempDetachBound;
439        WeakHashMap<View, ViewPropertyAnimatorCompat> mViewPropertyAnimatorCompatMap = null;
440        private static Method sChildrenDrawingOrderMethod;
441        static Field sAccessibilityDelegateField;
442        static boolean sAccessibilityDelegateCheckFailed = false;
443
444        public void setAccessibilityDelegate(View v,
445                @Nullable AccessibilityDelegateCompat delegate) {
446            v.setAccessibilityDelegate(delegate == null ? null : delegate.getBridge());
447        }
448
449        public boolean hasAccessibilityDelegate(View v) {
450            if (sAccessibilityDelegateCheckFailed) {
451                return false; // View implementation might have changed.
452            }
453            if (sAccessibilityDelegateField == null) {
454                try {
455                    sAccessibilityDelegateField = View.class
456                            .getDeclaredField("mAccessibilityDelegate");
457                    sAccessibilityDelegateField.setAccessible(true);
458                } catch (Throwable t) {
459                    sAccessibilityDelegateCheckFailed = true;
460                    return false;
461                }
462            }
463            try {
464                return sAccessibilityDelegateField.get(v) != null;
465            } catch (Throwable t) {
466                sAccessibilityDelegateCheckFailed = true;
467                return false;
468            }
469        }
470
471        public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
472            v.onInitializeAccessibilityNodeInfo(info.unwrap());
473        }
474
475        @SuppressWarnings("deprecation")
476        public boolean startDragAndDrop(View v, ClipData data, View.DragShadowBuilder shadowBuilder,
477                Object localState, int flags) {
478            return v.startDrag(data, shadowBuilder, localState, flags);
479        }
480
481        public void cancelDragAndDrop(View v) {
482            // no-op
483        }
484
485        public void updateDragShadow(View v, View.DragShadowBuilder shadowBuilder) {
486            // no-op
487        }
488
489        public boolean hasTransientState(View view) {
490            // A view can't have transient state if transient state wasn't supported.
491            return false;
492        }
493
494        public void setHasTransientState(View view, boolean hasTransientState) {
495            // Do nothing; API doesn't exist
496        }
497
498        public void postInvalidateOnAnimation(View view) {
499            view.postInvalidate();
500        }
501
502        public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) {
503            view.postInvalidate(left, top, right, bottom);
504        }
505
506        public void postOnAnimation(View view, Runnable action) {
507            view.postDelayed(action, getFrameTime());
508        }
509
510        public void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
511            view.postDelayed(action, getFrameTime() + delayMillis);
512        }
513
514        long getFrameTime() {
515            return ValueAnimator.getFrameDelay();
516        }
517
518        public int getImportantForAccessibility(View view) {
519            return 0;
520        }
521
522        public void setImportantForAccessibility(View view, int mode) {
523        }
524
525        public boolean isImportantForAccessibility(View view) {
526            return true;
527        }
528
529        public boolean performAccessibilityAction(View view, int action, Bundle arguments) {
530            return false;
531        }
532
533        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
534            return null;
535        }
536
537        public int getLabelFor(View view) {
538            return 0;
539        }
540
541        public void setLabelFor(View view, int id) {
542        }
543
544        public void setLayerPaint(View view, Paint paint) {
545            // Make sure the paint is correct; this will be cheap if it's the same
546            // instance as was used to call setLayerType earlier.
547            view.setLayerType(view.getLayerType(), paint);
548            // This is expensive, but the only way to accomplish this before JB-MR1.
549            view.invalidate();
550        }
551
552        public int getLayoutDirection(View view) {
553            return LAYOUT_DIRECTION_LTR;
554        }
555
556        public void setLayoutDirection(View view, int layoutDirection) {
557            // No-op
558        }
559
560        public ViewParent getParentForAccessibility(View view) {
561            return view.getParent();
562        }
563
564        public int getAccessibilityLiveRegion(View view) {
565            return ACCESSIBILITY_LIVE_REGION_NONE;
566        }
567
568        public void setAccessibilityLiveRegion(View view, int mode) {
569            // No-op
570        }
571
572        public int getPaddingStart(View view) {
573            return view.getPaddingLeft();
574        }
575
576        public int getPaddingEnd(View view) {
577            return view.getPaddingRight();
578        }
579
580        public void setPaddingRelative(View view, int start, int top, int end, int bottom) {
581            view.setPadding(start, top, end, bottom);
582        }
583
584        public void dispatchStartTemporaryDetach(View view) {
585            if (!mTempDetachBound) {
586                bindTempDetach();
587            }
588            if (mDispatchStartTemporaryDetach != null) {
589                try {
590                    mDispatchStartTemporaryDetach.invoke(view);
591                } catch (Exception e) {
592                    Log.d(TAG, "Error calling dispatchStartTemporaryDetach", e);
593                }
594            } else {
595                // Try this instead
596                view.onStartTemporaryDetach();
597            }
598        }
599
600        public void dispatchFinishTemporaryDetach(View view) {
601            if (!mTempDetachBound) {
602                bindTempDetach();
603            }
604            if (mDispatchFinishTemporaryDetach != null) {
605                try {
606                    mDispatchFinishTemporaryDetach.invoke(view);
607                } catch (Exception e) {
608                    Log.d(TAG, "Error calling dispatchFinishTemporaryDetach", e);
609                }
610            } else {
611                // Try this instead
612                view.onFinishTemporaryDetach();
613            }
614        }
615
616        public boolean hasOverlappingRendering(View view) {
617            return true;
618        }
619
620        private void bindTempDetach() {
621            try {
622                mDispatchStartTemporaryDetach = View.class.getDeclaredMethod(
623                        "dispatchStartTemporaryDetach");
624                mDispatchFinishTemporaryDetach = View.class.getDeclaredMethod(
625                        "dispatchFinishTemporaryDetach");
626            } catch (NoSuchMethodException e) {
627                Log.e(TAG, "Couldn't find method", e);
628            }
629            mTempDetachBound = true;
630        }
631
632        public int getMinimumWidth(View view) {
633            if (!sMinWidthFieldFetched) {
634                try {
635                    sMinWidthField = View.class.getDeclaredField("mMinWidth");
636                    sMinWidthField.setAccessible(true);
637                } catch (NoSuchFieldException e) {
638                    // Couldn't find the field. Abort!
639                }
640                sMinWidthFieldFetched = true;
641            }
642
643            if (sMinWidthField != null) {
644                try {
645                    return (int) sMinWidthField.get(view);
646                } catch (Exception e) {
647                    // Field get failed. Oh well...
648                }
649            }
650
651            // We failed, return 0
652            return 0;
653        }
654
655        public int getMinimumHeight(View view) {
656            if (!sMinHeightFieldFetched) {
657                try {
658                    sMinHeightField = View.class.getDeclaredField("mMinHeight");
659                    sMinHeightField.setAccessible(true);
660                } catch (NoSuchFieldException e) {
661                    // Couldn't find the field. Abort!
662                }
663                sMinHeightFieldFetched = true;
664            }
665
666            if (sMinHeightField != null) {
667                try {
668                    return (int) sMinHeightField.get(view);
669                } catch (Exception e) {
670                    // Field get failed. Oh well...
671                }
672            }
673
674            // We failed, return 0
675            return 0;
676        }
677
678        public ViewPropertyAnimatorCompat animate(View view) {
679            if (mViewPropertyAnimatorCompatMap == null) {
680                mViewPropertyAnimatorCompatMap = new WeakHashMap<>();
681            }
682            ViewPropertyAnimatorCompat vpa = mViewPropertyAnimatorCompatMap.get(view);
683            if (vpa == null) {
684                vpa = new ViewPropertyAnimatorCompat(view);
685                mViewPropertyAnimatorCompatMap.put(view, vpa);
686            }
687            return vpa;
688        }
689
690        public void setTransitionName(View view, String transitionName) {
691            if (sTransitionNameMap == null) {
692                sTransitionNameMap = new WeakHashMap<>();
693            }
694            sTransitionNameMap.put(view, transitionName);
695        }
696
697        public String getTransitionName(View view) {
698            if (sTransitionNameMap == null) {
699                return null;
700            }
701            return sTransitionNameMap.get(view);
702        }
703
704        public int getWindowSystemUiVisibility(View view) {
705            return 0;
706        }
707
708        public void requestApplyInsets(View view) {
709        }
710
711        public void setElevation(View view, float elevation) {
712        }
713
714        public float getElevation(View view) {
715            return 0f;
716        }
717
718        public void setTranslationZ(View view, float translationZ) {
719        }
720
721        public float getTranslationZ(View view) {
722            return 0f;
723        }
724
725        public void setClipBounds(View view, Rect clipBounds) {
726        }
727
728        public Rect getClipBounds(View view) {
729            return null;
730        }
731
732        public void setChildrenDrawingOrderEnabled(ViewGroup viewGroup, boolean enabled) {
733            if (sChildrenDrawingOrderMethod == null) {
734                try {
735                    sChildrenDrawingOrderMethod = ViewGroup.class
736                            .getDeclaredMethod("setChildrenDrawingOrderEnabled", boolean.class);
737                } catch (NoSuchMethodException e) {
738                    Log.e(TAG, "Unable to find childrenDrawingOrderEnabled", e);
739                }
740                sChildrenDrawingOrderMethod.setAccessible(true);
741            }
742            try {
743                sChildrenDrawingOrderMethod.invoke(viewGroup, enabled);
744            } catch (IllegalAccessException e) {
745                Log.e(TAG, "Unable to invoke childrenDrawingOrderEnabled", e);
746            } catch (IllegalArgumentException e) {
747                Log.e(TAG, "Unable to invoke childrenDrawingOrderEnabled", e);
748            } catch (InvocationTargetException e) {
749                Log.e(TAG, "Unable to invoke childrenDrawingOrderEnabled", e);
750            }
751        }
752
753        public boolean getFitsSystemWindows(View view) {
754            return false;
755        }
756
757        public void setOnApplyWindowInsetsListener(View view,
758                OnApplyWindowInsetsListener listener) {
759            // noop
760        }
761
762        public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
763            return insets;
764        }
765
766        public WindowInsetsCompat dispatchApplyWindowInsets(View v, WindowInsetsCompat insets) {
767            return insets;
768        }
769
770        public boolean isPaddingRelative(View view) {
771            return false;
772        }
773
774        public void setNestedScrollingEnabled(View view, boolean enabled) {
775            if (view instanceof NestedScrollingChild) {
776                ((NestedScrollingChild) view).setNestedScrollingEnabled(enabled);
777            }
778        }
779
780        public boolean isNestedScrollingEnabled(View view) {
781            if (view instanceof NestedScrollingChild) {
782                return ((NestedScrollingChild) view).isNestedScrollingEnabled();
783            }
784            return false;
785        }
786
787        public void setBackground(View view, Drawable background) {
788            view.setBackgroundDrawable(background);
789        }
790
791        public ColorStateList getBackgroundTintList(View view) {
792            return (view instanceof TintableBackgroundView)
793                    ? ((TintableBackgroundView) view).getSupportBackgroundTintList()
794                    : null;
795        }
796
797        public void setBackgroundTintList(View view, ColorStateList tintList) {
798            if (view instanceof TintableBackgroundView) {
799                ((TintableBackgroundView) view).setSupportBackgroundTintList(tintList);
800            }
801        }
802
803        public void setBackgroundTintMode(View view, PorterDuff.Mode mode) {
804            if (view instanceof TintableBackgroundView) {
805                ((TintableBackgroundView) view).setSupportBackgroundTintMode(mode);
806            }
807        }
808
809        public PorterDuff.Mode getBackgroundTintMode(View view) {
810            return (view instanceof TintableBackgroundView)
811                    ? ((TintableBackgroundView) view).getSupportBackgroundTintMode()
812                    : null;
813        }
814
815        public boolean startNestedScroll(View view, int axes) {
816            if (view instanceof NestedScrollingChild) {
817                return ((NestedScrollingChild) view).startNestedScroll(axes);
818            }
819            return false;
820        }
821
822        public void stopNestedScroll(View view) {
823            if (view instanceof NestedScrollingChild) {
824                ((NestedScrollingChild) view).stopNestedScroll();
825            }
826        }
827
828        public boolean hasNestedScrollingParent(View view) {
829            if (view instanceof NestedScrollingChild) {
830                return ((NestedScrollingChild) view).hasNestedScrollingParent();
831            }
832            return false;
833        }
834
835        public boolean dispatchNestedScroll(View view, int dxConsumed, int dyConsumed,
836                int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
837            if (view instanceof NestedScrollingChild) {
838                return ((NestedScrollingChild) view).dispatchNestedScroll(dxConsumed, dyConsumed,
839                        dxUnconsumed, dyUnconsumed, offsetInWindow);
840            }
841            return false;
842        }
843
844        public boolean dispatchNestedPreScroll(View view, int dx, int dy,
845                int[] consumed, int[] offsetInWindow) {
846            if (view instanceof NestedScrollingChild) {
847                return ((NestedScrollingChild) view).dispatchNestedPreScroll(dx, dy, consumed,
848                        offsetInWindow);
849            }
850            return false;
851        }
852
853        public boolean dispatchNestedFling(View view, float velocityX, float velocityY,
854                boolean consumed) {
855            if (view instanceof NestedScrollingChild) {
856                return ((NestedScrollingChild) view).dispatchNestedFling(velocityX, velocityY,
857                        consumed);
858            }
859            return false;
860        }
861
862        public boolean dispatchNestedPreFling(View view, float velocityX, float velocityY) {
863            if (view instanceof NestedScrollingChild) {
864                return ((NestedScrollingChild) view).dispatchNestedPreFling(velocityX, velocityY);
865            }
866            return false;
867        }
868
869        public boolean isInLayout(View view) {
870            return false;
871        }
872
873        public boolean isLaidOut(View view) {
874            return view.getWidth() > 0 && view.getHeight() > 0;
875        }
876
877        public boolean isLayoutDirectionResolved(View view) {
878            return false;
879        }
880
881        public float getZ(View view) {
882            return getTranslationZ(view) + getElevation(view);
883        }
884
885        public void setZ(View view, float z) {
886            // no-op
887        }
888
889        public boolean isAttachedToWindow(View view) {
890            return view.getWindowToken() != null;
891        }
892
893        public boolean hasOnClickListeners(View view) {
894            return false;
895        }
896
897        public int getScrollIndicators(View view) {
898            return 0;
899        }
900
901        public void setScrollIndicators(View view, int indicators) {
902            // no-op
903        }
904
905        public void setScrollIndicators(View view, int indicators, int mask) {
906            // no-op
907        }
908
909        public void offsetLeftAndRight(View view, int offset) {
910            view.offsetLeftAndRight(offset);
911            if (view.getVisibility() == View.VISIBLE) {
912                tickleInvalidationFlag(view);
913
914                ViewParent parent = view.getParent();
915                if (parent instanceof View) {
916                    tickleInvalidationFlag((View) parent);
917                }
918            }
919        }
920
921        public void offsetTopAndBottom(View view, int offset) {
922            view.offsetTopAndBottom(offset);
923            if (view.getVisibility() == View.VISIBLE) {
924                tickleInvalidationFlag(view);
925
926                ViewParent parent = view.getParent();
927                if (parent instanceof View) {
928                    tickleInvalidationFlag((View) parent);
929                }
930            }
931        }
932
933        private static void tickleInvalidationFlag(View view) {
934            final float y = view.getTranslationY();
935            view.setTranslationY(y + 1);
936            view.setTranslationY(y);
937        }
938
939        public void setPointerIcon(View view, PointerIconCompat pointerIcon) {
940            // no-op
941        }
942
943        public Display getDisplay(View view) {
944            if (isAttachedToWindow(view)) {
945                final WindowManager wm = (WindowManager) view.getContext().getSystemService(
946                        Context.WINDOW_SERVICE);
947                return wm.getDefaultDisplay();
948            }
949            return null;
950        }
951
952        public void setTooltipText(View view, CharSequence tooltipText) {
953        }
954
955        public int getNextClusterForwardId(@NonNull View view) {
956            return View.NO_ID;
957        }
958
959        public void setNextClusterForwardId(@NonNull View view, int nextClusterForwardId) {
960            // no-op
961        }
962
963        public boolean isKeyboardNavigationCluster(@NonNull View view) {
964            return false;
965        }
966
967        public void setKeyboardNavigationCluster(@NonNull View view, boolean isCluster) {
968            // no-op
969        }
970
971        public boolean isFocusedByDefault(@NonNull View view) {
972            return false;
973        }
974
975        public void setFocusedByDefault(@NonNull View view, boolean isFocusedByDefault) {
976            // no-op
977        }
978
979        public View keyboardNavigationClusterSearch(@NonNull View view, View currentCluster,
980                @FocusDirection int direction) {
981            return null;
982        }
983
984        public void addKeyboardNavigationClusters(@NonNull View view,
985                @NonNull Collection<View> views, int direction) {
986            // no-op
987        }
988
989        public boolean restoreDefaultFocus(@NonNull View view) {
990            return view.requestFocus();
991        }
992    }
993
994    @RequiresApi(15)
995    static class ViewCompatApi15Impl extends ViewCompatBaseImpl {
996        @Override
997        public boolean hasOnClickListeners(View view) {
998            return view.hasOnClickListeners();
999        }
1000    }
1001
1002    @RequiresApi(16)
1003    static class ViewCompatApi16Impl extends ViewCompatApi15Impl {
1004        @Override
1005        public boolean hasTransientState(View view) {
1006            return view.hasTransientState();
1007        }
1008        @Override
1009        public void setHasTransientState(View view, boolean hasTransientState) {
1010            view.setHasTransientState(hasTransientState);
1011        }
1012        @Override
1013        public void postInvalidateOnAnimation(View view) {
1014            view.postInvalidateOnAnimation();
1015        }
1016        @Override
1017        public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) {
1018            view.postInvalidateOnAnimation(left, top, right, bottom);
1019        }
1020        @Override
1021        public void postOnAnimation(View view, Runnable action) {
1022            view.postOnAnimation(action);
1023        }
1024        @Override
1025        public void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
1026            view.postOnAnimationDelayed(action, delayMillis);
1027        }
1028        @Override
1029        public int getImportantForAccessibility(View view) {
1030            return view.getImportantForAccessibility();
1031        }
1032        @Override
1033        public void setImportantForAccessibility(View view, int mode) {
1034            // IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS is not available
1035            // on this platform so replace with IMPORTANT_FOR_ACCESSIBILITY_NO
1036            // which is closer semantically.
1037            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
1038                mode = IMPORTANT_FOR_ACCESSIBILITY_NO;
1039            }
1040            //noinspection WrongConstant
1041            view.setImportantForAccessibility(mode);
1042        }
1043        @Override
1044        public boolean performAccessibilityAction(View view, int action, Bundle arguments) {
1045            return view.performAccessibilityAction(action, arguments);
1046        }
1047        @Override
1048        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
1049            AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
1050            if (provider != null) {
1051                return new AccessibilityNodeProviderCompat(provider);
1052            }
1053            return null;
1054        }
1055
1056        @Override
1057        public ViewParent getParentForAccessibility(View view) {
1058            return view.getParentForAccessibility();
1059        }
1060
1061        @Override
1062        public int getMinimumWidth(View view) {
1063            return view.getMinimumWidth();
1064        }
1065
1066        @Override
1067        public int getMinimumHeight(View view) {
1068            return view.getMinimumHeight();
1069        }
1070
1071        @SuppressWarnings("deprecation")
1072        @Override
1073        public void requestApplyInsets(View view) {
1074            view.requestFitSystemWindows();
1075        }
1076
1077        @Override
1078        public boolean getFitsSystemWindows(View view) {
1079            return view.getFitsSystemWindows();
1080        }
1081
1082        @Override
1083        public boolean hasOverlappingRendering(View view) {
1084            return view.hasOverlappingRendering();
1085        }
1086
1087        @Override
1088        public void setBackground(View view, Drawable background) {
1089            view.setBackground(background);
1090        }
1091    }
1092
1093    @RequiresApi(17)
1094    static class ViewCompatApi17Impl extends ViewCompatApi16Impl {
1095
1096        @Override
1097        public int getLabelFor(View view) {
1098            return view.getLabelFor();
1099        }
1100
1101        @Override
1102        public void setLabelFor(View view, int id) {
1103            view.setLabelFor(id);
1104        }
1105
1106        @Override
1107        public void setLayerPaint(View view, Paint paint) {
1108            view.setLayerPaint(paint);
1109        }
1110
1111        @Override
1112        public int getLayoutDirection(View view) {
1113            return view.getLayoutDirection();
1114        }
1115
1116        @Override
1117        public void setLayoutDirection(View view, int layoutDirection) {
1118            view.setLayoutDirection(layoutDirection);
1119        }
1120
1121        @Override
1122        public int getPaddingStart(View view) {
1123            return view.getPaddingStart();
1124        }
1125
1126        @Override
1127        public int getPaddingEnd(View view) {
1128            return view.getPaddingEnd();
1129        }
1130
1131        @Override
1132        public void setPaddingRelative(View view, int start, int top, int end, int bottom) {
1133            view.setPaddingRelative(start, top, end, bottom);
1134        }
1135
1136        @Override
1137        public int getWindowSystemUiVisibility(View view) {
1138            return view.getWindowSystemUiVisibility();
1139        }
1140
1141        @Override
1142        public boolean isPaddingRelative(View view) {
1143            return view.isPaddingRelative();
1144        }
1145
1146        @Override
1147        public Display getDisplay(View view) {
1148            return view.getDisplay();
1149        }
1150    }
1151
1152    @RequiresApi(18)
1153    static class ViewCompatApi18Impl extends ViewCompatApi17Impl {
1154        @Override
1155        public void setClipBounds(View view, Rect clipBounds) {
1156            view.setClipBounds(clipBounds);
1157        }
1158
1159        @Override
1160        public Rect getClipBounds(View view) {
1161            return view.getClipBounds();
1162        }
1163
1164        @Override
1165        public boolean isInLayout(View view) {
1166            return view.isInLayout();
1167        }
1168    }
1169
1170    @RequiresApi(19)
1171    static class ViewCompatApi19Impl extends ViewCompatApi18Impl {
1172        @Override
1173        public int getAccessibilityLiveRegion(View view) {
1174            return view.getAccessibilityLiveRegion();
1175        }
1176
1177        @Override
1178        public void setAccessibilityLiveRegion(View view, int mode) {
1179            view.setAccessibilityLiveRegion(mode);
1180        }
1181
1182        @Override
1183        public void setImportantForAccessibility(View view, int mode) {
1184            view.setImportantForAccessibility(mode);
1185        }
1186
1187        @Override
1188        public boolean isLaidOut(View view) {
1189            return view.isLaidOut();
1190        }
1191
1192        @Override
1193        public boolean isLayoutDirectionResolved(View view) {
1194            return view.isLayoutDirectionResolved();
1195        }
1196
1197        @Override
1198        public boolean isAttachedToWindow(View view) {
1199            return view.isAttachedToWindow();
1200        }
1201    }
1202
1203    @RequiresApi(21)
1204    static class ViewCompatApi21Impl extends ViewCompatApi19Impl {
1205        private static ThreadLocal<Rect> sThreadLocalRect;
1206
1207        @Override
1208        public void setTransitionName(View view, String transitionName) {
1209            view.setTransitionName(transitionName);
1210        }
1211
1212        @Override
1213        public String getTransitionName(View view) {
1214            return view.getTransitionName();
1215        }
1216
1217        @Override
1218        public void requestApplyInsets(View view) {
1219            view.requestApplyInsets();
1220        }
1221
1222        @Override
1223        public void setElevation(View view, float elevation) {
1224            view.setElevation(elevation);
1225        }
1226
1227        @Override
1228        public float getElevation(View view) {
1229            return view.getElevation();
1230        }
1231
1232        @Override
1233        public void setTranslationZ(View view, float translationZ) {
1234            view.setTranslationZ(translationZ);
1235        }
1236
1237        @Override
1238        public float getTranslationZ(View view) {
1239            return view.getTranslationZ();
1240        }
1241
1242        @Override
1243        public void setOnApplyWindowInsetsListener(View view,
1244                final OnApplyWindowInsetsListener listener) {
1245            if (listener == null) {
1246                view.setOnApplyWindowInsetsListener(null);
1247                return;
1248            }
1249
1250            view.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
1251                @Override
1252                public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
1253                    WindowInsetsCompat compatInsets = WindowInsetsCompat.wrap(insets);
1254                    compatInsets = listener.onApplyWindowInsets(view, compatInsets);
1255                    return (WindowInsets) WindowInsetsCompat.unwrap(compatInsets);
1256                }
1257            });
1258        }
1259
1260        @Override
1261        public void setNestedScrollingEnabled(View view, boolean enabled) {
1262            view.setNestedScrollingEnabled(enabled);
1263        }
1264
1265        @Override
1266        public boolean isNestedScrollingEnabled(View view) {
1267            return view.isNestedScrollingEnabled();
1268        }
1269
1270        @Override
1271        public boolean startNestedScroll(View view, int axes) {
1272            return view.startNestedScroll(axes);
1273        }
1274
1275        @Override
1276        public void stopNestedScroll(View view) {
1277            view.stopNestedScroll();
1278        }
1279
1280        @Override
1281        public boolean hasNestedScrollingParent(View view) {
1282            return view.hasNestedScrollingParent();
1283        }
1284
1285        @Override
1286        public boolean dispatchNestedScroll(View view, int dxConsumed, int dyConsumed,
1287                int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
1288            return view.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,
1289                    offsetInWindow);
1290        }
1291
1292        @Override
1293        public boolean dispatchNestedPreScroll(View view, int dx, int dy,
1294                int[] consumed, int[] offsetInWindow) {
1295            return view.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
1296        }
1297
1298        @Override
1299        public boolean dispatchNestedFling(View view, float velocityX, float velocityY,
1300                boolean consumed) {
1301            return view.dispatchNestedFling(velocityX, velocityY, consumed);
1302        }
1303
1304        @Override
1305        public boolean dispatchNestedPreFling(View view, float velocityX, float velocityY) {
1306            return view.dispatchNestedPreFling(velocityX, velocityY);
1307        }
1308
1309        @Override
1310        public boolean isImportantForAccessibility(View view) {
1311            return view.isImportantForAccessibility();
1312        }
1313
1314        @Override
1315        public ColorStateList getBackgroundTintList(View view) {
1316            return view.getBackgroundTintList();
1317        }
1318
1319        @Override
1320        public void setBackgroundTintList(View view, ColorStateList tintList) {
1321            view.setBackgroundTintList(tintList);
1322
1323            if (Build.VERSION.SDK_INT == 21) {
1324                // Work around a bug in L that did not update the state of the background
1325                // after applying the tint
1326                Drawable background = view.getBackground();
1327                boolean hasTint = (view.getBackgroundTintList() != null)
1328                        && (view.getBackgroundTintMode() != null);
1329                if ((background != null) && hasTint) {
1330                    if (background.isStateful()) {
1331                        background.setState(view.getDrawableState());
1332                    }
1333                    view.setBackground(background);
1334                }
1335            }
1336        }
1337
1338        @Override
1339        public void setBackgroundTintMode(View view, PorterDuff.Mode mode) {
1340            view.setBackgroundTintMode(mode);
1341
1342            if (Build.VERSION.SDK_INT == 21) {
1343                // Work around a bug in L that did not update the state of the background
1344                // after applying the tint
1345                Drawable background = view.getBackground();
1346                boolean hasTint = (view.getBackgroundTintList() != null)
1347                        && (view.getBackgroundTintMode() != null);
1348                if ((background != null) && hasTint) {
1349                    if (background.isStateful()) {
1350                        background.setState(view.getDrawableState());
1351                    }
1352                    view.setBackground(background);
1353                }
1354            }
1355        }
1356
1357        @Override
1358        public PorterDuff.Mode getBackgroundTintMode(View view) {
1359            return view.getBackgroundTintMode();
1360        }
1361
1362        @Override
1363        public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
1364            WindowInsets unwrapped = (WindowInsets)  WindowInsetsCompat.unwrap(insets);
1365            WindowInsets result = v.onApplyWindowInsets(unwrapped);
1366            if (result != unwrapped) {
1367                unwrapped = new WindowInsets(result);
1368            }
1369            return WindowInsetsCompat.wrap(unwrapped);
1370        }
1371
1372        @Override
1373        public WindowInsetsCompat dispatchApplyWindowInsets(View v, WindowInsetsCompat insets) {
1374            WindowInsets unwrapped = (WindowInsets) WindowInsetsCompat.unwrap(insets);
1375            WindowInsets result = v.dispatchApplyWindowInsets(unwrapped);
1376            if (result != unwrapped) {
1377                unwrapped = new WindowInsets(result);
1378            }
1379            return WindowInsetsCompat.wrap(unwrapped);
1380        }
1381
1382        @Override
1383        public float getZ(View view) {
1384            return view.getZ();
1385        }
1386
1387        @Override
1388        public void setZ(View view, float z) {
1389            view.setZ(z);
1390        }
1391
1392        @Override
1393        public void offsetLeftAndRight(View view, int offset) {
1394            final Rect parentRect = getEmptyTempRect();
1395            boolean needInvalidateWorkaround = false;
1396
1397            final ViewParent parent = view.getParent();
1398            if (parent instanceof View) {
1399                final View p = (View) parent;
1400                parentRect.set(p.getLeft(), p.getTop(), p.getRight(), p.getBottom());
1401                // If the view currently does not currently intersect the parent (and is therefore
1402                // not displayed) we may need need to invalidate
1403                needInvalidateWorkaround = !parentRect.intersects(view.getLeft(), view.getTop(),
1404                        view.getRight(), view.getBottom());
1405            }
1406
1407            // Now offset, invoking the API 11+ implementation (which contains its own workarounds)
1408            super.offsetLeftAndRight(view, offset);
1409
1410            // The view has now been offset, so let's intersect the Rect and invalidate where
1411            // the View is now displayed
1412            if (needInvalidateWorkaround && parentRect.intersect(view.getLeft(), view.getTop(),
1413                    view.getRight(), view.getBottom())) {
1414                ((View) parent).invalidate(parentRect);
1415            }
1416        }
1417
1418        @Override
1419        public void offsetTopAndBottom(View view, int offset) {
1420            final Rect parentRect = getEmptyTempRect();
1421            boolean needInvalidateWorkaround = false;
1422
1423            final ViewParent parent = view.getParent();
1424            if (parent instanceof View) {
1425                final View p = (View) parent;
1426                parentRect.set(p.getLeft(), p.getTop(), p.getRight(), p.getBottom());
1427                // If the view currently does not currently intersect the parent (and is therefore
1428                // not displayed) we may need need to invalidate
1429                needInvalidateWorkaround = !parentRect.intersects(view.getLeft(), view.getTop(),
1430                        view.getRight(), view.getBottom());
1431            }
1432
1433            // Now offset, invoking the API 11+ implementation (which contains its own workarounds)
1434            super.offsetTopAndBottom(view, offset);
1435
1436            // The view has now been offset, so let's intersect the Rect and invalidate where
1437            // the View is now displayed
1438            if (needInvalidateWorkaround && parentRect.intersect(view.getLeft(), view.getTop(),
1439                    view.getRight(), view.getBottom())) {
1440                ((View) parent).invalidate(parentRect);
1441            }
1442        }
1443
1444        private static Rect getEmptyTempRect() {
1445            if (sThreadLocalRect == null) {
1446                sThreadLocalRect = new ThreadLocal<>();
1447            }
1448            Rect rect = sThreadLocalRect.get();
1449            if (rect == null) {
1450                rect = new Rect();
1451                sThreadLocalRect.set(rect);
1452            }
1453            rect.setEmpty();
1454            return rect;
1455        }
1456    }
1457
1458    @RequiresApi(23)
1459    static class ViewCompatApi23Impl extends ViewCompatApi21Impl {
1460        @Override
1461        public void setScrollIndicators(View view, int indicators) {
1462            view.setScrollIndicators(indicators);
1463        }
1464
1465        @Override
1466        public void setScrollIndicators(View view, int indicators, int mask) {
1467            view.setScrollIndicators(indicators, mask);
1468        }
1469
1470        @Override
1471        public int getScrollIndicators(View view) {
1472            return view.getScrollIndicators();
1473        }
1474
1475
1476        @Override
1477        public void offsetLeftAndRight(View view, int offset) {
1478            view.offsetLeftAndRight(offset);
1479        }
1480
1481        @Override
1482        public void offsetTopAndBottom(View view, int offset) {
1483            view.offsetTopAndBottom(offset);
1484        }
1485    }
1486
1487    @RequiresApi(24)
1488    static class ViewCompatApi24Impl extends ViewCompatApi23Impl {
1489        @Override
1490        public void dispatchStartTemporaryDetach(View view) {
1491            view.dispatchStartTemporaryDetach();
1492        }
1493
1494        @Override
1495        public void dispatchFinishTemporaryDetach(View view) {
1496            view.dispatchFinishTemporaryDetach();
1497        }
1498
1499        @Override
1500        public void setPointerIcon(View view, PointerIconCompat pointerIconCompat) {
1501            view.setPointerIcon((PointerIcon) (pointerIconCompat != null
1502                    ? pointerIconCompat.getPointerIcon() : null));
1503        }
1504
1505        @Override
1506        public boolean startDragAndDrop(View view, ClipData data,
1507                View.DragShadowBuilder shadowBuilder, Object localState, int flags) {
1508            return view.startDragAndDrop(data, shadowBuilder, localState, flags);
1509        }
1510
1511        @Override
1512        public void cancelDragAndDrop(View view) {
1513            view.cancelDragAndDrop();
1514        }
1515
1516        @Override
1517        public void updateDragShadow(View view, View.DragShadowBuilder shadowBuilder) {
1518            view.updateDragShadow(shadowBuilder);
1519        }
1520    }
1521
1522    @RequiresApi(26)
1523    static class ViewCompatApi26Impl extends ViewCompatApi24Impl {
1524        @Override
1525        public void setTooltipText(View view, CharSequence tooltipText) {
1526            view.setTooltipText(tooltipText);
1527        }
1528
1529        @Override
1530        public int getNextClusterForwardId(@NonNull View view) {
1531            return view.getNextClusterForwardId();
1532        }
1533
1534        @Override
1535        public void setNextClusterForwardId(@NonNull View view, int nextClusterForwardId) {
1536            view.setNextClusterForwardId(nextClusterForwardId);
1537        }
1538
1539        @Override
1540        public boolean isKeyboardNavigationCluster(@NonNull View view) {
1541            return view.isKeyboardNavigationCluster();
1542        }
1543
1544        @Override
1545        public void setKeyboardNavigationCluster(@NonNull View view, boolean isCluster) {
1546            view.setKeyboardNavigationCluster(isCluster);
1547        }
1548
1549        @Override
1550        public boolean isFocusedByDefault(@NonNull View view) {
1551            return view.isFocusedByDefault();
1552        }
1553
1554        @Override
1555        public void setFocusedByDefault(@NonNull View view, boolean isFocusedByDefault) {
1556            view.setFocusedByDefault(isFocusedByDefault);
1557        }
1558
1559        @Override
1560        public View keyboardNavigationClusterSearch(@NonNull View view, View currentCluster,
1561                @FocusDirection int direction) {
1562            return view.keyboardNavigationClusterSearch(currentCluster, direction);
1563        }
1564
1565        @Override
1566        public void addKeyboardNavigationClusters(@NonNull View view,
1567                @NonNull Collection<View> views, int direction) {
1568            view.addKeyboardNavigationClusters(views, direction);
1569        }
1570
1571        @Override
1572        public boolean restoreDefaultFocus(@NonNull View view) {
1573            return view.restoreDefaultFocus();
1574        }
1575    }
1576
1577    static final ViewCompatBaseImpl IMPL;
1578    static {
1579        if (BuildCompat.isAtLeastO()) {
1580            IMPL = new ViewCompatApi26Impl();
1581        } else if (Build.VERSION.SDK_INT >= 24) {
1582            IMPL = new ViewCompatApi24Impl();
1583        } else if (Build.VERSION.SDK_INT >= 23) {
1584            IMPL = new ViewCompatApi23Impl();
1585        } else if (Build.VERSION.SDK_INT >= 21) {
1586            IMPL = new ViewCompatApi21Impl();
1587        } else if (Build.VERSION.SDK_INT >= 19) {
1588            IMPL = new ViewCompatApi19Impl();
1589        } else if (Build.VERSION.SDK_INT >= 18) {
1590            IMPL = new ViewCompatApi18Impl();
1591        } else if (Build.VERSION.SDK_INT >= 17) {
1592            IMPL = new ViewCompatApi17Impl();
1593        } else if (Build.VERSION.SDK_INT >= 16) {
1594            IMPL = new ViewCompatApi16Impl();
1595        } else if (Build.VERSION.SDK_INT >= 15) {
1596            IMPL = new ViewCompatApi15Impl();
1597        } else {
1598            IMPL = new ViewCompatBaseImpl();
1599        }
1600    }
1601
1602    /**
1603     * Check if this view can be scrolled horizontally in a certain direction.
1604     *
1605     * @param view The View against which to invoke the method.
1606     * @param direction Negative to check scrolling left, positive to check scrolling right.
1607     * @return true if this view can be scrolled in the specified direction, false otherwise.
1608     *
1609     * @deprecated Use {@link View#canScrollHorizontally(int)} directly.
1610     */
1611    @Deprecated
1612    public static boolean canScrollHorizontally(View view, int direction) {
1613        return view.canScrollHorizontally(direction);
1614    }
1615
1616    /**
1617     * Check if this view can be scrolled vertically in a certain direction.
1618     *
1619     * @param view The View against which to invoke the method.
1620     * @param direction Negative to check scrolling up, positive to check scrolling down.
1621     * @return true if this view can be scrolled in the specified direction, false otherwise.
1622     *
1623     * @deprecated Use {@link View#canScrollVertically(int)} directly.
1624     */
1625    @Deprecated
1626    public static boolean canScrollVertically(View view, int direction) {
1627        return view.canScrollVertically(direction);
1628    }
1629
1630    /**
1631     * Returns the over-scroll mode for this view. The result will be
1632     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
1633     * (allow over-scrolling only if the view content is larger than the container),
1634     * or {@link #OVER_SCROLL_NEVER}.
1635     *
1636     * @param v The View against which to invoke the method.
1637     * @return This view's over-scroll mode.
1638     * @deprecated Call {@link View#getOverScrollMode()} directly. This method will be
1639     * removed in a future release.
1640     */
1641    @Deprecated
1642    @OverScroll
1643    public static int getOverScrollMode(View v) {
1644        //noinspection ResourceType
1645        return v.getOverScrollMode();
1646    }
1647
1648    /**
1649     * Set the over-scroll mode for this view. Valid over-scroll modes are
1650     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
1651     * (allow over-scrolling only if the view content is larger than the container),
1652     * or {@link #OVER_SCROLL_NEVER}.
1653     *
1654     * Setting the over-scroll mode of a view will have an effect only if the
1655     * view is capable of scrolling.
1656     *
1657     * @param v The View against which to invoke the method.
1658     * @param overScrollMode The new over-scroll mode for this view.
1659     * @deprecated Call {@link View#setOverScrollMode(int)} directly. This method will be
1660     * removed in a future release.
1661     */
1662    @Deprecated
1663    public static void setOverScrollMode(View v, @OverScroll int overScrollMode) {
1664        v.setOverScrollMode(overScrollMode);
1665    }
1666
1667    /**
1668     * Called from {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
1669     * giving a chance to this View to populate the accessibility event with its
1670     * text content. While this method is free to modify event
1671     * attributes other than text content, doing so should normally be performed in
1672     * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)}.
1673     * <p>
1674     * Example: Adding formatted date string to an accessibility event in addition
1675     *          to the text added by the super implementation:
1676     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
1677     *     super.onPopulateAccessibilityEvent(event);
1678     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
1679     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
1680     *         mCurrentDate.getTimeInMillis(), flags);
1681     *     event.getText().add(selectedDateUtterance);
1682     * }</pre>
1683     * <p>
1684     * If an {@link AccessibilityDelegateCompat} has been specified via calling
1685     * {@link ViewCompat#setAccessibilityDelegate(View, AccessibilityDelegateCompat)} its
1686     * {@link AccessibilityDelegateCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
1687     * is responsible for handling this call.
1688     * </p>
1689     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
1690     * information to the event, in case the default implementation has basic information to add.
1691     * </p>
1692     *
1693     * @param v The View against which to invoke the method.
1694     * @param event The accessibility event which to populate.
1695     *
1696     * @see View#sendAccessibilityEvent(int)
1697     * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
1698     *
1699     * @deprecated Call {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)} directly.
1700     * This method will be removed in a future release.
1701     */
1702    @Deprecated
1703    public static void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {
1704        v.onPopulateAccessibilityEvent(event);
1705    }
1706
1707    /**
1708     * Initializes an {@link AccessibilityEvent} with information about
1709     * this View which is the event source. In other words, the source of
1710     * an accessibility event is the view whose state change triggered firing
1711     * the event.
1712     * <p>
1713     * Example: Setting the password property of an event in addition
1714     *          to properties set by the super implementation:
1715     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
1716     *     super.onInitializeAccessibilityEvent(event);
1717     *     event.setPassword(true);
1718     * }</pre>
1719     * <p>
1720     * If an {@link AccessibilityDelegateCompat} has been specified via calling
1721     * {@link ViewCompat#setAccessibilityDelegate(View, AccessibilityDelegateCompat)}, its
1722     * {@link AccessibilityDelegateCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
1723     * is responsible for handling this call.
1724     *
1725     * @param v The View against which to invoke the method.
1726     * @param event The event to initialize.
1727     *
1728     * @see View#sendAccessibilityEvent(int)
1729     * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
1730     *
1731     * @deprecated Call {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)} directly.
1732     * This method will be removed in a future release.
1733     */
1734    @Deprecated
1735    public static void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {
1736        v.onInitializeAccessibilityEvent(event);
1737    }
1738
1739    /**
1740     * Initializes an {@link AccessibilityNodeInfoCompat} with information
1741     * about this view. The base implementation sets:
1742     * <ul>
1743     * <li>{@link AccessibilityNodeInfoCompat#setParent(View)},</li>
1744     * <li>{@link AccessibilityNodeInfoCompat#setBoundsInParent(Rect)},</li>
1745     * <li>{@link AccessibilityNodeInfoCompat#setBoundsInScreen(Rect)},</li>
1746     * <li>{@link AccessibilityNodeInfoCompat#setPackageName(CharSequence)},</li>
1747     * <li>{@link AccessibilityNodeInfoCompat#setClassName(CharSequence)},</li>
1748     * <li>{@link AccessibilityNodeInfoCompat#setContentDescription(CharSequence)},</li>
1749     * <li>{@link AccessibilityNodeInfoCompat#setEnabled(boolean)},</li>
1750     * <li>{@link AccessibilityNodeInfoCompat#setClickable(boolean)},</li>
1751     * <li>{@link AccessibilityNodeInfoCompat#setFocusable(boolean)},</li>
1752     * <li>{@link AccessibilityNodeInfoCompat#setFocused(boolean)},</li>
1753     * <li>{@link AccessibilityNodeInfoCompat#setLongClickable(boolean)},</li>
1754     * <li>{@link AccessibilityNodeInfoCompat#setSelected(boolean)},</li>
1755     * </ul>
1756     * <p>
1757     * If an {@link AccessibilityDelegateCompat} has been specified via calling
1758     * {@link ViewCompat#setAccessibilityDelegate(View, AccessibilityDelegateCompat)}, its
1759     * {@link AccessibilityDelegateCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)}
1760     * method is responsible for handling this call.
1761     *
1762     * @param v The View against which to invoke the method.
1763     * @param info The instance to initialize.
1764     */
1765    public static void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
1766        IMPL.onInitializeAccessibilityNodeInfo(v, info);
1767    }
1768
1769    /**
1770     * Sets a delegate for implementing accessibility support via composition
1771     * (as opposed to inheritance). For more details, see
1772     * {@link AccessibilityDelegateCompat}.
1773     * <p>
1774     * <strong>Note:</strong> On platform versions prior to
1775     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
1776     * views in the {@code android.widget.*} package are called <i>before</i>
1777     * host methods. This prevents certain properties such as class name from
1778     * being modified by overriding
1779     * {@link AccessibilityDelegateCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)},
1780     * as any changes will be overwritten by the host class.
1781     * <p>
1782     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
1783     * methods are called <i>after</i> host methods, which all properties to be
1784     * modified without being overwritten by the host class.
1785     *
1786     * @param delegate the object to which accessibility method calls should be
1787     *                 delegated
1788     * @see AccessibilityDelegateCompat
1789     */
1790    public static void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) {
1791        IMPL.setAccessibilityDelegate(v, delegate);
1792    }
1793
1794    /**
1795     * Checks whether provided View has an accessibility delegate attached to it.
1796     *
1797     * @param v The View instance to check
1798     * @return True if the View has an accessibility delegate
1799     */
1800    public static boolean hasAccessibilityDelegate(View v) {
1801        return IMPL.hasAccessibilityDelegate(v);
1802    }
1803
1804    /**
1805     * Indicates whether the view is currently tracking transient state that the
1806     * app should not need to concern itself with saving and restoring, but that
1807     * the framework should take special note to preserve when possible.
1808     *
1809     * @param view View to check for transient state
1810     * @return true if the view has transient state
1811     */
1812    public static boolean hasTransientState(View view) {
1813        return IMPL.hasTransientState(view);
1814    }
1815
1816    /**
1817     * Set whether this view is currently tracking transient state that the
1818     * framework should attempt to preserve when possible.
1819     *
1820     * @param view View tracking transient state
1821     * @param hasTransientState true if this view has transient state
1822     */
1823    public static void setHasTransientState(View view, boolean hasTransientState) {
1824        IMPL.setHasTransientState(view, hasTransientState);
1825    }
1826
1827    /**
1828     * <p>Cause an invalidate to happen on the next animation time step, typically the
1829     * next display frame.</p>
1830     *
1831     * <p>This method can be invoked from outside of the UI thread
1832     * only when this View is attached to a window.</p>
1833     *
1834     * @param view View to invalidate
1835     */
1836    public static void postInvalidateOnAnimation(View view) {
1837        IMPL.postInvalidateOnAnimation(view);
1838    }
1839
1840    /**
1841     * <p>Cause an invalidate of the specified area to happen on the next animation
1842     * time step, typically the next display frame.</p>
1843     *
1844     * <p>This method can be invoked from outside of the UI thread
1845     * only when this View is attached to a window.</p>
1846     *
1847     * @param view View to invalidate
1848     * @param left The left coordinate of the rectangle to invalidate.
1849     * @param top The top coordinate of the rectangle to invalidate.
1850     * @param right The right coordinate of the rectangle to invalidate.
1851     * @param bottom The bottom coordinate of the rectangle to invalidate.
1852     */
1853    public static void postInvalidateOnAnimation(View view, int left, int top,
1854            int right, int bottom) {
1855        IMPL.postInvalidateOnAnimation(view, left, top, right, bottom);
1856    }
1857
1858    /**
1859     * <p>Causes the Runnable to execute on the next animation time step.
1860     * The runnable will be run on the user interface thread.</p>
1861     *
1862     * <p>This method can be invoked from outside of the UI thread
1863     * only when this View is attached to a window.</p>
1864     *
1865     * @param view View to post this Runnable to
1866     * @param action The Runnable that will be executed.
1867     */
1868    public static void postOnAnimation(View view, Runnable action) {
1869        IMPL.postOnAnimation(view, action);
1870    }
1871
1872    /**
1873     * <p>Causes the Runnable to execute on the next animation time step,
1874     * after the specified amount of time elapses.
1875     * The runnable will be run on the user interface thread.</p>
1876     *
1877     * <p>This method can be invoked from outside of the UI thread
1878     * only when this View is attached to a window.</p>
1879     *
1880     * @param view The view to post this Runnable to
1881     * @param action The Runnable that will be executed.
1882     * @param delayMillis The delay (in milliseconds) until the Runnable
1883     *        will be executed.
1884     */
1885    public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
1886        IMPL.postOnAnimationDelayed(view, action, delayMillis);
1887    }
1888
1889    /**
1890     * Gets the mode for determining whether this View is important for accessibility
1891     * which is if it fires accessibility events and if it is reported to
1892     * accessibility services that query the screen.
1893     *
1894     * @param view The view whose property to get.
1895     * @return The mode for determining whether a View is important for accessibility.
1896     *
1897     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
1898     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
1899     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
1900     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
1901     */
1902    @ImportantForAccessibility
1903    public static int getImportantForAccessibility(View view) {
1904        //noinspection ResourceType
1905        return IMPL.getImportantForAccessibility(view);
1906    }
1907
1908    /**
1909     * Sets how to determine whether this view is important for accessibility
1910     * which is if it fires accessibility events and if it is reported to
1911     * accessibility services that query the screen.
1912     * <p>
1913     * <em>Note:</em> If the current platform version does not support the
1914     *  {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} mode, then
1915     *  {@link #IMPORTANT_FOR_ACCESSIBILITY_NO} will be used as it is the
1916     *  closest terms of semantics.
1917     * </p>
1918     *
1919     * @param view The view whose property to set.
1920     * @param mode How to determine whether this view is important for accessibility.
1921     *
1922     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
1923     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
1924     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
1925     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
1926     */
1927    public static void setImportantForAccessibility(View view,
1928            @ImportantForAccessibility int mode) {
1929        IMPL.setImportantForAccessibility(view, mode);
1930    }
1931
1932    /**
1933     * Computes whether this view should be exposed for accessibility. In
1934     * general, views that are interactive or provide information are exposed
1935     * while views that serve only as containers are hidden.
1936     * <p>
1937     * If an ancestor of this view has importance
1938     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
1939     * returns <code>false</code>.
1940     * <p>
1941     * Otherwise, the value is computed according to the view's
1942     * {@link #getImportantForAccessibility(View)} value:
1943     * <ol>
1944     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
1945     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
1946     * </code>
1947     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
1948     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
1949     * view satisfies any of the following:
1950     * <ul>
1951     * <li>Is actionable, e.g. {@link View#isClickable()},
1952     * {@link View#isLongClickable()}, or {@link View#isFocusable()}
1953     * <li>Has an {@link AccessibilityDelegateCompat}
1954     * <li>Has an interaction listener, e.g. {@link View.OnTouchListener},
1955     * {@link View.OnKeyListener}, etc.
1956     * <li>Is an accessibility live region, e.g.
1957     * {@link #getAccessibilityLiveRegion(View)} is not
1958     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
1959     * </ul>
1960     * </ol>
1961     * <p>
1962     * <em>Note:</em> Prior to API 21, this method will always return {@code true}.
1963     *
1964     * @return Whether the view is exposed for accessibility.
1965     * @see #setImportantForAccessibility(View, int)
1966     * @see #getImportantForAccessibility(View)
1967     */
1968    public static boolean isImportantForAccessibility(View view) {
1969        return IMPL.isImportantForAccessibility(view);
1970    }
1971
1972    /**
1973     * Performs the specified accessibility action on the view. For
1974     * possible accessibility actions look at {@link AccessibilityNodeInfoCompat}.
1975     * <p>
1976     * If an {@link AccessibilityDelegateCompat} has been specified via calling
1977     * {@link #setAccessibilityDelegate(View, AccessibilityDelegateCompat)} its
1978     * {@link AccessibilityDelegateCompat#performAccessibilityAction(View, int, Bundle)}
1979     * is responsible for handling this call.
1980     * </p>
1981     *
1982     * @param action The action to perform.
1983     * @param arguments Optional action arguments.
1984     * @return Whether the action was performed.
1985     */
1986    public static boolean performAccessibilityAction(View view, int action, Bundle arguments) {
1987        return IMPL.performAccessibilityAction(view, action, arguments);
1988    }
1989
1990    /**
1991     * Gets the provider for managing a virtual view hierarchy rooted at this View
1992     * and reported to {@link android.accessibilityservice.AccessibilityService}s
1993     * that explore the window content.
1994     * <p>
1995     * If this method returns an instance, this instance is responsible for managing
1996     * {@link AccessibilityNodeInfoCompat}s describing the virtual sub-tree rooted at
1997     * this View including the one representing the View itself. Similarly the returned
1998     * instance is responsible for performing accessibility actions on any virtual
1999     * view or the root view itself.
2000     * </p>
2001     * <p>
2002     * If an {@link AccessibilityDelegateCompat} has been specified via calling
2003     * {@link #setAccessibilityDelegate(View, AccessibilityDelegateCompat)} its
2004     * {@link AccessibilityDelegateCompat#getAccessibilityNodeProvider(View)}
2005     * is responsible for handling this call.
2006     * </p>
2007     *
2008     * @param view The view whose property to get.
2009     * @return The provider.
2010     *
2011     * @see AccessibilityNodeProviderCompat
2012     */
2013    public static AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
2014        return IMPL.getAccessibilityNodeProvider(view);
2015    }
2016
2017    /**
2018     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
2019     * completely transparent and 1 means the view is completely opaque.
2020     *
2021     * <p>By default this is 1.0f.
2022     * @return The opacity of the view.
2023     *
2024     * @deprecated Use {@link View#getAlpha()} directly.
2025     */
2026    @Deprecated
2027    public static float getAlpha(View view) {
2028        return view.getAlpha();
2029    }
2030
2031    /**
2032     * <p>Specifies the type of layer backing this view. The layer can be
2033     * {@link View#LAYER_TYPE_NONE disabled}, {@link View#LAYER_TYPE_SOFTWARE software} or
2034     * {@link View#LAYER_TYPE_HARDWARE hardware}.</p>
2035     *
2036     * <p>A layer is associated with an optional {@link android.graphics.Paint}
2037     * instance that controls how the layer is composed on screen. The following
2038     * properties of the paint are taken into account when composing the layer:</p>
2039     * <ul>
2040     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
2041     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
2042     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
2043     * </ul>
2044     *
2045     * <p>If this view has an alpha value set to < 1.0 by calling
2046     * setAlpha(float), the alpha value of the layer's paint is replaced by
2047     * this view's alpha value. Calling setAlpha(float) is therefore
2048     * equivalent to setting a hardware layer on this view and providing a paint with
2049     * the desired alpha value.<p>
2050     *
2051     * <p>Refer to the documentation of {@link View#LAYER_TYPE_NONE disabled},
2052     * {@link View#LAYER_TYPE_SOFTWARE software} and {@link View#LAYER_TYPE_HARDWARE hardware}
2053     * for more information on when and how to use layers.</p>
2054     *
2055     * @param view View to set the layer type for
2056     * @param layerType The type of layer to use with this view, must be one of
2057     *        {@link View#LAYER_TYPE_NONE}, {@link View#LAYER_TYPE_SOFTWARE} or
2058     *        {@link View#LAYER_TYPE_HARDWARE}
2059     * @param paint The paint used to compose the layer. This argument is optional
2060     *        and can be null. It is ignored when the layer type is
2061     *        {@link View#LAYER_TYPE_NONE}
2062     *
2063     * @deprecated Use {@link View#setLayerType(int, Paint)} directly.
2064     */
2065    @Deprecated
2066    public static void setLayerType(View view, @LayerType int layerType, Paint paint) {
2067        view.setLayerType(layerType, paint);
2068    }
2069
2070    /**
2071     * Indicates what type of layer is currently associated with this view. By default
2072     * a view does not have a layer, and the layer type is {@link View#LAYER_TYPE_NONE}.
2073     * Refer to the documentation of
2074     * {@link #setLayerType(android.view.View, int, android.graphics.Paint)}
2075     * for more information on the different types of layers.
2076     *
2077     * @param view The view to fetch the layer type from
2078     * @return {@link View#LAYER_TYPE_NONE}, {@link View#LAYER_TYPE_SOFTWARE} or
2079     *         {@link View#LAYER_TYPE_HARDWARE}
2080     *
2081     * @see #setLayerType(android.view.View, int, android.graphics.Paint)
2082     * @see View#LAYER_TYPE_NONE
2083     * @see View#LAYER_TYPE_SOFTWARE
2084     * @see View#LAYER_TYPE_HARDWARE
2085     *
2086     * @deprecated Use {@link View#getLayerType()} directly.
2087     */
2088    @Deprecated
2089    @LayerType
2090    public static int getLayerType(View view) {
2091        //noinspection ResourceType
2092        return view.getLayerType();
2093    }
2094
2095    /**
2096     * Gets the id of a view for which a given view serves as a label for
2097     * accessibility purposes.
2098     *
2099     * @param view The view on which to invoke the corresponding method.
2100     * @return The labeled view id.
2101     */
2102    public static int getLabelFor(View view) {
2103        return IMPL.getLabelFor(view);
2104    }
2105
2106    /**
2107     * Sets the id of a view for which a given view serves as a label for
2108     * accessibility purposes.
2109     *
2110     * @param view The view on which to invoke the corresponding method.
2111     * @param labeledId The labeled view id.
2112     */
2113    public static void setLabelFor(View view, @IdRes int labeledId) {
2114        IMPL.setLabelFor(view, labeledId);
2115    }
2116
2117    /**
2118     * Updates the {@link Paint} object used with the current layer (used only if the current
2119     * layer type is not set to {@link View#LAYER_TYPE_NONE}). Changed properties of the Paint
2120     * provided to {@link #setLayerType(android.view.View, int, android.graphics.Paint)}
2121     * will be used the next time the View is redrawn, but
2122     * {@link #setLayerPaint(android.view.View, android.graphics.Paint)}
2123     * must be called to ensure that the view gets redrawn immediately.
2124     *
2125     * <p>A layer is associated with an optional {@link android.graphics.Paint}
2126     * instance that controls how the layer is composed on screen. The following
2127     * properties of the paint are taken into account when composing the layer:</p>
2128     * <ul>
2129     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
2130     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
2131     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
2132     * </ul>
2133     *
2134     * <p>If this view has an alpha value set to < 1.0 by calling
2135     * View#setAlpha(float), the alpha value of the layer's paint is replaced by
2136     * this view's alpha value. Calling View#setAlpha(float) is therefore
2137     * equivalent to setting a hardware layer on this view and providing a paint with
2138     * the desired alpha value.</p>
2139     *
2140     * @param view View to set a layer paint for
2141     * @param paint The paint used to compose the layer. This argument is optional
2142     *        and can be null. It is ignored when the layer type is
2143     *        {@link View#LAYER_TYPE_NONE}
2144     *
2145     * @see #setLayerType(View, int, android.graphics.Paint)
2146     */
2147    public static void setLayerPaint(View view, Paint paint) {
2148        IMPL.setLayerPaint(view, paint);
2149    }
2150
2151    /**
2152     * Returns the resolved layout direction for this view.
2153     *
2154     * @param view View to get layout direction for
2155     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
2156     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
2157     *
2158     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
2159     * is lower than Jellybean MR1 (API 17)
2160     */
2161    @ResolvedLayoutDirectionMode
2162    public static int getLayoutDirection(View view) {
2163        //noinspection ResourceType
2164        return IMPL.getLayoutDirection(view);
2165    }
2166
2167    /**
2168     * Set the layout direction for this view. This will propagate a reset of layout direction
2169     * resolution to the view's children and resolve layout direction for this view.
2170     *
2171     * @param view View to set layout direction for
2172     * @param layoutDirection the layout direction to set. Should be one of:
2173     *
2174     * {@link #LAYOUT_DIRECTION_LTR},
2175     * {@link #LAYOUT_DIRECTION_RTL},
2176     * {@link #LAYOUT_DIRECTION_INHERIT},
2177     * {@link #LAYOUT_DIRECTION_LOCALE}.
2178     *
2179     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
2180     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
2181     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
2182     */
2183    public static void setLayoutDirection(View view, @LayoutDirectionMode int layoutDirection) {
2184        IMPL.setLayoutDirection(view, layoutDirection);
2185    }
2186
2187    /**
2188     * Gets the parent for accessibility purposes. Note that the parent for
2189     * accessibility is not necessary the immediate parent. It is the first
2190     * predecessor that is important for accessibility.
2191     *
2192     * @param view View to retrieve parent for
2193     * @return The parent for use in accessibility inspection
2194     */
2195    public static ViewParent getParentForAccessibility(View view) {
2196        return IMPL.getParentForAccessibility(view);
2197    }
2198
2199    /**
2200     * Indicates whether this View is opaque. An opaque View guarantees that it will
2201     * draw all the pixels overlapping its bounds using a fully opaque color.
2202     *
2203     * @return True if this View is guaranteed to be fully opaque, false otherwise.
2204     * @deprecated Use {@link View#isOpaque()} directly. This method will be
2205     * removed in a future release.
2206     */
2207    @Deprecated
2208    public static boolean isOpaque(View view) {
2209        return view.isOpaque();
2210    }
2211
2212    /**
2213     * Utility to reconcile a desired size and state, with constraints imposed
2214     * by a MeasureSpec.  Will take the desired size, unless a different size
2215     * is imposed by the constraints.  The returned value is a compound integer,
2216     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
2217     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
2218     * size is smaller than the size the view wants to be.
2219     *
2220     * @param size How big the view wants to be
2221     * @param measureSpec Constraints imposed by the parent
2222     * @return Size information bit mask as defined by
2223     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
2224     *
2225     * @deprecated Use {@link View#resolveSizeAndState(int, int, int)} directly.
2226     */
2227    @Deprecated
2228    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
2229        return View.resolveSizeAndState(size, measureSpec, childMeasuredState);
2230    }
2231
2232    /**
2233     * Return the full width measurement information for this view as computed
2234     * by the most recent call to {@link android.view.View#measure(int, int)}.
2235     * This result is a bit mask as defined by {@link #MEASURED_SIZE_MASK} and
2236     * {@link #MEASURED_STATE_TOO_SMALL}.
2237     * This should be used during measurement and layout calculations only. Use
2238     * {@link android.view.View#getWidth()} to see how wide a view is after layout.
2239     *
2240     * @return The measured width of this view as a bit mask.
2241     *
2242     * @deprecated Use {@link View#getMeasuredWidth()} directly.
2243     */
2244    @Deprecated
2245    public static int getMeasuredWidthAndState(View view) {
2246        return view.getMeasuredWidthAndState();
2247    }
2248
2249    /**
2250     * Return the full height measurement information for this view as computed
2251     * by the most recent call to {@link android.view.View#measure(int, int)}.
2252     * This result is a bit mask as defined by {@link #MEASURED_SIZE_MASK} and
2253     * {@link #MEASURED_STATE_TOO_SMALL}.
2254     * This should be used during measurement and layout calculations only. Use
2255     * {@link android.view.View#getHeight()} to see how wide a view is after layout.
2256     *
2257     * @return The measured width of this view as a bit mask.
2258     *
2259     * @deprecated Use {@link View#getMeasuredHeightAndState()} directly.
2260     */
2261    @Deprecated
2262    public static int getMeasuredHeightAndState(View view) {
2263        return view.getMeasuredHeightAndState();
2264    }
2265
2266    /**
2267     * Return only the state bits of {@link #getMeasuredWidthAndState}
2268     * and {@link #getMeasuredHeightAndState}, combined into one integer.
2269     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
2270     * and the height component is at the shifted bits
2271     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
2272     *
2273     * @deprecated Use {@link View#getMeasuredState()} directly.
2274     */
2275    @Deprecated
2276    public static int getMeasuredState(View view) {
2277        return view.getMeasuredState();
2278    }
2279
2280    /**
2281     * Merge two states as returned by {@link #getMeasuredState(View)}.
2282     * @param curState The current state as returned from a view or the result
2283     * of combining multiple views.
2284     * @param newState The new view state to combine.
2285     * @return Returns a new integer reflecting the combination of the two
2286     * states.
2287     *
2288     * @deprecated Use {@link View#combineMeasuredStates(int, int)} directly.
2289     */
2290    @Deprecated
2291    public static int combineMeasuredStates(int curState, int newState) {
2292        return View.combineMeasuredStates(curState, newState);
2293    }
2294
2295    /**
2296     * Gets the live region mode for the specified View.
2297     *
2298     * @param view The view from which to obtain the live region mode
2299     * @return The live region mode for the view.
2300     *
2301     * @see ViewCompat#setAccessibilityLiveRegion(View, int)
2302     */
2303    @AccessibilityLiveRegion
2304    public static int getAccessibilityLiveRegion(View view) {
2305        //noinspection ResourceType
2306        return IMPL.getAccessibilityLiveRegion(view);
2307    }
2308
2309    /**
2310     * Sets the live region mode for the specified view. This indicates to
2311     * accessibility services whether they should automatically notify the user
2312     * about changes to the view's content description or text, or to the
2313     * content descriptions or text of the view's children (where applicable).
2314     * <p>
2315     * For example, in a login screen with a TextView that displays an "incorrect
2316     * password" notification, that view should be marked as a live region with
2317     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
2318     * <p>
2319     * To disable change notifications for this view, use
2320     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
2321     * mode for most views.
2322     * <p>
2323     * To indicate that the user should be notified of changes, use
2324     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
2325     * <p>
2326     * If the view's changes should interrupt ongoing speech and notify the user
2327     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
2328     *
2329     * @param view The view on which to set the live region mode
2330     * @param mode The live region mode for this view, one of:
2331     *        <ul>
2332     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
2333     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
2334     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
2335     *        </ul>
2336     */
2337    public static void setAccessibilityLiveRegion(View view, @AccessibilityLiveRegion int mode) {
2338        IMPL.setAccessibilityLiveRegion(view, mode);
2339    }
2340
2341    /**
2342     * Returns the start padding of the specified view depending on its resolved layout direction.
2343     * If there are inset and enabled scrollbars, this value may include the space
2344     * required to display the scrollbars as well.
2345     *
2346     * @param view The view to get padding for
2347     * @return the start padding in pixels
2348     */
2349    public static int getPaddingStart(View view) {
2350        return IMPL.getPaddingStart(view);
2351    }
2352
2353    /**
2354     * Returns the end padding of the specified view depending on its resolved layout direction.
2355     * If there are inset and enabled scrollbars, this value may include the space
2356     * required to display the scrollbars as well.
2357     *
2358     * @param view The view to get padding for
2359     * @return the end padding in pixels
2360     */
2361    public static int getPaddingEnd(View view) {
2362        return IMPL.getPaddingEnd(view);
2363    }
2364
2365    /**
2366     * Sets the relative padding. The view may add on the space required to display
2367     * the scrollbars, depending on the style and visibility of the scrollbars.
2368     * So the values returned from {@link #getPaddingStart}, {@link View#getPaddingTop},
2369     * {@link #getPaddingEnd} and {@link View#getPaddingBottom} may be different
2370     * from the values set in this call.
2371     *
2372     * @param view The view on which to set relative padding
2373     * @param start the start padding in pixels
2374     * @param top the top padding in pixels
2375     * @param end the end padding in pixels
2376     * @param bottom the bottom padding in pixels
2377     */
2378    public static void setPaddingRelative(View view, int start, int top, int end, int bottom) {
2379        IMPL.setPaddingRelative(view, start, top, end, bottom);
2380    }
2381
2382    /**
2383     * Notify a view that it is being temporarily detached.
2384     */
2385    public static void dispatchStartTemporaryDetach(View view) {
2386        IMPL.dispatchStartTemporaryDetach(view);
2387    }
2388
2389    /**
2390     * Notify a view that its temporary detach has ended; the view is now reattached.
2391     */
2392    public static void dispatchFinishTemporaryDetach(View view) {
2393        IMPL.dispatchFinishTemporaryDetach(view);
2394    }
2395
2396    /**
2397     * The horizontal location of this view relative to its {@link View#getLeft() left} position.
2398     * This position is post-layout, in addition to wherever the object's
2399     * layout placed it.
2400     *
2401     * @return The horizontal position of this view relative to its left position, in pixels.
2402     *
2403     * @deprecated Use {@link View#getTranslationX()} directly.
2404     */
2405    @Deprecated
2406    public static float getTranslationX(View view) {
2407        return view.getTranslationX();
2408    }
2409
2410    /**
2411     * The vertical location of this view relative to its {@link View#getTop() top} position.
2412     * This position is post-layout, in addition to wherever the object's
2413     * layout placed it.
2414     *
2415     * @return The vertical position of this view relative to its top position, in pixels.
2416     *
2417     * @deprecated Use {@link View#getTranslationY()} directly.
2418     */
2419    @Deprecated
2420    public static float getTranslationY(View view) {
2421        return view.getTranslationY();
2422    }
2423
2424    /**
2425     * The transform matrix of this view, which is calculated based on the current
2426     * rotation, scale, and pivot properties.
2427     * <p>
2428     *
2429     * @param view The view whose Matrix will be returned
2430     * @return The current transform matrix for the view
2431     *
2432     * @see #getRotation(View)
2433     * @see #getScaleX(View)
2434     * @see #getScaleY(View)
2435     * @see #getPivotX(View)
2436     * @see #getPivotY(View)
2437     *
2438     * @deprecated Use {@link View#getMatrix()} directly.
2439     */
2440    @Deprecated
2441    @Nullable
2442    public static Matrix getMatrix(View view) {
2443        return view.getMatrix();
2444    }
2445
2446    /**
2447     * Returns the minimum width of the view.
2448     *
2449     * <p>Prior to API 16, this method may return 0 on some platforms.</p>
2450     *
2451     * @return the minimum width the view will try to be.
2452     */
2453    public static int getMinimumWidth(View view) {
2454        return IMPL.getMinimumWidth(view);
2455    }
2456
2457    /**
2458     * Returns the minimum height of the view.
2459     *
2460     * <p>Prior to API 16, this method may return 0 on some platforms.</p>
2461     *
2462     * @return the minimum height the view will try to be.
2463     */
2464    public static int getMinimumHeight(View view) {
2465        return IMPL.getMinimumHeight(view);
2466    }
2467
2468    /**
2469     * This method returns a ViewPropertyAnimator object, which can be used to animate
2470     * specific properties on this View.
2471     *
2472     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
2473     */
2474    public static ViewPropertyAnimatorCompat animate(View view) {
2475        return IMPL.animate(view);
2476    }
2477
2478    /**
2479     * Sets the horizontal location of this view relative to its left position.
2480     * This effectively positions the object post-layout, in addition to wherever the object's
2481     * layout placed it.
2482     *
2483     * @param value The horizontal position of this view relative to its left position,
2484     * in pixels.
2485     *
2486     * @deprecated Use {@link View#setTranslationX(float)} directly.
2487     */
2488    @Deprecated
2489    public static void setTranslationX(View view, float value) {
2490        view.setTranslationX(value);
2491    }
2492
2493    /**
2494     * Sets the vertical location of this view relative to its top position.
2495     * This effectively positions the object post-layout, in addition to wherever the object's
2496     * layout placed it.
2497     *
2498     * @param value The vertical position of this view relative to its top position,
2499     * in pixels.
2500     *
2501     * @attr name android:translationY
2502     *
2503     * @deprecated Use {@link View#setTranslationY(float)} directly.
2504     */
2505    @Deprecated
2506    public static void setTranslationY(View view, float value) {
2507        view.setTranslationY(value);
2508    }
2509
2510    /**
2511     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
2512     * completely transparent and 1 means the view is completely opaque.</p>
2513     *
2514     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
2515     * performance implications, especially for large views. It is best to use the alpha property
2516     * sparingly and transiently, as in the case of fading animations.</p>
2517     *
2518     * @param value The opacity of the view.
2519     *
2520     * @deprecated Use {@link View#setAlpha(float)} directly.
2521     */
2522    @Deprecated
2523    public static void setAlpha(View view, @FloatRange(from=0.0, to=1.0) float value) {
2524        view.setAlpha(value);
2525    }
2526
2527    /**
2528     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
2529     * {@link #setTranslationX(View, float) translationX} property to be the difference between
2530     * the x value passed in and the current left property of the view as determined
2531     * by the layout bounds.
2532     *
2533     * @param value The visual x position of this view, in pixels.
2534     *
2535     * @deprecated Use {@link View#setX(float)} directly.
2536     */
2537    @Deprecated
2538    public static void setX(View view, float value) {
2539        view.setX(value);
2540    }
2541
2542    /**
2543     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
2544     * {@link #setTranslationY(View, float) translationY} property to be the difference between
2545     * the y value passed in and the current top property of the view as determined by the
2546     * layout bounds.
2547     *
2548     * @param value The visual y position of this view, in pixels.
2549     *
2550     * @deprecated Use {@link View#setY(float)} directly.
2551     */
2552    @Deprecated
2553    public static void setY(View view, float value) {
2554        view.setY(value);
2555    }
2556
2557    /**
2558     * Sets the degrees that the view is rotated around the pivot point. Increasing values
2559     * result in clockwise rotation.
2560     *
2561     * @param value The degrees of rotation.
2562     *
2563     * @deprecated Use {@link View#setRotation(float)} directly.
2564     */
2565    @Deprecated
2566    public static void setRotation(View view, float value) {
2567        view.setRotation(value);
2568    }
2569
2570    /**
2571     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
2572     * Increasing values result in clockwise rotation from the viewpoint of looking down the
2573     * x axis.
2574     *
2575     * @param value The degrees of X rotation.
2576     *
2577     * @deprecated Use {@link View#setRotationX(float)} directly.
2578     */
2579    @Deprecated
2580    public static void setRotationX(View view, float value) {
2581        view.setRotationX(value);
2582    }
2583
2584    /**
2585     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
2586     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
2587     * down the y axis.
2588     *
2589     * @param value The degrees of Y rotation.
2590     *
2591     * @deprecated Use {@link View#setRotationY(float)} directly.
2592     */
2593    @Deprecated
2594    public static void setRotationY(View view, float value) {
2595        view.setRotationY(value);
2596    }
2597
2598    /**
2599     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
2600     * the view's unscaled width. A value of 1 means that no scaling is applied.
2601     *
2602     * @param value The scaling factor.
2603     *
2604     * @deprecated Use {@link View#setScaleX(float)} directly.
2605     */
2606    @Deprecated
2607    public static void setScaleX(View view, float value) {
2608        view.setScaleX(value);
2609    }
2610
2611    /**
2612     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
2613     * the view's unscaled width. A value of 1 means that no scaling is applied.
2614     *
2615     * @param value The scaling factor.
2616     *
2617     * @deprecated Use {@link View#setScaleY(float)} directly.
2618     */
2619    @Deprecated
2620    public static void setScaleY(View view, float value) {
2621        view.setScaleY(value);
2622    }
2623
2624    /**
2625     * The x location of the point around which the view is
2626     * {@link #setRotation(View, float) rotated} and {@link #setScaleX(View, float) scaled}.
2627     *
2628     * @deprecated Use {@link View#getPivotX()} directly.
2629     */
2630    @Deprecated
2631    public static float getPivotX(View view) {
2632        return view.getPivotX();
2633    }
2634
2635    /**
2636     * Sets the x location of the point around which the view is
2637     * {@link #setRotation(View, float) rotated} and {@link #setScaleX(View, float) scaled}.
2638     * By default, the pivot point is centered on the object.
2639     * Setting this property disables this behavior and causes the view to use only the
2640     * explicitly set pivotX and pivotY values.
2641     *
2642     * @param value The x location of the pivot point.
2643     *
2644     * @deprecated Use {@link View#setPivotX(float)} directly.
2645     */
2646    @Deprecated
2647    public static void setPivotX(View view, float value) {
2648        view.setPivotX(value);
2649    }
2650
2651    /**
2652     * The y location of the point around which the view is {@link #setRotation(View,
2653     * float) rotated} and {@link #setScaleY(View, float) scaled}.
2654     *
2655     * @return The y location of the pivot point.
2656     *
2657     * @deprecated Use {@link View#getPivotY()} directly.
2658     */
2659    @Deprecated
2660    public static float getPivotY(View view) {
2661        return view.getPivotY();
2662    }
2663
2664    /**
2665     * Sets the y location of the point around which the view is
2666     * {@link #setRotation(View, float) rotated} and {@link #setScaleY(View, float) scaled}.
2667     * By default, the pivot point is centered on the object.
2668     * Setting this property disables this behavior and causes the view to use only the
2669     * explicitly set pivotX and pivotY values.
2670     *
2671     * @param value The y location of the pivot point.
2672     *
2673     * @deprecated Use {@link View#setPivotX(float)} directly.
2674     */
2675    @Deprecated
2676    public static void setPivotY(View view, float value) {
2677        view.setPivotY(value);
2678    }
2679
2680    /**
2681     * @deprecated Use {@link View#getRotation()} directly.
2682     */
2683    @Deprecated
2684    public static float getRotation(View view) {
2685        return view.getRotation();
2686    }
2687
2688    /**
2689     * @deprecated Use {@link View#getRotationX()} directly.
2690     */
2691    @Deprecated
2692    public static float getRotationX(View view) {
2693        return view.getRotationX();
2694    }
2695
2696    /**
2697     * @deprecated Use {@link View#getRotationY()} directly.
2698     */
2699    @Deprecated
2700    public static float getRotationY(View view) {
2701        return view.getRotationY();
2702    }
2703
2704    /**
2705     * @deprecated Use {@link View#getScaleX()} directly.
2706     */
2707    @Deprecated
2708    public static float getScaleX(View view) {
2709        return view.getScaleX();
2710    }
2711
2712    /**
2713     * @deprecated Use {@link View#getScaleY()} directly.
2714     */
2715    @Deprecated
2716    public static float getScaleY(View view) {
2717        return view.getScaleY();
2718    }
2719
2720    /**
2721     * @deprecated Use {@link View#getX()} directly.
2722     */
2723    @Deprecated
2724    public static float getX(View view) {
2725        return view.getX();
2726    }
2727
2728    /**
2729     * @deprecated Use {@link View#getY()} directly.
2730     */
2731    @Deprecated
2732    public static float getY(View view) {
2733        return view.getY();
2734    }
2735
2736    /**
2737     * Sets the base elevation of this view, in pixels.
2738     */
2739    public static void setElevation(View view, float elevation) {
2740        IMPL.setElevation(view, elevation);
2741    }
2742
2743    /**
2744     * The base elevation of this view relative to its parent, in pixels.
2745     *
2746     * @return The base depth position of the view, in pixels.
2747     */
2748    public static float getElevation(View view) {
2749        return IMPL.getElevation(view);
2750    }
2751
2752    /**
2753     * Sets the depth location of this view relative to its {@link #getElevation(View) elevation}.
2754     */
2755    public static void setTranslationZ(View view, float translationZ) {
2756        IMPL.setTranslationZ(view, translationZ);
2757    }
2758
2759    /**
2760     * The depth location of this view relative to its {@link #getElevation(View) elevation}.
2761     *
2762     * @return The depth of this view relative to its elevation.
2763     */
2764    public static float getTranslationZ(View view) {
2765        return IMPL.getTranslationZ(view);
2766    }
2767
2768    /**
2769     * Sets the name of the View to be used to identify Views in Transitions.
2770     * Names should be unique in the View hierarchy.
2771     *
2772     * @param view The View against which to invoke the method.
2773     * @param transitionName The name of the View to uniquely identify it for Transitions.
2774     */
2775    public static void setTransitionName(View view, String transitionName) {
2776        IMPL.setTransitionName(view, transitionName);
2777    }
2778
2779    /**
2780     * Returns the name of the View to be used to identify Views in Transitions.
2781     * Names should be unique in the View hierarchy.
2782     *
2783     * <p>This returns null if the View has not been given a name.</p>
2784     *
2785     * @param view The View against which to invoke the method.
2786     * @return The name used of the View to be used to identify Views in Transitions or null
2787     * if no name has been given.
2788     */
2789    public static String getTransitionName(View view) {
2790        return IMPL.getTransitionName(view);
2791    }
2792
2793    /**
2794     * Returns the current system UI visibility that is currently set for the entire window.
2795     */
2796    public static int getWindowSystemUiVisibility(View view) {
2797        return IMPL.getWindowSystemUiVisibility(view);
2798    }
2799
2800    /**
2801     * Ask that a new dispatch of {@code View.onApplyWindowInsets(WindowInsets)} be performed. This
2802     * falls back to {@code View.requestFitSystemWindows()} where available.
2803     */
2804    public static void requestApplyInsets(View view) {
2805        IMPL.requestApplyInsets(view);
2806    }
2807
2808    /**
2809     * Tells the ViewGroup whether to draw its children in the order defined by the method
2810     * {@code ViewGroup.getChildDrawingOrder(int, int)}.
2811     *
2812     * @param enabled true if the order of the children when drawing is determined by
2813     *        {@link ViewGroup#getChildDrawingOrder(int, int)}, false otherwise
2814     *
2815     * <p>Prior to API 7 this will have no effect.</p>
2816     */
2817    public static void setChildrenDrawingOrderEnabled(ViewGroup viewGroup, boolean enabled) {
2818       IMPL.setChildrenDrawingOrderEnabled(viewGroup, enabled);
2819    }
2820
2821    /**
2822     * Returns true if this view should adapt to fit system window insets. This method will always
2823     * return false before API 16 (Jellybean).
2824     */
2825    public static boolean getFitsSystemWindows(View v) {
2826        return IMPL.getFitsSystemWindows(v);
2827    }
2828
2829    /**
2830     * Sets whether or not this view should account for system screen decorations
2831     * such as the status bar and inset its content; that is, controlling whether
2832     * the default implementation of {@link View#fitSystemWindows(Rect)} will be
2833     * executed. See that method for more details.
2834     *
2835     * @deprecated Use {@link View#setFitsSystemWindows(boolean)} directly.
2836     */
2837    @Deprecated
2838    public static void setFitsSystemWindows(View view, boolean fitSystemWindows) {
2839        view.setFitsSystemWindows(fitSystemWindows);
2840    }
2841
2842    /**
2843     * On API 11 devices and above, call <code>Drawable.jumpToCurrentState()</code>
2844     * on all Drawable objects associated with this view.
2845     * <p>
2846     * On API 21 and above, also calls <code>StateListAnimator#jumpToCurrentState()</code>
2847     * if there is a StateListAnimator attached to this view.
2848     *
2849     * @deprecated Use {@link View#jumpDrawablesToCurrentState()} directly.
2850     */
2851    @Deprecated
2852    public static void jumpDrawablesToCurrentState(View v) {
2853        v.jumpDrawablesToCurrentState();
2854    }
2855
2856    /**
2857     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
2858     * window insets to this view. This will only take effect on devices with API 21 or above.
2859     */
2860    public static void setOnApplyWindowInsetsListener(View v,
2861            OnApplyWindowInsetsListener listener) {
2862        IMPL.setOnApplyWindowInsetsListener(v, listener);
2863    }
2864
2865    /**
2866     * Called when the view should apply {@link WindowInsetsCompat} according to its internal policy.
2867     *
2868     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
2869     * it will be called during dispatch instead of this method. The listener may optionally
2870     * call this method from its own implementation if it wishes to apply the view's default
2871     * insets policy in addition to its own.</p>
2872     *
2873     * @param view The View against which to invoke the method.
2874     * @param insets Insets to apply
2875     * @return The supplied insets with any applied insets consumed
2876     */
2877    public static WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
2878        return IMPL.onApplyWindowInsets(view, insets);
2879    }
2880
2881    /**
2882     * Request to apply the given window insets to this view or another view in its subtree.
2883     *
2884     * <p>This method should be called by clients wishing to apply insets corresponding to areas
2885     * obscured by window decorations or overlays. This can include the status and navigation bars,
2886     * action bars, input methods and more. New inset categories may be added in the future.
2887     * The method returns the insets provided minus any that were applied by this view or its
2888     * children.</p>
2889     *
2890     * @param insets Insets to apply
2891     * @return The provided insets minus the insets that were consumed
2892     */
2893    public static WindowInsetsCompat dispatchApplyWindowInsets(View view,
2894            WindowInsetsCompat insets) {
2895        return IMPL.dispatchApplyWindowInsets(view, insets);
2896    }
2897
2898    /**
2899     * Controls whether the entire hierarchy under this view will save its
2900     * state when a state saving traversal occurs from its parent.
2901     *
2902     * @param enabled Set to false to <em>disable</em> state saving, or true
2903     * (the default) to allow it.
2904     *
2905     * @deprecated Use {@link View#setSaveFromParentEnabled(boolean)} directly.
2906     */
2907    @Deprecated
2908    public static void setSaveFromParentEnabled(View v, boolean enabled) {
2909        v.setSaveFromParentEnabled(enabled);
2910    }
2911
2912    /**
2913     * Changes the activated state of this view. A view can be activated or not.
2914     * Note that activation is not the same as selection.  Selection is
2915     * a transient property, representing the view (hierarchy) the user is
2916     * currently interacting with.  Activation is a longer-term state that the
2917     * user can move views in and out of.
2918     *
2919     * @param activated true if the view must be activated, false otherwise
2920     *
2921     * @deprecated Use {@link View#setActivated(boolean)} directly.
2922     */
2923    @Deprecated
2924    public static void setActivated(View view, boolean activated) {
2925        view.setActivated(activated);
2926    }
2927
2928    /**
2929     * Returns whether this View has content which overlaps.
2930     *
2931     * <p>This function, intended to be overridden by specific View types, is an optimization when
2932     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
2933     * an offscreen buffer and then composited into place, which can be expensive. If the view has
2934     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
2935     * directly. An example of overlapping rendering is a TextView with a background image, such as
2936     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
2937     * ImageView with only the foreground image. The default implementation returns true; subclasses
2938     * should override if they have cases which can be optimized.</p>
2939     *
2940     * @return true if the content in this view might overlap, false otherwise.
2941     */
2942    public static boolean hasOverlappingRendering(View view) {
2943        return IMPL.hasOverlappingRendering(view);
2944    }
2945
2946    /**
2947     * Return if the padding as been set through relative values
2948     * {@code View.setPaddingRelative(int, int, int, int)} or thru
2949     *
2950     * @return true if the padding is relative or false if it is not.
2951     */
2952    public static boolean isPaddingRelative(View view) {
2953        return IMPL.isPaddingRelative(view);
2954    }
2955
2956    /**
2957     * Set the background of the {@code view} to a given Drawable, or remove the background. If the
2958     * background has padding, {@code view}'s padding is set to the background's padding. However,
2959     * when a background is removed, this View's padding isn't touched. If setting the padding is
2960     * desired, please use{@code setPadding(int, int, int, int)}.
2961     */
2962    public static void setBackground(View view, Drawable background) {
2963        IMPL.setBackground(view, background);
2964    }
2965
2966    /**
2967     * Return the tint applied to the background drawable, if specified.
2968     * <p>
2969     * Only returns meaningful info when running on API v21 or newer, or if {@code view}
2970     * implements the {@code TintableBackgroundView} interface.
2971     */
2972    public static ColorStateList getBackgroundTintList(View view) {
2973        return IMPL.getBackgroundTintList(view);
2974    }
2975
2976    /**
2977     * Applies a tint to the background drawable.
2978     * <p>
2979     * This will always take effect when running on API v21 or newer. When running on platforms
2980     * previous to API v21, it will only take effect if {@code view} implements the
2981     * {@code TintableBackgroundView} interface.
2982     */
2983    public static void setBackgroundTintList(View view, ColorStateList tintList) {
2984        IMPL.setBackgroundTintList(view, tintList);
2985    }
2986
2987    /**
2988     * Return the blending mode used to apply the tint to the background
2989     * drawable, if specified.
2990     * <p>
2991     * Only returns meaningful info when running on API v21 or newer, or if {@code view}
2992     * implements the {@code TintableBackgroundView} interface.
2993     */
2994    public static PorterDuff.Mode getBackgroundTintMode(View view) {
2995        return IMPL.getBackgroundTintMode(view);
2996    }
2997
2998    /**
2999     * Specifies the blending mode used to apply the tint specified by
3000     * {@link #setBackgroundTintList(android.view.View, android.content.res.ColorStateList)} to
3001     * the background drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
3002     * <p>
3003     * This will always take effect when running on API v21 or newer. When running on platforms
3004     * previous to API v21, it will only take effect if {@code view} implement the
3005     * {@code TintableBackgroundView} interface.
3006     */
3007    public static void setBackgroundTintMode(View view, PorterDuff.Mode mode) {
3008        IMPL.setBackgroundTintMode(view, mode);
3009    }
3010
3011    // TODO: getters for various view properties (rotation, etc)
3012
3013    /**
3014     * Enable or disable nested scrolling for this view.
3015     *
3016     * <p>If this property is set to true the view will be permitted to initiate nested
3017     * scrolling operations with a compatible parent view in the current hierarchy. If this
3018     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
3019     * while a nested scroll is in progress has the effect of
3020     * {@link #stopNestedScroll(View) stopping} the nested scroll.</p>
3021     *
3022     * @param enabled true to enable nested scrolling, false to disable
3023     *
3024     * @see #isNestedScrollingEnabled(View)
3025     */
3026    public static void setNestedScrollingEnabled(@NonNull View view, boolean enabled) {
3027        IMPL.setNestedScrollingEnabled(view, enabled);
3028    }
3029
3030    /**
3031     * Returns true if nested scrolling is enabled for this view.
3032     *
3033     * <p>If nested scrolling is enabled and this View class implementation supports it,
3034     * this view will act as a nested scrolling child view when applicable, forwarding data
3035     * about the scroll operation in progress to a compatible and cooperating nested scrolling
3036     * parent.</p>
3037     *
3038     * @return true if nested scrolling is enabled
3039     *
3040     * @see #setNestedScrollingEnabled(View, boolean)
3041     */
3042    public static boolean isNestedScrollingEnabled(@NonNull View view) {
3043        return IMPL.isNestedScrollingEnabled(view);
3044    }
3045
3046    /**
3047     * Begin a nestable scroll operation along the given axes.
3048     *
3049     * <p>This version of the method just calls {@link #startNestedScroll(View, int, int)} using
3050     * the touch input type.</p>
3051     *
3052     * @param axes Flags consisting of a combination of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}
3053     *             and/or {@link ViewCompat#SCROLL_AXIS_VERTICAL}.
3054     * @return true if a cooperative parent was found and nested scrolling has been enabled for
3055     *         the current gesture.
3056     */
3057    public static boolean startNestedScroll(@NonNull View view, @ScrollAxis int axes) {
3058        return IMPL.startNestedScroll(view, axes);
3059    }
3060
3061    /**
3062     * Stop a nested scroll in progress.
3063     *
3064     * <p>This version of the method just calls {@link #stopNestedScroll(View, int)} using the
3065     * touch input type.</p>
3066     *
3067     * @see #startNestedScroll(View, int)
3068     */
3069    public static void stopNestedScroll(@NonNull View view) {
3070        IMPL.stopNestedScroll(view);
3071    }
3072
3073    /**
3074     * Returns true if this view has a nested scrolling parent.
3075     *
3076     * <p>This version of the method just calls {@link #hasNestedScrollingParent(View, int)}
3077     * using the touch input type.</p>
3078     *
3079     * @return whether this view has a nested scrolling parent
3080     */
3081    public static boolean hasNestedScrollingParent(@NonNull View view) {
3082        return IMPL.hasNestedScrollingParent(view);
3083    }
3084
3085    /**
3086     * Dispatch one step of a nested scroll in progress.
3087     *
3088     * <p>This version of the method just calls
3089     * {@link #dispatchNestedScroll(View, int, int, int, int, int[], int)} using the touch input
3090     * type.</p>
3091     *
3092     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
3093     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
3094     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
3095     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
3096     * @param offsetInWindow Optional. If not null, on return this will contain the offset
3097     *                       in local view coordinates of this view from before this operation
3098     *                       to after it completes. View implementations may use this to adjust
3099     *                       expected input coordinate tracking.
3100     * @return true if the event was dispatched, false if it could not be dispatched.
3101     */
3102    public static boolean dispatchNestedScroll(@NonNull View view, int dxConsumed, int dyConsumed,
3103            int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow) {
3104        return IMPL.dispatchNestedScroll(view, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,
3105                offsetInWindow);
3106    }
3107
3108    /**
3109     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
3110     *
3111     * <p>This version of the method just calls
3112     * {@link #dispatchNestedPreScroll(View, int, int, int[], int[], int)} using the touch input
3113     * type.</p>
3114     *
3115     * @param dx Horizontal scroll distance in pixels
3116     * @param dy Vertical scroll distance in pixels
3117     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
3118     *                 and consumed[1] the consumed dy.
3119     * @param offsetInWindow Optional. If not null, on return this will contain the offset
3120     *                       in local view coordinates of this view from before this operation
3121     *                       to after it completes. View implementations may use this to adjust
3122     *                       expected input coordinate tracking.
3123     * @return true if the parent consumed some or all of the scroll delta
3124     */
3125    public static boolean dispatchNestedPreScroll(@NonNull View view, int dx, int dy,
3126            @Nullable int[] consumed, @Nullable int[] offsetInWindow) {
3127        return IMPL.dispatchNestedPreScroll(view, dx, dy, consumed, offsetInWindow);
3128    }
3129
3130    /**
3131     * Begin a nestable scroll operation along the given axes.
3132     *
3133     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
3134     *
3135     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
3136     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
3137     * In the case of touch scrolling the nested scroll will be terminated automatically in
3138     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
3139     * In the event of programmatic scrolling the caller must explicitly call
3140     * {@link #stopNestedScroll(View)} to indicate the end of the nested scroll.</p>
3141     *
3142     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
3143     * If it returns false the caller may ignore the rest of this contract until the next scroll.
3144     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
3145     *
3146     * <p>At each incremental step of the scroll the caller should invoke
3147     * {@link #dispatchNestedPreScroll(View, int, int, int[], int[]) dispatchNestedPreScroll}
3148     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
3149     * parent at least partially consumed the scroll and the caller should adjust the amount it
3150     * scrolls by.</p>
3151     *
3152     * <p>After applying the remainder of the scroll delta the caller should invoke
3153     * {@link #dispatchNestedScroll(View, int, int, int, int, int[]) dispatchNestedScroll}, passing
3154     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
3155     * these values differently. See
3156     * {@link NestedScrollingParent#onNestedScroll(View, int, int, int, int)}.
3157     * </p>
3158     *
3159     * @param axes Flags consisting of a combination of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}
3160     *             and/or {@link ViewCompat#SCROLL_AXIS_VERTICAL}.
3161     * @param type the type of input which cause this scroll event
3162     * @return true if a cooperative parent was found and nested scrolling has been enabled for
3163     *         the current gesture.
3164     *
3165     * @see #stopNestedScroll(View)
3166     * @see #dispatchNestedPreScroll(View, int, int, int[], int[])
3167     * @see #dispatchNestedScroll(View, int, int, int, int, int[])
3168     */
3169    public static boolean startNestedScroll(@NonNull View view, @ScrollAxis int axes,
3170            @NestedScrollType int type) {
3171        if (view instanceof NestedScrollingChild2) {
3172            return ((NestedScrollingChild2) view).startNestedScroll(axes, type);
3173        } else if (type == ViewCompat.TYPE_TOUCH) {
3174            return IMPL.startNestedScroll(view, axes);
3175        }
3176        return false;
3177    }
3178
3179    /**
3180     * Stop a nested scroll in progress.
3181     *
3182     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
3183     *
3184     * @param type the type of input which cause this scroll event
3185     * @see #startNestedScroll(View, int)
3186     */
3187    public static void stopNestedScroll(@NonNull View view, @NestedScrollType int type) {
3188        if (view instanceof NestedScrollingChild2) {
3189            ((NestedScrollingChild2) view).stopNestedScroll(type);
3190        } else if (type == ViewCompat.TYPE_TOUCH) {
3191            IMPL.stopNestedScroll(view);
3192        }
3193    }
3194
3195    /**
3196     * Returns true if this view has a nested scrolling parent.
3197     *
3198     * <p>The presence of a nested scrolling parent indicates that this view has initiated
3199     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
3200     *
3201     * @param type the type of input which cause this scroll event
3202     * @return whether this view has a nested scrolling parent
3203     */
3204    public static boolean hasNestedScrollingParent(@NonNull View view, @NestedScrollType int type) {
3205        if (view instanceof NestedScrollingChild2) {
3206            ((NestedScrollingChild2) view).hasNestedScrollingParent(type);
3207        } else if (type == ViewCompat.TYPE_TOUCH) {
3208            return IMPL.hasNestedScrollingParent(view);
3209        }
3210        return false;
3211    }
3212
3213    /**
3214     * Dispatch one step of a nested scroll in progress.
3215     *
3216     * <p>Implementations of views that support nested scrolling should call this to report
3217     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
3218     * is not currently in progress or nested scrolling is not
3219     * {@link #isNestedScrollingEnabled(View) enabled} for this view this method does nothing.</p>
3220     *
3221     * <p>Compatible View implementations should also call
3222     * {@link #dispatchNestedPreScroll(View, int, int, int[], int[]) dispatchNestedPreScroll} before
3223     * consuming a component of the scroll event themselves.</p>
3224     *
3225     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
3226     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
3227     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
3228     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
3229     * @param offsetInWindow Optional. If not null, on return this will contain the offset
3230     *                       in local view coordinates of this view from before this operation
3231     *                       to after it completes. View implementations may use this to adjust
3232     *                       expected input coordinate tracking.
3233     * @param type the type of input which cause this scroll event
3234     * @return true if the event was dispatched, false if it could not be dispatched.
3235     * @see #dispatchNestedPreScroll(View, int, int, int[], int[])
3236     */
3237    public static boolean dispatchNestedScroll(@NonNull View view, int dxConsumed, int dyConsumed,
3238            int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow,
3239            @NestedScrollType int type) {
3240        if (view instanceof NestedScrollingChild2) {
3241            return ((NestedScrollingChild2) view).dispatchNestedScroll(dxConsumed, dyConsumed,
3242                    dxUnconsumed, dyUnconsumed, offsetInWindow, type);
3243        } else if (type == ViewCompat.TYPE_TOUCH) {
3244            return IMPL.dispatchNestedScroll(view, dxConsumed, dyConsumed, dxUnconsumed,
3245                    dyUnconsumed, offsetInWindow);
3246        }
3247        return false;
3248    }
3249
3250    /**
3251     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
3252     *
3253     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
3254     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
3255     * scrolling operation to consume some or all of the scroll operation before the child view
3256     * consumes it.</p>
3257     *
3258     * @param dx Horizontal scroll distance in pixels
3259     * @param dy Vertical scroll distance in pixels
3260     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
3261     *                 and consumed[1] the consumed dy.
3262     * @param offsetInWindow Optional. If not null, on return this will contain the offset
3263     *                       in local view coordinates of this view from before this operation
3264     *                       to after it completes. View implementations may use this to adjust
3265     *                       expected input coordinate tracking.
3266     * @param type the type of input which cause this scroll event
3267     * @return true if the parent consumed some or all of the scroll delta
3268     * @see #dispatchNestedScroll(View, int, int, int, int, int[])
3269     */
3270    public static boolean dispatchNestedPreScroll(@NonNull View view, int dx, int dy,
3271            @Nullable int[] consumed, @Nullable int[] offsetInWindow, @NestedScrollType int type) {
3272        if (view instanceof NestedScrollingChild2) {
3273            return ((NestedScrollingChild2) view).dispatchNestedPreScroll(dx, dy, consumed,
3274                    offsetInWindow, type);
3275        } else if (type == ViewCompat.TYPE_TOUCH) {
3276            return IMPL.dispatchNestedPreScroll(view, dx, dy, consumed, offsetInWindow);
3277        }
3278        return false;
3279    }
3280
3281    /**
3282     * Dispatch a fling to a nested scrolling parent.
3283     *
3284     * <p>This method should be used to indicate that a nested scrolling child has detected
3285     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
3286     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
3287     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
3288     * along a scrollable axis.</p>
3289     *
3290     * <p>If a nested scrolling child view would normally fling but it is at the edge of
3291     * its own content, it can use this method to delegate the fling to its nested scrolling
3292     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
3293     *
3294     * @param velocityX Horizontal fling velocity in pixels per second
3295     * @param velocityY Vertical fling velocity in pixels per second
3296     * @param consumed true if the child consumed the fling, false otherwise
3297     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
3298     */
3299    public static boolean dispatchNestedFling(@NonNull View view, float velocityX, float velocityY,
3300            boolean consumed) {
3301        return IMPL.dispatchNestedFling(view, velocityX, velocityY, consumed);
3302    }
3303
3304    /**
3305     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
3306     *
3307     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
3308     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
3309     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
3310     * before the child view consumes it. If this method returns <code>true</code>, a nested
3311     * parent view consumed the fling and this view should not scroll as a result.</p>
3312     *
3313     * <p>For a better user experience, only one view in a nested scrolling chain should consume
3314     * the fling at a time. If a parent view consumed the fling this method will return false.
3315     * Custom view implementations should account for this in two ways:</p>
3316     *
3317     * <ul>
3318     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
3319     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
3320     *     position regardless.</li>
3321     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
3322     *     even to settle back to a valid idle position.</li>
3323     * </ul>
3324     *
3325     * <p>Views should also not offer fling velocities to nested parent views along an axis
3326     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
3327     * should not offer a horizontal fling velocity to its parents since scrolling along that
3328     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
3329     *
3330     * @param velocityX Horizontal fling velocity in pixels per second
3331     * @param velocityY Vertical fling velocity in pixels per second
3332     * @return true if a nested scrolling parent consumed the fling
3333     */
3334    public static boolean dispatchNestedPreFling(@NonNull View view, float velocityX,
3335            float velocityY) {
3336        return IMPL.dispatchNestedPreFling(view, velocityX, velocityY);
3337    }
3338
3339    /**
3340     * Returns whether the view hierarchy is currently undergoing a layout pass. This
3341     * information is useful to avoid situations such as calling {@link View#requestLayout()}
3342     * during a layout pass.
3343     * <p>
3344     * Compatibility:
3345     * <ul>
3346     *     <li>API &lt; 18: Always returns {@code false}</li>
3347     * </ul>
3348     *
3349     * @return whether the view hierarchy is currently undergoing a layout pass
3350     */
3351    public static boolean isInLayout(View view) {
3352        return IMPL.isInLayout(view);
3353    }
3354
3355    /**
3356     * Returns true if {@code view} has been through at least one layout since it
3357     * was last attached to or detached from a window.
3358     */
3359    public static boolean isLaidOut(View view) {
3360        return IMPL.isLaidOut(view);
3361    }
3362
3363    /**
3364     * Returns whether layout direction has been resolved.
3365     * <p>
3366     * Compatibility:
3367     * <ul>
3368     *     <li>API &lt; 19: Always returns {@code false}</li>
3369     * </ul>
3370     *
3371     * @return true if layout direction has been resolved.
3372     */
3373    public static boolean isLayoutDirectionResolved(View view) {
3374        return IMPL.isLayoutDirectionResolved(view);
3375    }
3376
3377    /**
3378     * The visual z position of this view, in pixels. This is equivalent to the
3379     * {@link #setTranslationZ(View, float) translationZ} property plus the current
3380     * {@link #getElevation(View) elevation} property.
3381     *
3382     * @return The visual z position of this view, in pixels.
3383     */
3384    public static float getZ(View view) {
3385        return IMPL.getZ(view);
3386    }
3387
3388    /**
3389     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
3390     * {@link #setTranslationZ(View, float) translationZ} property to be the difference between
3391     * the x value passed in and the current {@link #getElevation(View) elevation} property.
3392     * <p>
3393     * Compatibility:
3394     * <ul>
3395     *     <li>API &lt; 21: No-op
3396     * </ul>
3397     *
3398     * @param z The visual z position of this view, in pixels.
3399     */
3400    public static void setZ(View view, float z) {
3401        IMPL.setZ(view, z);
3402    }
3403
3404    /**
3405     * Offset this view's vertical location by the specified number of pixels.
3406     *
3407     * @param offset the number of pixels to offset the view by
3408     */
3409    public static void offsetTopAndBottom(View view, int offset) {
3410        IMPL.offsetTopAndBottom(view, offset);
3411    }
3412
3413    /**
3414     * Offset this view's horizontal location by the specified amount of pixels.
3415     *
3416     * @param offset the number of pixels to offset the view by
3417     */
3418    public static void offsetLeftAndRight(View view, int offset) {
3419        IMPL.offsetLeftAndRight(view, offset);
3420    }
3421
3422    /**
3423     * Sets a rectangular area on this view to which the view will be clipped
3424     * when it is drawn. Setting the value to null will remove the clip bounds
3425     * and the view will draw normally, using its full bounds.
3426     *
3427     * <p>Prior to API 18 this does nothing.</p>
3428     *
3429     * @param view       The view to set clipBounds.
3430     * @param clipBounds The rectangular area, in the local coordinates of
3431     * this view, to which future drawing operations will be clipped.
3432     */
3433    public static void setClipBounds(View view, Rect clipBounds) {
3434        IMPL.setClipBounds(view, clipBounds);
3435    }
3436
3437    /**
3438     * Returns a copy of the current {@link #setClipBounds(View, Rect)}.
3439     *
3440     * <p>Prior to API 18 this will return null.</p>
3441     *
3442     * @return A copy of the current clip bounds if clip bounds are set,
3443     * otherwise null.
3444     */
3445    public static Rect getClipBounds(View view) {
3446        return IMPL.getClipBounds(view);
3447    }
3448
3449    /**
3450     * Returns true if the provided view is currently attached to a window.
3451     */
3452    public static boolean isAttachedToWindow(View view) {
3453        return IMPL.isAttachedToWindow(view);
3454    }
3455
3456    /**
3457     * Returns whether the provided view has an attached {@link View.OnClickListener}.
3458     *
3459     * @return true if there is a listener, false if there is none.
3460     */
3461    public static boolean hasOnClickListeners(View view) {
3462        return IMPL.hasOnClickListeners(view);
3463    }
3464
3465    /**
3466     * Sets the state of all scroll indicators.
3467     * <p>
3468     * See {@link #setScrollIndicators(View, int, int)} for usage information.
3469     *
3470     * @param indicators a bitmask of indicators that should be enabled, or
3471     *                   {@code 0} to disable all indicators
3472     *
3473     * @see #setScrollIndicators(View, int, int)
3474     * @see #getScrollIndicators(View)
3475     */
3476    public static void setScrollIndicators(@NonNull View view, @ScrollIndicators int indicators) {
3477        IMPL.setScrollIndicators(view, indicators);
3478    }
3479
3480    /**
3481     * Sets the state of the scroll indicators specified by the mask. To change
3482     * all scroll indicators at once, see {@link #setScrollIndicators(View, int)}.
3483     * <p>
3484     * When a scroll indicator is enabled, it will be displayed if the view
3485     * can scroll in the direction of the indicator.
3486     * <p>
3487     * Multiple indicator types may be enabled or disabled by passing the
3488     * logical OR of the desired types. If multiple types are specified, they
3489     * will all be set to the same enabled state.
3490     * <p>
3491     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators}
3492     *
3493     * @param indicators the indicator direction, or the logical OR of multiple
3494     *             indicator directions. One or more of:
3495     *             <ul>
3496     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
3497     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
3498     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
3499     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
3500     *               <li>{@link #SCROLL_INDICATOR_START}</li>
3501     *               <li>{@link #SCROLL_INDICATOR_END}</li>
3502     *             </ul>
3503     *
3504     * @see #setScrollIndicators(View, int)
3505     * @see #getScrollIndicators(View)
3506     */
3507    public static void setScrollIndicators(@NonNull View view, @ScrollIndicators int indicators,
3508            @ScrollIndicators int mask) {
3509        IMPL.setScrollIndicators(view, indicators, mask);
3510    }
3511
3512    /**
3513     * Returns a bitmask representing the enabled scroll indicators.
3514     * <p>
3515     * For example, if the top and left scroll indicators are enabled and all
3516     * other indicators are disabled, the return value will be
3517     * {@code ViewCompat.SCROLL_INDICATOR_TOP | ViewCompat.SCROLL_INDICATOR_LEFT}.
3518     * <p>
3519     * To check whether the bottom scroll indicator is enabled, use the value
3520     * of {@code (ViewCompat.getScrollIndicators(view) & ViewCompat.SCROLL_INDICATOR_BOTTOM) != 0}.
3521     *
3522     * @return a bitmask representing the enabled scroll indicators
3523     */
3524    public static int getScrollIndicators(@NonNull View view) {
3525        return IMPL.getScrollIndicators(view);
3526    }
3527
3528    /**
3529     * Set the pointer icon for the current view.
3530     * @param pointerIcon A PointerIconCompat instance which will be shown when the mouse hovers.
3531     */
3532    public static void setPointerIcon(@NonNull View view, PointerIconCompat pointerIcon) {
3533        IMPL.setPointerIcon(view, pointerIcon);
3534    }
3535
3536    /**
3537     * Gets the logical display to which the view's window has been attached.
3538     * <p>
3539     * Compatibility:
3540     * <ul>
3541     * <li>API &lt; 17: Returns the default display when the view is attached. Otherwise, null.
3542     * </ul>
3543     *
3544     * @return The logical display, or null if the view is not currently attached to a window.
3545     */
3546    public static Display getDisplay(@NonNull View view) {
3547        return IMPL.getDisplay(view);
3548    }
3549
3550    /**
3551     * Sets the tooltip for the view.
3552     *
3553     * <p>Prior to API 26 this does nothing. Use TooltipCompat class from v7 appcompat library
3554     * for a compatible tooltip implementation.</p>
3555     *
3556     * @param tooltipText the tooltip text
3557     */
3558    public static void setTooltipText(@NonNull View view, @Nullable CharSequence tooltipText) {
3559        IMPL.setTooltipText(view, tooltipText);
3560    }
3561
3562    /**
3563     * Start the drag and drop operation.
3564     */
3565    public static boolean startDragAndDrop(View v, ClipData data,
3566            View.DragShadowBuilder shadowBuilder, Object localState, int flags) {
3567        return IMPL.startDragAndDrop(v, data, shadowBuilder, localState, flags);
3568    }
3569
3570    /**
3571     * Cancel the drag and drop operation.
3572     */
3573    public static void cancelDragAndDrop(View v) {
3574        IMPL.cancelDragAndDrop(v);
3575    }
3576
3577    /**
3578     * Update the drag shadow while drag and drop is in progress.
3579     */
3580    public static void updateDragShadow(View v, View.DragShadowBuilder shadowBuilder) {
3581        IMPL.updateDragShadow(v, shadowBuilder);
3582    }
3583
3584    /**
3585     * Gets the ID of the next keyboard navigation cluster root.
3586     *
3587     * @return the next keyboard navigation cluster ID, or {@link View#NO_ID} if the framework
3588     *         should decide automatically or API < 26.
3589     */
3590    public static int getNextClusterForwardId(@NonNull View view) {
3591        return IMPL.getNextClusterForwardId(view);
3592    }
3593
3594    /**
3595     * Sets the ID of the next keyboard navigation cluster root view. Does nothing if {@code view}
3596     * is not a keyboard navigation cluster or if API < 26.
3597     *
3598     * @param nextClusterForwardId next cluster ID, or {@link View#NO_ID} if the framework
3599     *                             should decide automatically.
3600     */
3601    public static void setNextClusterForwardId(@NonNull View view, int nextClusterForwardId) {
3602        IMPL.setNextClusterForwardId(view, nextClusterForwardId);
3603    }
3604
3605    /**
3606     * Returns whether {@code view} is a root of a keyboard navigation cluster. Always returns
3607     * {@code false} on API < 26.
3608     *
3609     * @return {@code true} if this view is a root of a cluster, or {@code false} otherwise.
3610     */
3611    public static boolean isKeyboardNavigationCluster(@NonNull View view) {
3612        return IMPL.isKeyboardNavigationCluster(view);
3613    }
3614
3615    /**
3616     * Set whether {@code view} is a root of a keyboard navigation cluster. Does nothing if
3617     * API < 26.
3618     *
3619     * @param isCluster {@code true} to mark {@code view} as the root of a cluster, {@code false}
3620     *                  to unmark.
3621     */
3622    public static void setKeyboardNavigationCluster(@NonNull View view, boolean isCluster) {
3623        IMPL.setKeyboardNavigationCluster(view, isCluster);
3624    }
3625
3626    /**
3627     * Returns whether {@code view} should receive focus when the focus is restored for the view
3628     * hierarchy containing it. Returns {@code false} on API < 26.
3629     * <p>
3630     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
3631     * window or serves as a target of cluster navigation.
3632     *
3633     * @return {@code true} if {@code view} is the default-focus view, {@code false} otherwise.
3634     */
3635    public static boolean isFocusedByDefault(@NonNull View view) {
3636        return IMPL.isFocusedByDefault(view);
3637    }
3638
3639    /**
3640     * Sets whether {@code view} should receive focus when the focus is restored for the view
3641     * hierarchy containing it.
3642     * <p>
3643     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
3644     * window or serves as a target of cluster navigation.
3645     * <p>
3646     * Does nothing on API < 26.
3647     *
3648     * @param isFocusedByDefault {@code true} to set {@code view} as the default-focus view,
3649     *                           {@code false} otherwise.
3650     */
3651    public static void setFocusedByDefault(@NonNull View view, boolean isFocusedByDefault) {
3652        IMPL.setFocusedByDefault(view, isFocusedByDefault);
3653    }
3654
3655    /**
3656     * Find the nearest keyboard navigation cluster in the specified direction.
3657     * This does not actually give focus to that cluster.
3658     *
3659     * @param currentCluster The starting point of the search. {@code null} means the current
3660     *                       cluster is not found yet.
3661     * @param direction Direction to look.
3662     *
3663     * @return the nearest keyboard navigation cluster in the specified direction, or {@code null}
3664     *         if one can't be found or if API < 26.
3665     */
3666    public static View keyboardNavigationClusterSearch(@NonNull View view, View currentCluster,
3667            @FocusDirection int direction) {
3668        return IMPL.keyboardNavigationClusterSearch(view, currentCluster, direction);
3669    }
3670
3671    /**
3672     * Adds any keyboard navigation cluster roots that are descendants of {@code view} (
3673     * including {@code view} if it is a cluster root itself) to {@code views}. Does nothing
3674     * on API < 26.
3675     *
3676     * @param views collection of keyboard navigation cluster roots found so far.
3677     * @param direction direction to look.
3678     */
3679    public static void addKeyboardNavigationClusters(@NonNull View view,
3680            @NonNull Collection<View> views, int direction) {
3681        IMPL.addKeyboardNavigationClusters(view, views, direction);
3682    }
3683
3684    /**
3685     * Gives focus to the default-focus view in the view hierarchy rooted at {@code view}.
3686     * If the default-focus view cannot be found or if API < 26, this falls back to calling
3687     * {@link View#requestFocus(int)}.
3688     *
3689     * @return {@code true} if {@code view} or one of its descendants took focus, {@code false}
3690     *         otherwise.
3691     */
3692    public static boolean restoreDefaultFocus(@NonNull View view) {
3693        return IMPL.restoreDefaultFocus(view);
3694    }
3695
3696    protected ViewCompat() {}
3697}
3698