ViewCompat.java revision b1bfdf4c03d1b25959c5818805b997020f7ed085
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.graphics.Paint;
20import android.graphics.PixelFormat;
21import android.graphics.Rect;
22import android.graphics.drawable.Drawable;
23import android.os.Bundle;
24import android.support.annotation.IdRes;
25import android.support.annotation.IntDef;
26import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
27import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
28import android.util.Log;
29import android.view.View;
30import android.view.ViewParent;
31import android.view.accessibility.AccessibilityEvent;
32
33import java.lang.annotation.Retention;
34import java.lang.annotation.RetentionPolicy;
35import java.lang.reflect.InvocationTargetException;
36import java.lang.reflect.Method;
37
38/**
39 * Helper for accessing features in {@link View} introduced after API
40 * level 4 in a backwards compatible fashion.
41 */
42public class ViewCompat {
43    private static final String TAG = "ViewCompat";
44
45    /** @hide */
46    @IntDef({OVER_SCROLL_ALWAYS, OVER_SCROLL_IF_CONTENT_SCROLLS, OVER_SCROLL_IF_CONTENT_SCROLLS})
47    @Retention(RetentionPolicy.SOURCE)
48    private @interface OverScroll {}
49
50    /**
51     * Always allow a user to over-scroll this view, provided it is a
52     * view that can scroll.
53     */
54    public static final int OVER_SCROLL_ALWAYS = 0;
55
56    /**
57     * Allow a user to over-scroll this view only if the content is large
58     * enough to meaningfully scroll, provided it is a view that can scroll.
59     */
60    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
61
62    /**
63     * Never allow a user to over-scroll this view.
64     */
65    public static final int OVER_SCROLL_NEVER = 2;
66
67    private static final long FAKE_FRAME_TIME = 10;
68
69    /** @hide */
70    @IntDef({
71            IMPORTANT_FOR_ACCESSIBILITY_AUTO,
72            IMPORTANT_FOR_ACCESSIBILITY_YES,
73            IMPORTANT_FOR_ACCESSIBILITY_NO,
74            IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
75    })
76    @Retention(RetentionPolicy.SOURCE)
77    private @interface ImportantForAccessibility {}
78
79    /**
80     * Automatically determine whether a view is important for accessibility.
81     */
82    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
83
84    /**
85     * The view is important for accessibility.
86     */
87    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
88
89    /**
90     * The view is not important for accessibility.
91     */
92    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
93
94    /**
95     * The view is not important for accessibility, nor are any of its
96     * descendant views.
97     */
98    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
99
100    /** @hide */
101    @IntDef({
102            ACCESSIBILITY_LIVE_REGION_NONE,
103            ACCESSIBILITY_LIVE_REGION_POLITE,
104            ACCESSIBILITY_LIVE_REGION_ASSERTIVE
105    })
106    @Retention(RetentionPolicy.SOURCE)
107    private @interface AccessibilityLiveRegion {}
108
109    /**
110     * Live region mode specifying that accessibility services should not
111     * automatically announce changes to this view. This is the default live
112     * region mode for most views.
113     * <p>
114     * Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}.
115     */
116    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
117
118    /**
119     * Live region mode specifying that accessibility services should announce
120     * changes to this view.
121     * <p>
122     * Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}.
123     */
124    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
125
126    /**
127     * Live region mode specifying that accessibility services should interrupt
128     * ongoing speech to immediately announce changes to this view.
129     * <p>
130     * Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}.
131     */
132    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
133
134    /** @hide */
135    @IntDef({LAYER_TYPE_NONE, LAYER_TYPE_SOFTWARE, LAYER_TYPE_HARDWARE})
136    @Retention(RetentionPolicy.SOURCE)
137    private @interface LayerType {}
138
139    /**
140     * Indicates that the view does not have a layer.
141     */
142    public static final int LAYER_TYPE_NONE = 0;
143
144    /**
145     * <p>Indicates that the view has a software layer. A software layer is backed
146     * by a bitmap and causes the view to be rendered using Android's software
147     * rendering pipeline, even if hardware acceleration is enabled.</p>
148     *
149     * <p>Software layers have various usages:</p>
150     * <p>When the application is not using hardware acceleration, a software layer
151     * is useful to apply a specific color filter and/or blending mode and/or
152     * translucency to a view and all its children.</p>
153     * <p>When the application is using hardware acceleration, a software layer
154     * is useful to render drawing primitives not supported by the hardware
155     * accelerated pipeline. It can also be used to cache a complex view tree
156     * into a texture and reduce the complexity of drawing operations. For instance,
157     * when animating a complex view tree with a translation, a software layer can
158     * be used to render the view tree only once.</p>
159     * <p>Software layers should be avoided when the affected view tree updates
160     * often. Every update will require to re-render the software layer, which can
161     * potentially be slow (particularly when hardware acceleration is turned on
162     * since the layer will have to be uploaded into a hardware texture after every
163     * update.)</p>
164     */
165    public static final int LAYER_TYPE_SOFTWARE = 1;
166
167    /**
168     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
169     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
170     * OpenGL hardware) and causes the view to be rendered using Android's hardware
171     * rendering pipeline, but only if hardware acceleration is turned on for the
172     * view hierarchy. When hardware acceleration is turned off, hardware layers
173     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
174     *
175     * <p>A hardware layer is useful to apply a specific color filter and/or
176     * blending mode and/or translucency to a view and all its children.</p>
177     * <p>A hardware layer can be used to cache a complex view tree into a
178     * texture and reduce the complexity of drawing operations. For instance,
179     * when animating a complex view tree with a translation, a hardware layer can
180     * be used to render the view tree only once.</p>
181     * <p>A hardware layer can also be used to increase the rendering quality when
182     * rotation transformations are applied on a view. It can also be used to
183     * prevent potential clipping issues when applying 3D transforms on a view.</p>
184     */
185    public static final int LAYER_TYPE_HARDWARE = 2;
186
187    /** @hide */
188    @IntDef({
189            LAYOUT_DIRECTION_LTR,
190            LAYOUT_DIRECTION_RTL,
191            LAYOUT_DIRECTION_INHERIT,
192            LAYOUT_DIRECTION_LOCALE})
193    @Retention(RetentionPolicy.SOURCE)
194    private @interface LayoutDirectionMode {}
195
196    /** @hide */
197    @IntDef({
198            LAYOUT_DIRECTION_LTR,
199            LAYOUT_DIRECTION_RTL
200    })
201    @Retention(RetentionPolicy.SOURCE)
202    private @interface ResolvedLayoutDirectionMode {}
203
204    /**
205     * Horizontal layout direction of this view is from Left to Right.
206     */
207    public static final int LAYOUT_DIRECTION_LTR = 0;
208
209    /**
210     * Horizontal layout direction of this view is from Right to Left.
211     */
212    public static final int LAYOUT_DIRECTION_RTL = 1;
213
214    /**
215     * Horizontal layout direction of this view is inherited from its parent.
216     * Use with {@link #setLayoutDirection}.
217     */
218    public static final int LAYOUT_DIRECTION_INHERIT = 2;
219
220    /**
221     * Horizontal layout direction of this view is from deduced from the default language
222     * script for the locale. Use with {@link #setLayoutDirection}.
223     */
224    public static final int LAYOUT_DIRECTION_LOCALE = 3;
225
226    /**
227     * Bits of {@link #getMeasuredWidthAndState} and
228     * {@link #getMeasuredWidthAndState} that provide the actual measured size.
229     */
230    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
231
232    /**
233     * Bits of {@link #getMeasuredWidthAndState} and
234     * {@link #getMeasuredWidthAndState} that provide the additional state bits.
235     */
236    public static final int MEASURED_STATE_MASK = 0xff000000;
237
238    /**
239     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
240     * for functions that combine both width and height into a single int,
241     * such as {@link #getMeasuredState} and the childState argument of
242     * {@link #resolveSizeAndState(int, int, int)}.
243     */
244    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
245
246    /**
247     * Bit of {@link #getMeasuredWidthAndState} and
248     * {@link #getMeasuredWidthAndState} that indicates the measured size
249     * is smaller that the space the view would like to have.
250     */
251    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
252
253    interface ViewCompatImpl {
254        public boolean canScrollHorizontally(View v, int direction);
255        public boolean canScrollVertically(View v, int direction);
256        public int getOverScrollMode(View v);
257        public void setOverScrollMode(View v, int mode);
258        public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event);
259        public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event);
260        public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info);
261        public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate);
262        public boolean hasTransientState(View view);
263        public void setHasTransientState(View view, boolean hasTransientState);
264        public void postInvalidateOnAnimation(View view);
265        public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom);
266        public void postOnAnimation(View view, Runnable action);
267        public void postOnAnimationDelayed(View view, Runnable action, long delayMillis);
268        public int getImportantForAccessibility(View view);
269        public void setImportantForAccessibility(View view, int mode);
270        public boolean performAccessibilityAction(View view, int action, Bundle arguments);
271        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view);
272        public float getAlpha(View view);
273        public void setLayerType(View view, int layerType, Paint paint);
274        public int getLayerType(View view);
275        public int getLabelFor(View view);
276        public void setLabelFor(View view, int id);
277        public void setLayerPaint(View view, Paint paint);
278        public int getLayoutDirection(View view);
279        public void setLayoutDirection(View view, int layoutDirection);
280        public ViewParent getParentForAccessibility(View view);
281        public boolean isOpaque(View view);
282        public int resolveSizeAndState(int size, int measureSpec, int childMeasuredState);
283        public int getMeasuredWidthAndState(View view);
284        public int getMeasuredHeightAndState(View view);
285        public int getMeasuredState(View view);
286        public int getAccessibilityLiveRegion(View view);
287        public void setAccessibilityLiveRegion(View view, int mode);
288        public int getPaddingStart(View view);
289        public int getPaddingEnd(View view);
290        public void setPaddingRelative(View view, int start, int top, int end, int bottom);
291        public void dispatchStartTemporaryDetach(View view);
292        public void dispatchFinishTemporaryDetach(View view);
293        public float getTranslationX(View view);
294        public float getTranslationY(View view);
295        public int getMinimumWidth(View view);
296        public int getMinimumHeight(View view);
297    }
298
299    static class BaseViewCompatImpl implements ViewCompatImpl {
300        private Method mDispatchStartTemporaryDetach;
301        private Method mDispatchFinishTemporaryDetach;
302        private boolean mTempDetachBound;
303
304        public boolean canScrollHorizontally(View v, int direction) {
305            return false;
306        }
307        public boolean canScrollVertically(View v, int direction) {
308            return false;
309        }
310        public int getOverScrollMode(View v) {
311            return OVER_SCROLL_NEVER;
312        }
313        public void setOverScrollMode(View v, int mode) {
314            // Do nothing; API doesn't exist
315        }
316        public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) {
317            // Do nothing; API doesn't exist
318        }
319        public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {
320            // Do nothing; API doesn't exist
321        }
322        public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {
323         // Do nothing; API doesn't exist
324        }
325        public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
326            // Do nothing; API doesn't exist
327        }
328        public boolean hasTransientState(View view) {
329            // A view can't have transient state if transient state wasn't supported.
330            return false;
331        }
332        public void setHasTransientState(View view, boolean hasTransientState) {
333            // Do nothing; API doesn't exist
334        }
335        public void postInvalidateOnAnimation(View view) {
336            view.invalidate();
337        }
338        public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) {
339            view.invalidate(left, top, right, bottom);
340        }
341        public void postOnAnimation(View view, Runnable action) {
342            view.postDelayed(action, getFrameTime());
343        }
344        public void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
345            view.postDelayed(action, getFrameTime() + delayMillis);
346        }
347        long getFrameTime() {
348            return FAKE_FRAME_TIME;
349        }
350        public int getImportantForAccessibility(View view) {
351            return 0;
352        }
353        public void setImportantForAccessibility(View view, int mode) {
354
355        }
356        public boolean performAccessibilityAction(View view, int action, Bundle arguments) {
357            return false;
358        }
359        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
360            return null;
361        }
362        public float getAlpha(View view) {
363            return 1.0f;
364        }
365        public void setLayerType(View view, int layerType, Paint paint) {
366            // No-op until layers became available (HC)
367        }
368        public int getLayerType(View view) {
369            return LAYER_TYPE_NONE;
370        }
371        public int getLabelFor(View view) {
372            return 0;
373        }
374        public void setLabelFor(View view, int id) {
375
376        }
377        public void setLayerPaint(View view, Paint p) {
378            // No-op until layers became available (HC)
379        }
380
381        @Override
382        public int getLayoutDirection(View view) {
383            return LAYOUT_DIRECTION_LTR;
384        }
385
386        @Override
387        public void setLayoutDirection(View view, int layoutDirection) {
388            // No-op
389        }
390
391        @Override
392        public ViewParent getParentForAccessibility(View view) {
393            return view.getParent();
394        }
395
396        @Override
397        public boolean isOpaque(View view) {
398            final Drawable bg = view.getBackground();
399            if (bg != null) {
400                return bg.getOpacity() == PixelFormat.OPAQUE;
401            }
402            return false;
403        }
404
405        public int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
406            return View.resolveSize(size, measureSpec);
407        }
408
409        @Override
410        public int getMeasuredWidthAndState(View view) {
411            return view.getMeasuredWidth();
412        }
413
414        @Override
415        public int getMeasuredHeightAndState(View view) {
416            return view.getMeasuredHeight();
417        }
418
419        @Override
420        public int getMeasuredState(View view) {
421            return 0;
422        }
423
424        @Override
425        public int getAccessibilityLiveRegion(View view) {
426            return ACCESSIBILITY_LIVE_REGION_NONE;
427        }
428
429        @Override
430        public void setAccessibilityLiveRegion(View view, int mode) {
431            // No-op
432        }
433
434        @Override
435        public int getPaddingStart(View view) {
436            return view.getPaddingLeft();
437        }
438
439        @Override
440        public int getPaddingEnd(View view) {
441            return view.getPaddingRight();
442        }
443
444        @Override
445        public void setPaddingRelative(View view, int start, int top, int end, int bottom) {
446            view.setPadding(start, top, end, bottom);
447        }
448
449        @Override
450        public void dispatchStartTemporaryDetach(View view) {
451            if (!mTempDetachBound) {
452                bindTempDetach();
453            }
454            if (mDispatchStartTemporaryDetach != null) {
455                try {
456                    mDispatchStartTemporaryDetach.invoke(view);
457                } catch (Exception e) {
458                    Log.d(TAG, "Error calling dispatchStartTemporaryDetach", e);
459                }
460            } else {
461                // Try this instead
462                view.onStartTemporaryDetach();
463            }
464        }
465
466        @Override
467        public void dispatchFinishTemporaryDetach(View view) {
468            if (!mTempDetachBound) {
469                bindTempDetach();
470            }
471            if (mDispatchFinishTemporaryDetach != null) {
472                try {
473                    mDispatchFinishTemporaryDetach.invoke(view);
474                } catch (Exception e) {
475                    Log.d(TAG, "Error calling dispatchFinishTemporaryDetach", e);
476                }
477            } else {
478                // Try this instead
479                view.onFinishTemporaryDetach();
480            }
481        }
482
483        private void bindTempDetach() {
484            try {
485                mDispatchStartTemporaryDetach = View.class.getDeclaredMethod(
486                        "dispatchStartTemporaryDetach");
487                mDispatchFinishTemporaryDetach = View.class.getDeclaredMethod(
488                        "dispatchFinishTemporaryDetach");
489            } catch (NoSuchMethodException e) {
490                Log.e(TAG, "Couldn't find method", e);
491            }
492            mTempDetachBound = true;
493        }
494
495        @Override
496        public float getTranslationX(View view) {
497            return 0;
498        }
499
500        @Override
501        public float getTranslationY(View view) {
502            return 0;
503        }
504
505        @Override
506        public int getMinimumWidth(View view) {
507            return 0;
508        }
509
510        @Override
511        public int getMinimumHeight(View view) {
512            return 0;
513        }
514    }
515
516    static class EclairMr1ViewCompatImpl extends BaseViewCompatImpl {
517        @Override
518        public boolean isOpaque(View view) {
519            return ViewCompatEclairMr1.isOpaque(view);
520        }
521    }
522
523    static class GBViewCompatImpl extends EclairMr1ViewCompatImpl {
524        @Override
525        public int getOverScrollMode(View v) {
526            return ViewCompatGingerbread.getOverScrollMode(v);
527        }
528        @Override
529        public void setOverScrollMode(View v, int mode) {
530            ViewCompatGingerbread.setOverScrollMode(v, mode);
531        }
532    }
533
534    static class HCViewCompatImpl extends GBViewCompatImpl {
535        @Override
536        long getFrameTime() {
537            return ViewCompatHC.getFrameTime();
538        }
539        @Override
540        public float getAlpha(View view) {
541            return ViewCompatHC.getAlpha(view);
542        }
543        @Override
544        public void setLayerType(View view, int layerType, Paint paint) {
545            ViewCompatHC.setLayerType(view, layerType, paint);
546        }
547        @Override
548        public int getLayerType(View view)  {
549            return ViewCompatHC.getLayerType(view);
550        }
551        @Override
552        public void setLayerPaint(View view, Paint paint) {
553            // Make sure the paint is correct; this will be cheap if it's the same
554            // instance as was used to call setLayerType earlier.
555            setLayerType(view, getLayerType(view), paint);
556            // This is expensive, but the only way to accomplish this before JB-MR1.
557            view.invalidate();
558        }
559        @Override
560        public int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
561            return ViewCompatHC.resolveSizeAndState(size, measureSpec, childMeasuredState);
562        }
563        @Override
564        public int getMeasuredWidthAndState(View view) {
565            return ViewCompatHC.getMeasuredWidthAndState(view);
566        }
567        @Override
568        public int getMeasuredHeightAndState(View view) {
569            return ViewCompatHC.getMeasuredHeightAndState(view);
570        }
571        @Override
572        public int getMeasuredState(View view) {
573            return ViewCompatHC.getMeasuredState(view);
574        }
575        @Override
576        public float getTranslationX(View view) {
577            return ViewCompatHC.getTranslationX(view);
578        }
579        @Override
580        public float getTranslationY(View view) {
581            return ViewCompatHC.getTranslationY(view);
582        }
583    }
584
585    static class ICSViewCompatImpl extends HCViewCompatImpl {
586        @Override
587        public boolean canScrollHorizontally(View v, int direction) {
588            return ViewCompatICS.canScrollHorizontally(v, direction);
589        }
590        @Override
591        public boolean canScrollVertically(View v, int direction) {
592            return ViewCompatICS.canScrollVertically(v, direction);
593        }
594        @Override
595        public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {
596            ViewCompatICS.onPopulateAccessibilityEvent(v, event);
597        }
598        @Override
599        public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {
600            ViewCompatICS.onInitializeAccessibilityEvent(v, event);
601        }
602        @Override
603        public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
604            ViewCompatICS.onInitializeAccessibilityNodeInfo(v, info.getInfo());
605        }
606        @Override
607        public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) {
608            ViewCompatICS.setAccessibilityDelegate(v, delegate.getBridge());
609        }
610    }
611
612    static class JBViewCompatImpl extends ICSViewCompatImpl {
613        @Override
614        public boolean hasTransientState(View view) {
615            return ViewCompatJB.hasTransientState(view);
616        }
617        @Override
618        public void setHasTransientState(View view, boolean hasTransientState) {
619            ViewCompatJB.setHasTransientState(view, hasTransientState);
620        }
621        @Override
622        public void postInvalidateOnAnimation(View view) {
623            ViewCompatJB.postInvalidateOnAnimation(view);
624        }
625        @Override
626        public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) {
627            ViewCompatJB.postInvalidateOnAnimation(view, left, top, right, bottom);
628        }
629        @Override
630        public void postOnAnimation(View view, Runnable action) {
631            ViewCompatJB.postOnAnimation(view, action);
632        }
633        @Override
634        public void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
635            ViewCompatJB.postOnAnimationDelayed(view, action, delayMillis);
636        }
637        @Override
638        public int getImportantForAccessibility(View view) {
639            return ViewCompatJB.getImportantForAccessibility(view);
640        }
641        @Override
642        public void setImportantForAccessibility(View view, int mode) {
643            // IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS is not available
644            // on this platform so replace with IMPORTANT_FOR_ACCESSIBILITY_NO
645            // which is closer semantically.
646            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
647                mode = IMPORTANT_FOR_ACCESSIBILITY_NO;
648            }
649            ViewCompatJB.setImportantForAccessibility(view, mode);
650        }
651        @Override
652        public boolean performAccessibilityAction(View view, int action, Bundle arguments) {
653            return ViewCompatJB.performAccessibilityAction(view, action, arguments);
654        }
655        @Override
656        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
657            Object compat = ViewCompatJB.getAccessibilityNodeProvider(view);
658            if (compat != null) {
659                return new AccessibilityNodeProviderCompat(compat);
660            }
661            return null;
662        }
663
664        @Override
665        public ViewParent getParentForAccessibility(View view) {
666            return ViewCompatJB.getParentForAccessibility(view);
667        }
668
669        @Override
670        public int getMinimumWidth(View view) {
671            return ViewCompatJB.getMinimumWidth(view);
672        }
673
674        @Override
675        public int getMinimumHeight(View view) {
676            return ViewCompatJB.getMinimumHeight(view);
677        }
678    }
679
680    static class JbMr1ViewCompatImpl extends JBViewCompatImpl {
681
682        @Override
683        public int getLabelFor(View view) {
684            return ViewCompatJellybeanMr1.getLabelFor(view);
685        }
686
687        @Override
688        public void setLabelFor(View view, int id) {
689            ViewCompatJellybeanMr1.setLabelFor(view, id);
690        }
691
692        @Override
693        public void setLayerPaint(View view, Paint paint) {
694            ViewCompatJellybeanMr1.setLayerPaint(view, paint);
695        }
696
697        @Override
698        public int getLayoutDirection(View view) {
699            return ViewCompatJellybeanMr1.getLayoutDirection(view);
700        }
701
702        @Override
703        public void setLayoutDirection(View view, int layoutDirection) {
704            ViewCompatJellybeanMr1.setLayoutDirection(view, layoutDirection);
705        }
706
707        @Override
708        public int getPaddingStart(View view) {
709            return ViewCompatJellybeanMr1.getPaddingStart(view);
710        }
711
712        @Override
713        public int getPaddingEnd(View view) {
714            return ViewCompatJellybeanMr1.getPaddingEnd(view);
715        }
716
717        @Override
718        public void setPaddingRelative(View view, int start, int top, int end, int bottom) {
719            ViewCompatJellybeanMr1.setPaddingRelative(view, start, top, end, bottom);
720        }
721    }
722
723    static class KitKatViewCompatImpl extends JbMr1ViewCompatImpl {
724        @Override
725        public int getAccessibilityLiveRegion(View view) {
726            return ViewCompatKitKat.getAccessibilityLiveRegion(view);
727        }
728
729        @Override
730        public void setAccessibilityLiveRegion(View view, int mode) {
731            ViewCompatKitKat.setAccessibilityLiveRegion(view, mode);
732        }
733
734        @Override
735        public void setImportantForAccessibility(View view, int mode) {
736            ViewCompatJB.setImportantForAccessibility(view, mode);
737        }
738    }
739
740    static final ViewCompatImpl IMPL;
741    static {
742        final int version = android.os.Build.VERSION.SDK_INT;
743        if (version >= 19) {
744            IMPL = new KitKatViewCompatImpl();
745        } else if (version >= 17) {
746            IMPL = new JbMr1ViewCompatImpl();
747        } else if (version >= 16) {
748            IMPL = new JBViewCompatImpl();
749        } else if (version >= 14) {
750            IMPL = new ICSViewCompatImpl();
751        } else if (version >= 11) {
752            IMPL = new HCViewCompatImpl();
753        } else if (version >= 9) {
754            IMPL = new GBViewCompatImpl();
755        } else {
756            IMPL = new BaseViewCompatImpl();
757        }
758    }
759
760    /**
761     * Check if this view can be scrolled horizontally in a certain direction.
762     *
763     * @param v The View against which to invoke the method.
764     * @param direction Negative to check scrolling left, positive to check scrolling right.
765     * @return true if this view can be scrolled in the specified direction, false otherwise.
766     */
767    public static boolean canScrollHorizontally(View v, int direction) {
768        return IMPL.canScrollHorizontally(v, direction);
769    }
770
771    /**
772     * Check if this view can be scrolled vertically in a certain direction.
773     *
774     * @param v The View against which to invoke the method.
775     * @param direction Negative to check scrolling up, positive to check scrolling down.
776     * @return true if this view can be scrolled in the specified direction, false otherwise.
777     */
778    public static boolean canScrollVertically(View v, int direction) {
779        return IMPL.canScrollVertically(v, direction);
780    }
781
782    /**
783     * Returns the over-scroll mode for this view. The result will be
784     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
785     * (allow over-scrolling only if the view content is larger than the container),
786     * or {@link #OVER_SCROLL_NEVER}.
787     *
788     * @param v The View against which to invoke the method.
789     * @return This view's over-scroll mode.
790     */
791    @OverScroll
792    public static int getOverScrollMode(View v) {
793        return IMPL.getOverScrollMode(v);
794    }
795
796    /**
797     * Set the over-scroll mode for this view. Valid over-scroll modes are
798     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
799     * (allow over-scrolling only if the view content is larger than the container),
800     * or {@link #OVER_SCROLL_NEVER}.
801     *
802     * Setting the over-scroll mode of a view will have an effect only if the
803     * view is capable of scrolling.
804     *
805     * @param v The View against which to invoke the method.
806     * @param overScrollMode The new over-scroll mode for this view.
807     */
808    public static void setOverScrollMode(View v, @OverScroll int overScrollMode) {
809        IMPL.setOverScrollMode(v, overScrollMode);
810    }
811
812    /**
813     * Called from {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
814     * giving a chance to this View to populate the accessibility event with its
815     * text content. While this method is free to modify event
816     * attributes other than text content, doing so should normally be performed in
817     * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)}.
818     * <p>
819     * Example: Adding formatted date string to an accessibility event in addition
820     *          to the text added by the super implementation:
821     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
822     *     super.onPopulateAccessibilityEvent(event);
823     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
824     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
825     *         mCurrentDate.getTimeInMillis(), flags);
826     *     event.getText().add(selectedDateUtterance);
827     * }</pre>
828     * <p>
829     * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling
830     * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its
831     * {@link android.view.View.AccessibilityDelegate#onPopulateAccessibilityEvent(View,
832     *  AccessibilityEvent)}
833     * is responsible for handling this call.
834     * </p>
835     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
836     * information to the event, in case the default implementation has basic information to add.
837     * </p>
838     *
839     * @param v The View against which to invoke the method.
840     * @param event The accessibility event which to populate.
841     *
842     * @see View#sendAccessibilityEvent(int)
843     * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
844     */
845    public static void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {
846        IMPL.onPopulateAccessibilityEvent(v, event);
847    }
848
849    /**
850     * Initializes an {@link AccessibilityEvent} with information about
851     * this View which is the event source. In other words, the source of
852     * an accessibility event is the view whose state change triggered firing
853     * the event.
854     * <p>
855     * Example: Setting the password property of an event in addition
856     *          to properties set by the super implementation:
857     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
858     *     super.onInitializeAccessibilityEvent(event);
859     *     event.setPassword(true);
860     * }</pre>
861     * <p>
862     * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling
863     * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its
864     * {@link android.view.View.AccessibilityDelegate#onInitializeAccessibilityEvent(View,
865     *  AccessibilityEvent)}
866     * is responsible for handling this call.
867     * </p>
868     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
869     * information to the event, in case the default implementation has basic information to add.
870     * </p>
871     *
872     * @param v The View against which to invoke the method.
873     * @param event The event to initialize.
874     *
875     * @see View#sendAccessibilityEvent(int)
876     * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
877     */
878    public static void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {
879        IMPL.onInitializeAccessibilityEvent(v, event);
880    }
881
882    /**
883     * Initializes an {@link android.view.accessibility.AccessibilityNodeInfo} with information
884     * about this view. The base implementation sets:
885     * <ul>
886     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setParent(View)},</li>
887     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
888     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
889     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
890     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setClassName(CharSequence)},</li>
891     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
892     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setEnabled(boolean)},</li>
893     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setClickable(boolean)},</li>
894     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setFocusable(boolean)},</li>
895     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setFocused(boolean)},</li>
896     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setLongClickable(boolean)},</li>
897     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setSelected(boolean)},</li>
898     * </ul>
899     * <p>
900     * Subclasses should override this method, call the super implementation,
901     * and set additional attributes.
902     * </p>
903     * <p>
904     * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling
905     * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its
906     * {@link android.view.View.AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View,
907     *  android.view.accessibility.AccessibilityNodeInfo)}
908     * is responsible for handling this call.
909     * </p>
910     *
911     * @param v The View against which to invoke the method.
912     * @param info The instance to initialize.
913     */
914    public static void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
915        IMPL.onInitializeAccessibilityNodeInfo(v, info);
916    }
917
918    /**
919     * Sets a delegate for implementing accessibility support via compositon as
920     * opposed to inheritance. The delegate's primary use is for implementing
921     * backwards compatible widgets. For more details see
922     * {@link android.view.View.AccessibilityDelegate}.
923     *
924     * @param v The View against which to invoke the method.
925     * @param delegate The delegate instance.
926     *
927     * @see android.view.View.AccessibilityDelegate
928     */
929    public static void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) {
930        IMPL.setAccessibilityDelegate(v, delegate);
931    }
932
933    /**
934     * Indicates whether the view is currently tracking transient state that the
935     * app should not need to concern itself with saving and restoring, but that
936     * the framework should take special note to preserve when possible.
937     *
938     * @param view View to check for transient state
939     * @return true if the view has transient state
940     */
941    public static boolean hasTransientState(View view) {
942        return IMPL.hasTransientState(view);
943    }
944
945    /**
946     * Set whether this view is currently tracking transient state that the
947     * framework should attempt to preserve when possible.
948     *
949     * @param view View tracking transient state
950     * @param hasTransientState true if this view has transient state
951     */
952    public static void setHasTransientState(View view, boolean hasTransientState) {
953        IMPL.setHasTransientState(view, hasTransientState);
954    }
955
956    /**
957     * <p>Cause an invalidate to happen on the next animation time step, typically the
958     * next display frame.</p>
959     *
960     * <p>This method can be invoked from outside of the UI thread
961     * only when this View is attached to a window.</p>
962     *
963     * @param view View to invalidate
964     */
965    public static void postInvalidateOnAnimation(View view) {
966        IMPL.postInvalidateOnAnimation(view);
967    }
968
969    /**
970     * <p>Cause an invalidate of the specified area to happen on the next animation
971     * time step, typically the next display frame.</p>
972     *
973     * <p>This method can be invoked from outside of the UI thread
974     * only when this View is attached to a window.</p>
975     *
976     * @param view View to invalidate
977     * @param left The left coordinate of the rectangle to invalidate.
978     * @param top The top coordinate of the rectangle to invalidate.
979     * @param right The right coordinate of the rectangle to invalidate.
980     * @param bottom The bottom coordinate of the rectangle to invalidate.
981     */
982    public static void postInvalidateOnAnimation(View view, int left, int top,
983            int right, int bottom) {
984        IMPL.postInvalidateOnAnimation(view, left, top, right, bottom);
985    }
986
987    /**
988     * <p>Causes the Runnable to execute on the next animation time step.
989     * The runnable will be run on the user interface thread.</p>
990     *
991     * <p>This method can be invoked from outside of the UI thread
992     * only when this View is attached to a window.</p>
993     *
994     * @param view View to post this Runnable to
995     * @param action The Runnable that will be executed.
996     */
997    public static void postOnAnimation(View view, Runnable action) {
998        IMPL.postOnAnimation(view, action);
999    }
1000
1001    /**
1002     * <p>Causes the Runnable to execute on the next animation time step,
1003     * after the specified amount of time elapses.
1004     * The runnable will be run on the user interface thread.</p>
1005     *
1006     * <p>This method can be invoked from outside of the UI thread
1007     * only when this View is attached to a window.</p>
1008     *
1009     * @param view The view to post this Runnable to
1010     * @param action The Runnable that will be executed.
1011     * @param delayMillis The delay (in milliseconds) until the Runnable
1012     *        will be executed.
1013     */
1014    public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
1015        IMPL.postOnAnimationDelayed(view, action, delayMillis);
1016    }
1017
1018    /**
1019     * Gets the mode for determining whether this View is important for accessibility
1020     * which is if it fires accessibility events and if it is reported to
1021     * accessibility services that query the screen.
1022     *
1023     * @param view The view whose property to get.
1024     * @return The mode for determining whether a View is important for accessibility.
1025     *
1026     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
1027     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
1028     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
1029     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
1030     */
1031    @ImportantForAccessibility
1032    public static int getImportantForAccessibility(View view) {
1033        return IMPL.getImportantForAccessibility(view);
1034    }
1035
1036    /**
1037     * Sets how to determine whether this view is important for accessibility
1038     * which is if it fires accessibility events and if it is reported to
1039     * accessibility services that query the screen.
1040     * <p>
1041     * <em>Note:</em> If the current paltform version does not support the
1042     *  {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} mode, then
1043     *  {@link #IMPORTANT_FOR_ACCESSIBILITY_NO} will be used as it is the
1044     *  closest terms of semantics.
1045     * </p>
1046     *
1047     * @param view The view whose property to set.
1048     * @param mode How to determine whether this view is important for accessibility.
1049     *
1050     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
1051     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
1052     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
1053     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
1054     */
1055    public static void setImportantForAccessibility(View view,
1056            @ImportantForAccessibility int mode) {
1057        IMPL.setImportantForAccessibility(view, mode);
1058    }
1059
1060    /**
1061     * Performs the specified accessibility action on the view. For
1062     * possible accessibility actions look at {@link AccessibilityNodeInfoCompat}.
1063     * <p>
1064     * If an {@link AccessibilityDelegateCompat} has been specified via calling
1065     * {@link #setAccessibilityDelegate(View, AccessibilityDelegateCompat)} its
1066     * {@link AccessibilityDelegateCompat#performAccessibilityAction(View, int, Bundle)}
1067     * is responsible for handling this call.
1068     * </p>
1069     *
1070     * @param action The action to perform.
1071     * @param arguments Optional action arguments.
1072     * @return Whether the action was performed.
1073     */
1074    public static boolean performAccessibilityAction(View view, int action, Bundle arguments) {
1075        return IMPL.performAccessibilityAction(view, action, arguments);
1076    }
1077
1078    /**
1079     * Gets the provider for managing a virtual view hierarchy rooted at this View
1080     * and reported to {@link android.accessibilityservice.AccessibilityService}s
1081     * that explore the window content.
1082     * <p>
1083     * If this method returns an instance, this instance is responsible for managing
1084     * {@link AccessibilityNodeInfoCompat}s describing the virtual sub-tree rooted at
1085     * this View including the one representing the View itself. Similarly the returned
1086     * instance is responsible for performing accessibility actions on any virtual
1087     * view or the root view itself.
1088     * </p>
1089     * <p>
1090     * If an {@link AccessibilityDelegateCompat} has been specified via calling
1091     * {@link #setAccessibilityDelegate(View, AccessibilityDelegateCompat)} its
1092     * {@link AccessibilityDelegateCompat#getAccessibilityNodeProvider(View)}
1093     * is responsible for handling this call.
1094     * </p>
1095     *
1096     * @param view The view whose property to get.
1097     * @return The provider.
1098     *
1099     * @see AccessibilityNodeProviderCompat
1100     */
1101    public static AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
1102        return IMPL.getAccessibilityNodeProvider(view);
1103    }
1104
1105    /**
1106     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
1107     * completely transparent and 1 means the view is completely opaque.
1108     *
1109     * <p>By default this is 1.0f. Prior to API 11, the returned value is always 1.0f.
1110     * @return The opacity of the view.
1111     */
1112    public static float getAlpha(View view) {
1113        return IMPL.getAlpha(view);
1114    }
1115
1116    /**
1117     * <p>Specifies the type of layer backing this view. The layer can be
1118     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
1119     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
1120     *
1121     * <p>A layer is associated with an optional {@link android.graphics.Paint}
1122     * instance that controls how the layer is composed on screen. The following
1123     * properties of the paint are taken into account when composing the layer:</p>
1124     * <ul>
1125     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
1126     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
1127     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
1128     * </ul>
1129     *
1130     * <p>If this view has an alpha value set to < 1.0 by calling
1131     * setAlpha(float), the alpha value of the layer's paint is replaced by
1132     * this view's alpha value. Calling setAlpha(float) is therefore
1133     * equivalent to setting a hardware layer on this view and providing a paint with
1134     * the desired alpha value.<p>
1135     *
1136     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
1137     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
1138     * for more information on when and how to use layers.</p>
1139     *
1140     * @param layerType The ype of layer to use with this view, must be one of
1141     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
1142     *        {@link #LAYER_TYPE_HARDWARE}
1143     * @param paint The paint used to compose the layer. This argument is optional
1144     *        and can be null. It is ignored when the layer type is
1145     *        {@link #LAYER_TYPE_NONE}
1146     *
1147     * @param view View to set the layer type for
1148     * @param layerType The type of layer to use with this view, must be one of
1149     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
1150     *        {@link #LAYER_TYPE_HARDWARE}
1151     * @param paint The paint used to compose the layer. This argument is optional
1152     *        and can be null. It is ignored when the layer type is
1153     *        {@link #LAYER_TYPE_NONE}
1154     */
1155    public static void setLayerType(View view, @LayerType int layerType, Paint paint) {
1156        IMPL.setLayerType(view, layerType, paint);
1157    }
1158
1159    /**
1160     * Indicates what type of layer is currently associated with this view. By default
1161     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
1162     * Refer to the documentation of
1163     * {@link #setLayerType(android.view.View, int, android.graphics.Paint)}
1164     * for more information on the different types of layers.
1165     *
1166     * @param view The view to fetch the layer type from
1167     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
1168     *         {@link #LAYER_TYPE_HARDWARE}
1169     *
1170     * @see #setLayerType(android.view.View, int, android.graphics.Paint)
1171     * @see #LAYER_TYPE_NONE
1172     * @see #LAYER_TYPE_SOFTWARE
1173     * @see #LAYER_TYPE_HARDWARE
1174     */
1175    @LayerType
1176    public static int getLayerType(View view) {
1177        return IMPL.getLayerType(view);
1178    }
1179
1180    /**
1181     * Gets the id of a view for which a given view serves as a label for
1182     * accessibility purposes.
1183     *
1184     * @param view The view on which to invoke the corresponding method.
1185     * @return The labeled view id.
1186     */
1187    public static int getLabelFor(View view) {
1188        return IMPL.getLabelFor(view);
1189    }
1190
1191    /**
1192     * Sets the id of a view for which a given view serves as a label for
1193     * accessibility purposes.
1194     *
1195     * @param view The view on which to invoke the corresponding method.
1196     * @param labeledId The labeled view id.
1197     */
1198    public static void setLabelFor(View view, @IdRes int labeledId) {
1199        IMPL.setLabelFor(view, labeledId);
1200    }
1201
1202    /**
1203     * Updates the {@link Paint} object used with the current layer (used only if the current
1204     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
1205     * provided to {@link #setLayerType(android.view.View, int, android.graphics.Paint)}
1206     * will be used the next time the View is redrawn, but
1207     * {@link #setLayerPaint(android.view.View, android.graphics.Paint)}
1208     * must be called to ensure that the view gets redrawn immediately.
1209     *
1210     * <p>A layer is associated with an optional {@link android.graphics.Paint}
1211     * instance that controls how the layer is composed on screen. The following
1212     * properties of the paint are taken into account when composing the layer:</p>
1213     * <ul>
1214     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
1215     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
1216     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
1217     * </ul>
1218     *
1219     * <p>If this view has an alpha value set to < 1.0 by calling
1220     * View#setAlpha(float), the alpha value of the layer's paint is replaced by
1221     * this view's alpha value. Calling View#setAlpha(float) is therefore
1222     * equivalent to setting a hardware layer on this view and providing a paint with
1223     * the desired alpha value.</p>
1224     *
1225     * @param view View to set a layer paint for
1226     * @param paint The paint used to compose the layer. This argument is optional
1227     *        and can be null. It is ignored when the layer type is
1228     *        {@link #LAYER_TYPE_NONE}
1229     *
1230     * @see #setLayerType(View, int, android.graphics.Paint)
1231     */
1232    public static void setLayerPaint(View view, Paint paint) {
1233        IMPL.setLayerPaint(view, paint);
1234    }
1235
1236    /**
1237     * Returns the resolved layout direction for this view.
1238     *
1239     * @param view View to get layout direction for
1240     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
1241     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
1242     *
1243     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
1244     * is lower than Jellybean MR1 (API 17)
1245     */
1246    @ResolvedLayoutDirectionMode
1247    public static int getLayoutDirection(View view) {
1248        return IMPL.getLayoutDirection(view);
1249    }
1250
1251    /**
1252     * Set the layout direction for this view. This will propagate a reset of layout direction
1253     * resolution to the view's children and resolve layout direction for this view.
1254     *
1255     * @param view View to set layout direction for
1256     * @param layoutDirection the layout direction to set. Should be one of:
1257     *
1258     * {@link #LAYOUT_DIRECTION_LTR},
1259     * {@link #LAYOUT_DIRECTION_RTL},
1260     * {@link #LAYOUT_DIRECTION_INHERIT},
1261     * {@link #LAYOUT_DIRECTION_LOCALE}.
1262     *
1263     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
1264     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
1265     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
1266     */
1267    public static void setLayoutDirection(View view, @LayoutDirectionMode int layoutDirection) {
1268        IMPL.setLayoutDirection(view, layoutDirection);
1269    }
1270
1271    /**
1272     * Gets the parent for accessibility purposes. Note that the parent for
1273     * accessibility is not necessary the immediate parent. It is the first
1274     * predecessor that is important for accessibility.
1275     *
1276     * @param view View to retrieve parent for
1277     * @return The parent for use in accessibility inspection
1278     */
1279    public static ViewParent getParentForAccessibility(View view) {
1280        return IMPL.getParentForAccessibility(view);
1281    }
1282
1283    /**
1284     * Indicates whether this View is opaque. An opaque View guarantees that it will
1285     * draw all the pixels overlapping its bounds using a fully opaque color.
1286     *
1287     * On API 7 and above this will call View's true isOpaque method. On previous platform
1288     * versions it will check the opacity of the view's background drawable if present.
1289     *
1290     * @return True if this View is guaranteed to be fully opaque, false otherwise.
1291     */
1292    public static boolean isOpaque(View view) {
1293        return IMPL.isOpaque(view);
1294    }
1295
1296    /**
1297     * Utility to reconcile a desired size and state, with constraints imposed
1298     * by a MeasureSpec.  Will take the desired size, unless a different size
1299     * is imposed by the constraints.  The returned value is a compound integer,
1300     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
1301     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
1302     * size is smaller than the size the view wants to be.
1303     *
1304     * @param size How big the view wants to be
1305     * @param measureSpec Constraints imposed by the parent
1306     * @return Size information bit mask as defined by
1307     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
1308     */
1309    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
1310        return IMPL.resolveSizeAndState(size, measureSpec, childMeasuredState);
1311    }
1312
1313    /**
1314     * Return the full width measurement information for this view as computed
1315     * by the most recent call to {@link android.view.View#measure(int, int)}.
1316     * This result is a bit mask as defined by {@link #MEASURED_SIZE_MASK} and
1317     * {@link #MEASURED_STATE_TOO_SMALL}.
1318     * This should be used during measurement and layout calculations only. Use
1319     * {@link android.view.View#getWidth()} to see how wide a view is after layout.
1320     *
1321     * @return The measured width of this view as a bit mask.
1322     */
1323    public static int getMeasuredWidthAndState(View view) {
1324        return IMPL.getMeasuredWidthAndState(view);
1325    }
1326
1327    /**
1328     * Return the full height measurement information for this view as computed
1329     * by the most recent call to {@link android.view.View#measure(int, int)}.
1330     * This result is a bit mask as defined by {@link #MEASURED_SIZE_MASK} and
1331     * {@link #MEASURED_STATE_TOO_SMALL}.
1332     * This should be used during measurement and layout calculations only. Use
1333     * {@link android.view.View#getHeight()} to see how wide a view is after layout.
1334     *
1335     * @return The measured width of this view as a bit mask.
1336     */
1337    public static int getMeasuredHeightAndState(View view) {
1338        return IMPL.getMeasuredHeightAndState(view);
1339    }
1340
1341    /**
1342     * Return only the state bits of {@link #getMeasuredWidthAndState}
1343     * and {@link #getMeasuredHeightAndState}, combined into one integer.
1344     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
1345     * and the height component is at the shifted bits
1346     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
1347     */
1348    public static int getMeasuredState(View view) {
1349        return IMPL.getMeasuredState(view);
1350    }
1351
1352    /**
1353     * Gets the live region mode for the specified View.
1354     *
1355     * @param view The view from which to obtain the live region mode
1356     * @return The live region mode for the view.
1357     *
1358     * @see ViewCompat#setAccessibilityLiveRegion(View, int)
1359     */
1360    @AccessibilityLiveRegion
1361    public static int getAccessibilityLiveRegion(View view) {
1362        return IMPL.getAccessibilityLiveRegion(view);
1363    }
1364
1365    /**
1366     * Sets the live region mode for the specified view. This indicates to
1367     * accessibility services whether they should automatically notify the user
1368     * about changes to the view's content description or text, or to the
1369     * content descriptions or text of the view's children (where applicable).
1370     * <p>
1371     * For example, in a login screen with a TextView that displays an "incorrect
1372     * password" notification, that view should be marked as a live region with
1373     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
1374     * <p>
1375     * To disable change notifications for this view, use
1376     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
1377     * mode for most views.
1378     * <p>
1379     * To indicate that the user should be notified of changes, use
1380     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
1381     * <p>
1382     * If the view's changes should interrupt ongoing speech and notify the user
1383     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
1384     *
1385     * @param view The view on which to set the live region mode
1386     * @param mode The live region mode for this view, one of:
1387     *        <ul>
1388     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
1389     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
1390     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
1391     *        </ul>
1392     */
1393    public static void setAccessibilityLiveRegion(View view, @AccessibilityLiveRegion int mode) {
1394        IMPL.setAccessibilityLiveRegion(view, mode);
1395    }
1396
1397    /**
1398     * Returns the start padding of the specified view depending on its resolved layout direction.
1399     * If there are inset and enabled scrollbars, this value may include the space
1400     * required to display the scrollbars as well.
1401     *
1402     * @param view The view to get padding for
1403     * @return the start padding in pixels
1404     */
1405    public static int getPaddingStart(View view) {
1406        return IMPL.getPaddingStart(view);
1407    }
1408
1409    /**
1410     * Returns the end padding of the specified view depending on its resolved layout direction.
1411     * If there are inset and enabled scrollbars, this value may include the space
1412     * required to display the scrollbars as well.
1413     *
1414     * @param view The view to get padding for
1415     * @return the end padding in pixels
1416     */
1417    public static int getPaddingEnd(View view) {
1418        return IMPL.getPaddingEnd(view);
1419    }
1420
1421    /**
1422     * Sets the relative padding. The view may add on the space required to display
1423     * the scrollbars, depending on the style and visibility of the scrollbars.
1424     * So the values returned from {@link #getPaddingStart}, {@link View#getPaddingTop},
1425     * {@link #getPaddingEnd} and {@link View#getPaddingBottom} may be different
1426     * from the values set in this call.
1427     *
1428     * @param view The view on which to set relative padding
1429     * @param start the start padding in pixels
1430     * @param top the top padding in pixels
1431     * @param end the end padding in pixels
1432     * @param bottom the bottom padding in pixels
1433     */
1434    public static void setPaddingRelative(View view, int start, int top, int end, int bottom) {
1435        IMPL.setPaddingRelative(view, start, top, end, bottom);
1436    }
1437
1438    /**
1439     * Notify a view that it is being temporarily detached.
1440     */
1441    public static void dispatchStartTemporaryDetach(View view) {
1442        IMPL.dispatchStartTemporaryDetach(view);
1443    }
1444
1445    /**
1446     * Notify a view that its temporary detach has ended; the view is now reattached.
1447     */
1448    public static void dispatchFinishTemporaryDetach(View view) {
1449        IMPL.dispatchFinishTemporaryDetach(view);
1450    }
1451
1452    /**
1453     * The horizontal location of this view relative to its {@link View#getLeft() left} position.
1454     * This position is post-layout, in addition to wherever the object's
1455     * layout placed it.
1456     *
1457     * @return The horizontal position of this view relative to its left position, in pixels.
1458     */
1459    public static float getTranslationX(View view) {
1460        return IMPL.getTranslationX(view);
1461    }
1462
1463    /**
1464     * The vertical location of this view relative to its {@link View#getTop() left} position.
1465     * This position is post-layout, in addition to wherever the object's
1466     * layout placed it.
1467     *
1468     * @return The vertical position of this view relative to its top position, in pixels.
1469     */
1470    public static float getTranslationY(View view) {
1471        return IMPL.getTranslationY(view);
1472    }
1473
1474    /**
1475     * Returns the minimum width of the view.
1476     *
1477     * <p>Prior to API 16 this will return 0.</p>
1478     *
1479     * @return the minimum width the view will try to be.
1480     */
1481    public static int getMinimumWidth(View view) {
1482        return IMPL.getMinimumWidth(view);
1483    }
1484
1485    /**
1486     * Returns the minimum height of the view.
1487     *
1488     * <p>Prior to API 16 this will return 0.</p>
1489     *
1490     * @return the minimum height the view will try to be.
1491     */
1492    public static int getMinimumHeight(View view) {
1493        return IMPL.getMinimumHeight(view);
1494    }
1495}
1496