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.Rect;
21import android.os.Bundle;
22import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
23import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
24import android.view.View;
25import android.view.ViewParent;
26import android.view.accessibility.AccessibilityEvent;
27
28/**
29 * Helper for accessing features in {@link View} introduced after API
30 * level 4 in a backwards compatible fashion.
31 */
32public class ViewCompat {
33    /**
34     * Always allow a user to over-scroll this view, provided it is a
35     * view that can scroll.
36     */
37    public static final int OVER_SCROLL_ALWAYS = 0;
38
39    /**
40     * Allow a user to over-scroll this view only if the content is large
41     * enough to meaningfully scroll, provided it is a view that can scroll.
42     */
43    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
44
45    /**
46     * Never allow a user to over-scroll this view.
47     */
48    public static final int OVER_SCROLL_NEVER = 2;
49
50    private static final long FAKE_FRAME_TIME = 10;
51
52    /**
53     * Automatically determine whether a view is important for accessibility.
54     */
55    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
56
57    /**
58     * The view is important for accessibility.
59     */
60    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
61
62    /**
63     * The view is not important for accessibility.
64     */
65    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
66
67    /**
68     * Indicates that the view does not have a layer.
69     */
70    public static final int LAYER_TYPE_NONE = 0;
71
72    /**
73     * <p>Indicates that the view has a software layer. A software layer is backed
74     * by a bitmap and causes the view to be rendered using Android's software
75     * rendering pipeline, even if hardware acceleration is enabled.</p>
76     *
77     * <p>Software layers have various usages:</p>
78     * <p>When the application is not using hardware acceleration, a software layer
79     * is useful to apply a specific color filter and/or blending mode and/or
80     * translucency to a view and all its children.</p>
81     * <p>When the application is using hardware acceleration, a software layer
82     * is useful to render drawing primitives not supported by the hardware
83     * accelerated pipeline. It can also be used to cache a complex view tree
84     * into a texture and reduce the complexity of drawing operations. For instance,
85     * when animating a complex view tree with a translation, a software layer can
86     * be used to render the view tree only once.</p>
87     * <p>Software layers should be avoided when the affected view tree updates
88     * often. Every update will require to re-render the software layer, which can
89     * potentially be slow (particularly when hardware acceleration is turned on
90     * since the layer will have to be uploaded into a hardware texture after every
91     * update.)</p>
92     */
93    public static final int LAYER_TYPE_SOFTWARE = 1;
94
95    /**
96     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
97     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
98     * OpenGL hardware) and causes the view to be rendered using Android's hardware
99     * rendering pipeline, but only if hardware acceleration is turned on for the
100     * view hierarchy. When hardware acceleration is turned off, hardware layers
101     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
102     *
103     * <p>A hardware layer is useful to apply a specific color filter and/or
104     * blending mode and/or translucency to a view and all its children.</p>
105     * <p>A hardware layer can be used to cache a complex view tree into a
106     * texture and reduce the complexity of drawing operations. For instance,
107     * when animating a complex view tree with a translation, a hardware layer can
108     * be used to render the view tree only once.</p>
109     * <p>A hardware layer can also be used to increase the rendering quality when
110     * rotation transformations are applied on a view. It can also be used to
111     * prevent potential clipping issues when applying 3D transforms on a view.</p>
112     */
113    public static final int LAYER_TYPE_HARDWARE = 2;
114
115    /**
116     * Horizontal layout direction of this view is from Left to Right.
117     */
118    public static final int LAYOUT_DIRECTION_LTR = 0;
119
120    /**
121     * Horizontal layout direction of this view is from Right to Left.
122     */
123    public static final int LAYOUT_DIRECTION_RTL = 1;
124
125    /**
126     * Horizontal layout direction of this view is inherited from its parent.
127     * Use with {@link #setLayoutDirection}.
128     */
129    public static final int LAYOUT_DIRECTION_INHERIT = 2;
130
131    /**
132     * Horizontal layout direction of this view is from deduced from the default language
133     * script for the locale. Use with {@link #setLayoutDirection}.
134     */
135    public static final int LAYOUT_DIRECTION_LOCALE = 3;
136
137    interface ViewCompatImpl {
138        public boolean canScrollHorizontally(View v, int direction);
139        public boolean canScrollVertically(View v, int direction);
140        public int getOverScrollMode(View v);
141        public void setOverScrollMode(View v, int mode);
142        public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event);
143        public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event);
144        public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info);
145        public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate);
146        public boolean hasTransientState(View view);
147        public void setHasTransientState(View view, boolean hasTransientState);
148        public void postInvalidateOnAnimation(View view);
149        public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom);
150        public void postOnAnimation(View view, Runnable action);
151        public void postOnAnimationDelayed(View view, Runnable action, long delayMillis);
152        public int getImportantForAccessibility(View view);
153        public void setImportantForAccessibility(View view, int mode);
154        public boolean performAccessibilityAction(View view, int action, Bundle arguments);
155        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view);
156        public void setLayerType(View view, int layerType, Paint paint);
157        public int getLayerType(View view);
158        public int getLabelFor(View view);
159        public void setLabelFor(View view, int id);
160        public void setLayerPaint(View view, Paint paint);
161        public int getLayoutDirection(View view);
162        public void setLayoutDirection(View view, int layoutDirection);
163        public ViewParent getParentForAccessibility(View view);
164    }
165
166    static class BaseViewCompatImpl implements ViewCompatImpl {
167        public boolean canScrollHorizontally(View v, int direction) {
168            return false;
169        }
170        public boolean canScrollVertically(View v, int direction) {
171            return false;
172        }
173        public int getOverScrollMode(View v) {
174            return OVER_SCROLL_NEVER;
175        }
176        public void setOverScrollMode(View v, int mode) {
177            // Do nothing; API doesn't exist
178        }
179        public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) {
180            // Do nothing; API doesn't exist
181        }
182        public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {
183            // Do nothing; API doesn't exist
184        }
185        public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {
186         // Do nothing; API doesn't exist
187        }
188        public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
189            // Do nothing; API doesn't exist
190        }
191        public boolean hasTransientState(View view) {
192            // A view can't have transient state if transient state wasn't supported.
193            return false;
194        }
195        public void setHasTransientState(View view, boolean hasTransientState) {
196            // Do nothing; API doesn't exist
197        }
198        public void postInvalidateOnAnimation(View view) {
199            view.postInvalidateDelayed(getFrameTime());
200        }
201        public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) {
202            view.postInvalidateDelayed(getFrameTime(), left, top, right, bottom);
203        }
204        public void postOnAnimation(View view, Runnable action) {
205            view.postDelayed(action, getFrameTime());
206        }
207        public void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
208            view.postDelayed(action, getFrameTime() + delayMillis);
209        }
210        long getFrameTime() {
211            return FAKE_FRAME_TIME;
212        }
213        public int getImportantForAccessibility(View view) {
214            return 0;
215        }
216        public void setImportantForAccessibility(View view, int mode) {
217
218        }
219        public boolean performAccessibilityAction(View view, int action, Bundle arguments) {
220            return false;
221        }
222        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
223            return null;
224        }
225        public void setLayerType(View view, int layerType, Paint paint) {
226            // No-op until layers became available (HC)
227        }
228        public int getLayerType(View view) {
229            return LAYER_TYPE_NONE;
230        }
231        public int getLabelFor(View view) {
232            return 0;
233        }
234        public void setLabelFor(View view, int id) {
235
236        }
237        public void setLayerPaint(View view, Paint p) {
238            // No-op until layers became available (HC)
239        }
240
241        @Override
242        public int getLayoutDirection(View view) {
243            return LAYOUT_DIRECTION_LTR;
244        }
245
246        @Override
247        public void setLayoutDirection(View view, int layoutDirection) {
248            // No-op
249        }
250
251        @Override
252        public ViewParent getParentForAccessibility(View view) {
253            return view.getParent();
254        }
255    }
256
257    static class GBViewCompatImpl extends BaseViewCompatImpl {
258        @Override
259        public int getOverScrollMode(View v) {
260            return ViewCompatGingerbread.getOverScrollMode(v);
261        }
262        @Override
263        public void setOverScrollMode(View v, int mode) {
264            ViewCompatGingerbread.setOverScrollMode(v, mode);
265        }
266    }
267
268    static class HCViewCompatImpl extends GBViewCompatImpl {
269        long getFrameTime() {
270            return ViewCompatHC.getFrameTime();
271        }
272        @Override public void setLayerType(View view, int layerType, Paint paint) {
273            ViewCompatHC.setLayerType(view, layerType, paint);
274        }
275        @Override public int getLayerType(View view)  {
276            return ViewCompatHC.getLayerType(view);
277        }
278        @Override
279        public void setLayerPaint(View view, Paint paint) {
280            // Make sure the paint is correct; this will be cheap if it's the same
281            // instance as was used to call setLayerType earlier.
282            setLayerType(view, getLayerType(view), paint);
283            // This is expensive, but the only way to accomplish this before JB-MR1.
284            view.invalidate();
285        }
286    }
287
288    static class ICSViewCompatImpl extends HCViewCompatImpl {
289        @Override
290        public boolean canScrollHorizontally(View v, int direction) {
291            return ViewCompatICS.canScrollHorizontally(v, direction);
292        }
293        @Override
294        public boolean canScrollVertically(View v, int direction) {
295            return ViewCompatICS.canScrollVertically(v, direction);
296        }
297        @Override
298        public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {
299            ViewCompatICS.onPopulateAccessibilityEvent(v, event);
300        }
301        @Override
302        public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {
303            ViewCompatICS.onInitializeAccessibilityEvent(v, event);
304        }
305        @Override
306        public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
307            ViewCompatICS.onInitializeAccessibilityNodeInfo(v, info.getInfo());
308        }
309        @Override
310        public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) {
311            ViewCompatICS.setAccessibilityDelegate(v, delegate.getBridge());
312        }
313    }
314
315    static class JBViewCompatImpl extends ICSViewCompatImpl {
316        @Override
317        public boolean hasTransientState(View view) {
318            return ViewCompatJB.hasTransientState(view);
319        }
320        @Override
321        public void setHasTransientState(View view, boolean hasTransientState) {
322            ViewCompatJB.setHasTransientState(view, hasTransientState);
323        }
324        @Override
325        public void postInvalidateOnAnimation(View view) {
326            ViewCompatJB.postInvalidateOnAnimation(view);
327        }
328        @Override
329        public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) {
330            ViewCompatJB.postInvalidateOnAnimation(view, left, top, right, bottom);
331        }
332        @Override
333        public void postOnAnimation(View view, Runnable action) {
334            ViewCompatJB.postOnAnimation(view, action);
335        }
336        @Override
337        public void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
338            ViewCompatJB.postOnAnimationDelayed(view, action, delayMillis);
339        }
340        @Override
341        public int getImportantForAccessibility(View view) {
342            return ViewCompatJB.getImportantForAccessibility(view);
343        }
344        @Override
345        public void setImportantForAccessibility(View view, int mode) {
346            ViewCompatJB.setImportantForAccessibility(view, mode);
347        }
348        @Override
349        public boolean performAccessibilityAction(View view, int action, Bundle arguments) {
350            return ViewCompatJB.performAccessibilityAction(view, action, arguments);
351        }
352        @Override
353        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
354            Object compat = ViewCompatJB.getAccessibilityNodeProvider(view);
355            if (compat != null) {
356                return new AccessibilityNodeProviderCompat(compat);
357            }
358            return null;
359        }
360
361        @Override
362        public ViewParent getParentForAccessibility(View view) {
363            return ViewCompatJB.getParentForAccessibility(view);
364        }
365    }
366
367    static class JbMr1ViewCompatImpl extends JBViewCompatImpl {
368
369        @Override
370        public int getLabelFor(View view) {
371            return ViewCompatJellybeanMr1.getLabelFor(view);
372        }
373
374        @Override
375        public void setLabelFor(View view, int id) {
376            ViewCompatJellybeanMr1.setLabelFor(view, id);
377        }
378
379        @Override
380        public void setLayerPaint(View view, Paint paint) {
381            ViewCompatJellybeanMr1.setLayerPaint(view, paint);
382        }
383
384        @Override
385        public int getLayoutDirection(View view) {
386            return ViewCompatJellybeanMr1.getLayoutDirection(view);
387        }
388
389        @Override
390        public void setLayoutDirection(View view, int layoutDirection) {
391            ViewCompatJellybeanMr1.setLayoutDirection(view, layoutDirection);
392        }
393    }
394
395    static final ViewCompatImpl IMPL;
396    static {
397        final int version = android.os.Build.VERSION.SDK_INT;
398        if (version >= 17) {
399            IMPL = new JbMr1ViewCompatImpl();
400        } else if (version >= 16) {
401            IMPL = new JBViewCompatImpl();
402        } else if (version >= 14) {
403            IMPL = new ICSViewCompatImpl();
404        } else if (version >= 11) {
405            IMPL = new HCViewCompatImpl();
406        } else if (version >= 9) {
407            IMPL = new GBViewCompatImpl();
408        } else {
409            IMPL = new BaseViewCompatImpl();
410        }
411    }
412
413    /**
414     * Check if this view can be scrolled horizontally in a certain direction.
415     *
416     * @param v The View against which to invoke the method.
417     * @param direction Negative to check scrolling left, positive to check scrolling right.
418     * @return true if this view can be scrolled in the specified direction, false otherwise.
419     */
420    public static boolean canScrollHorizontally(View v, int direction) {
421        return IMPL.canScrollHorizontally(v, direction);
422    }
423
424    /**
425     * Check if this view can be scrolled vertically in a certain direction.
426     *
427     * @param v The View against which to invoke the method.
428     * @param direction Negative to check scrolling up, positive to check scrolling down.
429     * @return true if this view can be scrolled in the specified direction, false otherwise.
430     */
431    public static boolean canScrollVertically(View v, int direction) {
432        return IMPL.canScrollVertically(v, direction);
433    }
434
435    /**
436     * Returns the over-scroll mode for this view. The result will be
437     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
438     * (allow over-scrolling only if the view content is larger than the container),
439     * or {@link #OVER_SCROLL_NEVER}.
440     *
441     * @param v The View against which to invoke the method.
442     * @return This view's over-scroll mode.
443     */
444    public static int getOverScrollMode(View v) {
445        return IMPL.getOverScrollMode(v);
446    }
447
448    /**
449     * Set the over-scroll mode for this view. Valid over-scroll modes are
450     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
451     * (allow over-scrolling only if the view content is larger than the container),
452     * or {@link #OVER_SCROLL_NEVER}.
453     *
454     * Setting the over-scroll mode of a view will have an effect only if the
455     * view is capable of scrolling.
456     *
457     * @param v The View against which to invoke the method.
458     * @param overScrollMode The new over-scroll mode for this view.
459     */
460    public static void setOverScrollMode(View v, int overScrollMode) {
461        IMPL.setOverScrollMode(v, overScrollMode);
462    }
463
464    /**
465     * Called from {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
466     * giving a chance to this View to populate the accessibility event with its
467     * text content. While this method is free to modify event
468     * attributes other than text content, doing so should normally be performed in
469     * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)}.
470     * <p>
471     * Example: Adding formatted date string to an accessibility event in addition
472     *          to the text added by the super implementation:
473     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
474     *     super.onPopulateAccessibilityEvent(event);
475     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
476     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
477     *         mCurrentDate.getTimeInMillis(), flags);
478     *     event.getText().add(selectedDateUtterance);
479     * }</pre>
480     * <p>
481     * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling
482     * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its
483     * {@link android.view.View.AccessibilityDelegate#onPopulateAccessibilityEvent(View,
484     *  AccessibilityEvent)}
485     * is responsible for handling this call.
486     * </p>
487     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
488     * information to the event, in case the default implementation has basic information to add.
489     * </p>
490     *
491     * @param v The View against which to invoke the method.
492     * @param event The accessibility event which to populate.
493     *
494     * @see View#sendAccessibilityEvent(int)
495     * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
496     */
497    public static void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {
498        IMPL.onPopulateAccessibilityEvent(v, event);
499    }
500
501    /**
502     * Initializes an {@link AccessibilityEvent} with information about
503     * this View which is the event source. In other words, the source of
504     * an accessibility event is the view whose state change triggered firing
505     * the event.
506     * <p>
507     * Example: Setting the password property of an event in addition
508     *          to properties set by the super implementation:
509     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
510     *     super.onInitializeAccessibilityEvent(event);
511     *     event.setPassword(true);
512     * }</pre>
513     * <p>
514     * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling
515     * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its
516     * {@link android.view.View.AccessibilityDelegate#onInitializeAccessibilityEvent(View,
517     *  AccessibilityEvent)}
518     * is responsible for handling this call.
519     * </p>
520     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
521     * information to the event, in case the default implementation has basic information to add.
522     * </p>
523     *
524     * @param v The View against which to invoke the method.
525     * @param event The event to initialize.
526     *
527     * @see View#sendAccessibilityEvent(int)
528     * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
529     */
530    public static void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {
531        IMPL.onInitializeAccessibilityEvent(v, event);
532    }
533
534    /**
535     * Initializes an {@link android.view.accessibility.AccessibilityNodeInfo} with information
536     * about this view. The base implementation sets:
537     * <ul>
538     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setParent(View)},</li>
539     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
540     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
541     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
542     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setClassName(CharSequence)},</li>
543     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
544     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setEnabled(boolean)},</li>
545     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setClickable(boolean)},</li>
546     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setFocusable(boolean)},</li>
547     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setFocused(boolean)},</li>
548     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setLongClickable(boolean)},</li>
549     * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setSelected(boolean)},</li>
550     * </ul>
551     * <p>
552     * Subclasses should override this method, call the super implementation,
553     * and set additional attributes.
554     * </p>
555     * <p>
556     * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling
557     * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its
558     * {@link android.view.View.AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View,
559     *  android.view.accessibility.AccessibilityNodeInfo)}
560     * is responsible for handling this call.
561     * </p>
562     *
563     * @param v The View against which to invoke the method.
564     * @param info The instance to initialize.
565     */
566    public static void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
567        IMPL.onInitializeAccessibilityNodeInfo(v, info);
568    }
569
570    /**
571     * Sets a delegate for implementing accessibility support via compositon as
572     * opposed to inheritance. The delegate's primary use is for implementing
573     * backwards compatible widgets. For more details see
574     * {@link android.view.View.AccessibilityDelegate}.
575     *
576     * @param v The View against which to invoke the method.
577     * @param delegate The delegate instance.
578     *
579     * @see android.view.View.AccessibilityDelegate
580     */
581    public static void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) {
582        IMPL.setAccessibilityDelegate(v, delegate);
583    }
584
585    /**
586     * Indicates whether the view is currently tracking transient state that the
587     * app should not need to concern itself with saving and restoring, but that
588     * the framework should take special note to preserve when possible.
589     *
590     * @param view View to check for transient state
591     * @return true if the view has transient state
592     */
593    public static boolean hasTransientState(View view) {
594        return IMPL.hasTransientState(view);
595    }
596
597    /**
598     * Set whether this view is currently tracking transient state that the
599     * framework should attempt to preserve when possible.
600     *
601     * @param view View tracking transient state
602     * @param hasTransientState true if this view has transient state
603     */
604    public static void setHasTransientState(View view, boolean hasTransientState) {
605        IMPL.setHasTransientState(view, hasTransientState);
606    }
607
608    /**
609     * <p>Cause an invalidate to happen on the next animation time step, typically the
610     * next display frame.</p>
611     *
612     * <p>This method can be invoked from outside of the UI thread
613     * only when this View is attached to a window.</p>
614     *
615     * @param view View to invalidate
616     */
617    public static void postInvalidateOnAnimation(View view) {
618        IMPL.postInvalidateOnAnimation(view);
619    }
620
621    /**
622     * <p>Cause an invalidate of the specified area to happen on the next animation
623     * time step, typically the next display frame.</p>
624     *
625     * <p>This method can be invoked from outside of the UI thread
626     * only when this View is attached to a window.</p>
627     *
628     * @param view View to invalidate
629     * @param left The left coordinate of the rectangle to invalidate.
630     * @param top The top coordinate of the rectangle to invalidate.
631     * @param right The right coordinate of the rectangle to invalidate.
632     * @param bottom The bottom coordinate of the rectangle to invalidate.
633     */
634    public static void postInvalidateOnAnimation(View view, int left, int top,
635            int right, int bottom) {
636        IMPL.postInvalidateOnAnimation(view, left, top, right, bottom);
637    }
638
639    /**
640     * <p>Causes the Runnable to execute on the next animation time step.
641     * The runnable will be run on the user interface thread.</p>
642     *
643     * <p>This method can be invoked from outside of the UI thread
644     * only when this View is attached to a window.</p>
645     *
646     * @param view View to post this Runnable to
647     * @param action The Runnable that will be executed.
648     */
649    public static void postOnAnimation(View view, Runnable action) {
650        IMPL.postOnAnimation(view, action);
651    }
652
653    /**
654     * <p>Causes the Runnable to execute on the next animation time step,
655     * after the specified amount of time elapses.
656     * The runnable will be run on the user interface thread.</p>
657     *
658     * <p>This method can be invoked from outside of the UI thread
659     * only when this View is attached to a window.</p>
660     *
661     * @param view The view to post this Runnable to
662     * @param action The Runnable that will be executed.
663     * @param delayMillis The delay (in milliseconds) until the Runnable
664     *        will be executed.
665     */
666    public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
667        IMPL.postOnAnimationDelayed(view, action, delayMillis);
668    }
669
670    /**
671     * Gets the mode for determining whether this View is important for accessibility
672     * which is if it fires accessibility events and if it is reported to
673     * accessibility services that query the screen.
674     *
675     * @param view The view whose property to get.
676     * @return The mode for determining whether a View is important for accessibility.
677     *
678     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
679     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
680     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
681     */
682    public static int getImportantForAccessibility(View view) {
683        return IMPL.getImportantForAccessibility(view);
684    }
685
686    /**
687     * Sets how to determine whether this view is important for accessibility
688     * which is if it fires accessibility events and if it is reported to
689     * accessibility services that query the screen.
690     *
691     * @param view The view whose property to set.
692     * @param mode How to determine whether this view is important for accessibility.
693     *
694     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
695     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
696     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
697     */
698    public static void setImportantForAccessibility(View view, int mode) {
699        IMPL.setImportantForAccessibility(view, mode);
700    }
701
702    /**
703     * Performs the specified accessibility action on the view. For
704     * possible accessibility actions look at {@link AccessibilityNodeInfoCompat}.
705     * <p>
706     * If an {@link AccessibilityDelegateCompat} has been specified via calling
707     * {@link #setAccessibilityDelegate(View, AccessibilityDelegateCompat)} its
708     * {@link AccessibilityDelegateCompat#performAccessibilityAction(View, int, Bundle)}
709     * is responsible for handling this call.
710     * </p>
711     *
712     * @param action The action to perform.
713     * @param arguments Optional action arguments.
714     * @return Whether the action was performed.
715     */
716    public static boolean performAccessibilityAction(View view, int action, Bundle arguments) {
717        return IMPL.performAccessibilityAction(view, action, arguments);
718    }
719
720    /**
721     * Gets the provider for managing a virtual view hierarchy rooted at this View
722     * and reported to {@link android.accessibilityservice.AccessibilityService}s
723     * that explore the window content.
724     * <p>
725     * If this method returns an instance, this instance is responsible for managing
726     * {@link AccessibilityNodeInfoCompat}s describing the virtual sub-tree rooted at
727     * this View including the one representing the View itself. Similarly the returned
728     * instance is responsible for performing accessibility actions on any virtual
729     * view or the root view itself.
730     * </p>
731     * <p>
732     * If an {@link AccessibilityDelegateCompat} has been specified via calling
733     * {@link #setAccessibilityDelegate(View, AccessibilityDelegateCompat) its
734     * {@link AccessibilityDelegateCompat#getAccessibilityNodeProvider(View)}
735     * is responsible for handling this call.
736     * </p>
737     *
738     * @param view The view whose property to get.
739     * @return The provider.
740     *
741     * @see AccessibilityNodeProviderCompat
742     */
743    public static AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) {
744        return IMPL.getAccessibilityNodeProvider(view);
745    }
746
747    /**
748     * <p>Specifies the type of layer backing this view. The layer can be
749     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
750     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
751     *
752     * <p>A layer is associated with an optional {@link android.graphics.Paint}
753     * instance that controls how the layer is composed on screen. The following
754     * properties of the paint are taken into account when composing the layer:</p>
755     * <ul>
756     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
757     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
758     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
759     * </ul>
760     *
761     * <p>If this view has an alpha value set to < 1.0 by calling
762     * setAlpha(float), the alpha value of the layer's paint is replaced by
763     * this view's alpha value. Calling setAlpha(float) is therefore
764     * equivalent to setting a hardware layer on this view and providing a paint with
765     * the desired alpha value.<p>
766     *
767     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
768     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
769     * for more information on when and how to use layers.</p>
770     *
771     * @param layerType The ype of layer to use with this view, must be one of
772     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
773     *        {@link #LAYER_TYPE_HARDWARE}
774     * @param paint The paint used to compose the layer. This argument is optional
775     *        and can be null. It is ignored when the layer type is
776     *        {@link #LAYER_TYPE_NONE}
777     *
778     * @param view View to set the layer type for
779     * @param layerType The type of layer to use with this view, must be one of
780     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
781     *        {@link #LAYER_TYPE_HARDWARE}
782     * @param paint The paint used to compose the layer. This argument is optional
783     *        and can be null. It is ignored when the layer type is
784     *        {@link #LAYER_TYPE_NONE}
785     */
786    public static void setLayerType(View view, int layerType, Paint paint) {
787        IMPL.setLayerType(view, layerType, paint);
788    }
789
790    /**
791     * Indicates what type of layer is currently associated with this view. By default
792     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
793     * Refer to the documentation of
794     * {@link #setLayerType(android.view.View, int, android.graphics.Paint)}
795     * for more information on the different types of layers.
796     *
797     * @param view The view to fetch the layer type from
798     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
799     *         {@link #LAYER_TYPE_HARDWARE}
800     *
801     * @see #setLayerType(android.view.View, int, android.graphics.Paint)
802     * @see #LAYER_TYPE_NONE
803     * @see #LAYER_TYPE_SOFTWARE
804     * @see #LAYER_TYPE_HARDWARE
805     */
806    public static int getLayerType(View view) {
807        return IMPL.getLayerType(view);
808    }
809
810    /**
811     * Gets the id of a view for which a given view serves as a label for
812     * accessibility purposes.
813     *
814     * @param view The view on which to invoke the corresponding method.
815     * @return The labeled view id.
816     */
817    public static int getLabelFor(View view) {
818        return IMPL.getLabelFor(view);
819    }
820
821    /**
822     * Sets the id of a view for which a given view serves as a label for
823     * accessibility purposes.
824     *
825     * @param view The view on which to invoke the corresponding method.
826     * @param labeledId The labeled view id.
827     */
828    public static void setLabelFor(View view, int labeledId) {
829        IMPL.setLabelFor(view, labeledId);
830    }
831
832    /**
833     * Updates the {@link Paint} object used with the current layer (used only if the current
834     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
835     * provided to {@link #setLayerType(android.view.View, int, android.graphics.Paint)}
836     * will be used the next time the View is redrawn, but
837     * {@link #setLayerPaint(android.view.View, android.graphics.Paint)}
838     * must be called to ensure that the view gets redrawn immediately.
839     *
840     * <p>A layer is associated with an optional {@link android.graphics.Paint}
841     * instance that controls how the layer is composed on screen. The following
842     * properties of the paint are taken into account when composing the layer:</p>
843     * <ul>
844     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
845     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
846     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
847     * </ul>
848     *
849     * <p>If this view has an alpha value set to < 1.0 by calling
850     * View#setAlpha(float), the alpha value of the layer's paint is replaced by
851     * this view's alpha value. Calling View#setAlpha(float) is therefore
852     * equivalent to setting a hardware layer on this view and providing a paint with
853     * the desired alpha value.</p>
854     *
855     * @param view View to set a layer paint for
856     * @param paint The paint used to compose the layer. This argument is optional
857     *        and can be null. It is ignored when the layer type is
858     *        {@link #LAYER_TYPE_NONE}
859     *
860     * @see #setLayerType(View, int, android.graphics.Paint)
861     */
862    public static void setLayerPaint(View view, Paint paint) {
863        IMPL.setLayerPaint(view, paint);
864    }
865
866    /**
867     * Returns the resolved layout direction for this view.
868     *
869     * @param view View to get layout direction for
870     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
871     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
872     *
873     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
874     * is lower than Jellybean MR1 (API 17)
875     */
876    public static int getLayoutDirection(View view) {
877        return IMPL.getLayoutDirection(view);
878    }
879
880    /**
881     * Set the layout direction for this view. This will propagate a reset of layout direction
882     * resolution to the view's children and resolve layout direction for this view.
883     *
884     * @param view View to set layout direction for
885     * @param layoutDirection the layout direction to set. Should be one of:
886     *
887     * {@link #LAYOUT_DIRECTION_LTR},
888     * {@link #LAYOUT_DIRECTION_RTL},
889     * {@link #LAYOUT_DIRECTION_INHERIT},
890     * {@link #LAYOUT_DIRECTION_LOCALE}.
891     *
892     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
893     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
894     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
895     */
896    public static void setLayoutDirection(View view, int layoutDirection) {
897        IMPL.setLayoutDirection(view, layoutDirection);
898    }
899
900    /**
901     * Gets the parent for accessibility purposes. Note that the parent for
902     * accessibility is not necessary the immediate parent. It is the first
903     * predecessor that is important for accessibility.
904     *
905     * @param view View to retrieve parent for
906     * @return The parent for use in accessibility inspection
907     */
908    public static ViewParent getParentForAccessibility(View view) {
909        return IMPL.getParentForAccessibility(view);
910    }
911}
912