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