/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.support.v4.view; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.IdRes; import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.accessibility.AccessibilityEvent; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.WeakHashMap; /** * Helper for accessing features in {@link View} introduced after API * level 4 in a backwards compatible fashion. */ public class ViewCompat { private static final String TAG = "ViewCompat"; /** @hide */ @IntDef({OVER_SCROLL_ALWAYS, OVER_SCROLL_IF_CONTENT_SCROLLS, OVER_SCROLL_IF_CONTENT_SCROLLS}) @Retention(RetentionPolicy.SOURCE) private @interface OverScroll {} /** * Always allow a user to over-scroll this view, provided it is a * view that can scroll. */ public static final int OVER_SCROLL_ALWAYS = 0; /** * Allow a user to over-scroll this view only if the content is large * enough to meaningfully scroll, provided it is a view that can scroll. */ public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; /** * Never allow a user to over-scroll this view. */ public static final int OVER_SCROLL_NEVER = 2; private static final long FAKE_FRAME_TIME = 10; /** @hide */ @IntDef({ IMPORTANT_FOR_ACCESSIBILITY_AUTO, IMPORTANT_FOR_ACCESSIBILITY_YES, IMPORTANT_FOR_ACCESSIBILITY_NO, IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS }) @Retention(RetentionPolicy.SOURCE) private @interface ImportantForAccessibility {} /** * Automatically determine whether a view is important for accessibility. */ public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000; /** * The view is important for accessibility. */ public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001; /** * The view is not important for accessibility. */ public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002; /** * The view is not important for accessibility, nor are any of its * descendant views. */ public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004; /** @hide */ @IntDef({ ACCESSIBILITY_LIVE_REGION_NONE, ACCESSIBILITY_LIVE_REGION_POLITE, ACCESSIBILITY_LIVE_REGION_ASSERTIVE }) @Retention(RetentionPolicy.SOURCE) private @interface AccessibilityLiveRegion {} /** * Live region mode specifying that accessibility services should not * automatically announce changes to this view. This is the default live * region mode for most views. *

* Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}. */ public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000; /** * Live region mode specifying that accessibility services should announce * changes to this view. *

* Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}. */ public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001; /** * Live region mode specifying that accessibility services should interrupt * ongoing speech to immediately announce changes to this view. *

* Use with {@link ViewCompat#setAccessibilityLiveRegion(View, int)}. */ public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002; /** @hide */ @IntDef({LAYER_TYPE_NONE, LAYER_TYPE_SOFTWARE, LAYER_TYPE_HARDWARE}) @Retention(RetentionPolicy.SOURCE) private @interface LayerType {} /** * Indicates that the view does not have a layer. */ public static final int LAYER_TYPE_NONE = 0; /** *

Indicates that the view has a software layer. A software layer is backed * by a bitmap and causes the view to be rendered using Android's software * rendering pipeline, even if hardware acceleration is enabled.

* *

Software layers have various usages:

*

When the application is not using hardware acceleration, a software layer * is useful to apply a specific color filter and/or blending mode and/or * translucency to a view and all its children.

*

When the application is using hardware acceleration, a software layer * is useful to render drawing primitives not supported by the hardware * accelerated pipeline. It can also be used to cache a complex view tree * into a texture and reduce the complexity of drawing operations. For instance, * when animating a complex view tree with a translation, a software layer can * be used to render the view tree only once.

*

Software layers should be avoided when the affected view tree updates * often. Every update will require to re-render the software layer, which can * potentially be slow (particularly when hardware acceleration is turned on * since the layer will have to be uploaded into a hardware texture after every * update.)

*/ public static final int LAYER_TYPE_SOFTWARE = 1; /** *

Indicates that the view has a hardware layer. A hardware layer is backed * by a hardware specific texture (generally Frame Buffer Objects or FBO on * OpenGL hardware) and causes the view to be rendered using Android's hardware * rendering pipeline, but only if hardware acceleration is turned on for the * view hierarchy. When hardware acceleration is turned off, hardware layers * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.

* *

A hardware layer is useful to apply a specific color filter and/or * blending mode and/or translucency to a view and all its children.

*

A hardware layer can be used to cache a complex view tree into a * texture and reduce the complexity of drawing operations. For instance, * when animating a complex view tree with a translation, a hardware layer can * be used to render the view tree only once.

*

A hardware layer can also be used to increase the rendering quality when * rotation transformations are applied on a view. It can also be used to * prevent potential clipping issues when applying 3D transforms on a view.

*/ public static final int LAYER_TYPE_HARDWARE = 2; /** @hide */ @IntDef({ LAYOUT_DIRECTION_LTR, LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LOCALE}) @Retention(RetentionPolicy.SOURCE) private @interface LayoutDirectionMode {} /** @hide */ @IntDef({ LAYOUT_DIRECTION_LTR, LAYOUT_DIRECTION_RTL }) @Retention(RetentionPolicy.SOURCE) private @interface ResolvedLayoutDirectionMode {} /** * Horizontal layout direction of this view is from Left to Right. */ public static final int LAYOUT_DIRECTION_LTR = 0; /** * Horizontal layout direction of this view is from Right to Left. */ public static final int LAYOUT_DIRECTION_RTL = 1; /** * Horizontal layout direction of this view is inherited from its parent. * Use with {@link #setLayoutDirection}. */ public static final int LAYOUT_DIRECTION_INHERIT = 2; /** * Horizontal layout direction of this view is from deduced from the default language * script for the locale. Use with {@link #setLayoutDirection}. */ public static final int LAYOUT_DIRECTION_LOCALE = 3; /** * Bits of {@link #getMeasuredWidthAndState} and * {@link #getMeasuredWidthAndState} that provide the actual measured size. */ public static final int MEASURED_SIZE_MASK = 0x00ffffff; /** * Bits of {@link #getMeasuredWidthAndState} and * {@link #getMeasuredWidthAndState} that provide the additional state bits. */ public static final int MEASURED_STATE_MASK = 0xff000000; /** * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits * for functions that combine both width and height into a single int, * such as {@link #getMeasuredState} and the childState argument of * {@link #resolveSizeAndState(int, int, int)}. */ public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; /** * Bit of {@link #getMeasuredWidthAndState} and * {@link #getMeasuredWidthAndState} that indicates the measured size * is smaller that the space the view would like to have. */ public static final int MEASURED_STATE_TOO_SMALL = 0x01000000; interface ViewCompatImpl { public boolean canScrollHorizontally(View v, int direction); public boolean canScrollVertically(View v, int direction); public int getOverScrollMode(View v); public void setOverScrollMode(View v, int mode); public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event); public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event); public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info); public void setAccessibilityDelegate(View v, @Nullable AccessibilityDelegateCompat delegate); public boolean hasAccessibilityDelegate(View v); public boolean hasTransientState(View view); public void setHasTransientState(View view, boolean hasTransientState); public void postInvalidateOnAnimation(View view); public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom); public void postOnAnimation(View view, Runnable action); public void postOnAnimationDelayed(View view, Runnable action, long delayMillis); public int getImportantForAccessibility(View view); public void setImportantForAccessibility(View view, int mode); public boolean isImportantForAccessibility(View view); public boolean performAccessibilityAction(View view, int action, Bundle arguments); public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view); public float getAlpha(View view); public void setLayerType(View view, int layerType, Paint paint); public int getLayerType(View view); public int getLabelFor(View view); public void setLabelFor(View view, int id); public void setLayerPaint(View view, Paint paint); public int getLayoutDirection(View view); public void setLayoutDirection(View view, int layoutDirection); public ViewParent getParentForAccessibility(View view); public boolean isOpaque(View view); public int resolveSizeAndState(int size, int measureSpec, int childMeasuredState); public int getMeasuredWidthAndState(View view); public int getMeasuredHeightAndState(View view); public int getMeasuredState(View view); public int getAccessibilityLiveRegion(View view); public void setAccessibilityLiveRegion(View view, int mode); public int getPaddingStart(View view); public int getPaddingEnd(View view); public void setPaddingRelative(View view, int start, int top, int end, int bottom); public void dispatchStartTemporaryDetach(View view); public void dispatchFinishTemporaryDetach(View view); public float getX(View view); public float getY(View view); public float getRotation(View view); public float getRotationX(View view); public float getRotationY(View view); public float getScaleX(View view); public float getScaleY(View view); public float getTranslationX(View view); public float getTranslationY(View view); public int getMinimumWidth(View view); public int getMinimumHeight(View view); public ViewPropertyAnimatorCompat animate(View view); public void setRotation(View view, float value); public void setRotationX(View view, float value); public void setRotationY(View view, float value); public void setScaleX(View view, float value); public void setScaleY(View view, float value); public void setTranslationX(View view, float value); public void setTranslationY(View view, float value); public void setX(View view, float value); public void setY(View view, float value); public void setAlpha(View view, float value); public void setPivotX(View view, float value); public void setPivotY(View view, float value); public float getPivotX(View view); public float getPivotY(View view); public void setElevation(View view, float elevation); public float getElevation(View view); public void setTranslationZ(View view, float translationZ); public float getTranslationZ(View view); public void setTransitionName(View view, String transitionName); public String getTransitionName(View view); public int getWindowSystemUiVisibility(View view); public void requestApplyInsets(View view); public void setChildrenDrawingOrderEnabled(ViewGroup viewGroup, boolean enabled); public boolean getFitsSystemWindows(View view); void setFitsSystemWindows(View view, boolean fitSystemWindows); void jumpDrawablesToCurrentState(View v); void setOnApplyWindowInsetsListener(View view, OnApplyWindowInsetsListener listener); void setSaveFromParentEnabled(View view, boolean enabled); void setActivated(View view, boolean activated); } static class BaseViewCompatImpl implements ViewCompatImpl { private Method mDispatchStartTemporaryDetach; private Method mDispatchFinishTemporaryDetach; private boolean mTempDetachBound; WeakHashMap mViewPropertyAnimatorCompatMap = null; public boolean canScrollHorizontally(View v, int direction) { return false; } public boolean canScrollVertically(View v, int direction) { return false; } public int getOverScrollMode(View v) { return OVER_SCROLL_NEVER; } public void setOverScrollMode(View v, int mode) { // Do nothing; API doesn't exist } public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) { // Do nothing; API doesn't exist } @Override public boolean hasAccessibilityDelegate(View v) { return false; } public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) { // Do nothing; API doesn't exist } public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) { // Do nothing; API doesn't exist } public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) { // Do nothing; API doesn't exist } public boolean hasTransientState(View view) { // A view can't have transient state if transient state wasn't supported. return false; } public void setHasTransientState(View view, boolean hasTransientState) { // Do nothing; API doesn't exist } public void postInvalidateOnAnimation(View view) { view.invalidate(); } public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) { view.invalidate(left, top, right, bottom); } public void postOnAnimation(View view, Runnable action) { view.postDelayed(action, getFrameTime()); } public void postOnAnimationDelayed(View view, Runnable action, long delayMillis) { view.postDelayed(action, getFrameTime() + delayMillis); } long getFrameTime() { return FAKE_FRAME_TIME; } public int getImportantForAccessibility(View view) { return 0; } public void setImportantForAccessibility(View view, int mode) { } public boolean isImportantForAccessibility(View view) { return true; } public boolean performAccessibilityAction(View view, int action, Bundle arguments) { return false; } public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) { return null; } public float getAlpha(View view) { return 1.0f; } public void setLayerType(View view, int layerType, Paint paint) { // No-op until layers became available (HC) } public int getLayerType(View view) { return LAYER_TYPE_NONE; } public int getLabelFor(View view) { return 0; } public void setLabelFor(View view, int id) { } public void setLayerPaint(View view, Paint p) { // No-op until layers became available (HC) } @Override public int getLayoutDirection(View view) { return LAYOUT_DIRECTION_LTR; } @Override public void setLayoutDirection(View view, int layoutDirection) { // No-op } @Override public ViewParent getParentForAccessibility(View view) { return view.getParent(); } @Override public boolean isOpaque(View view) { final Drawable bg = view.getBackground(); if (bg != null) { return bg.getOpacity() == PixelFormat.OPAQUE; } return false; } public int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { return View.resolveSize(size, measureSpec); } @Override public int getMeasuredWidthAndState(View view) { return view.getMeasuredWidth(); } @Override public int getMeasuredHeightAndState(View view) { return view.getMeasuredHeight(); } @Override public int getMeasuredState(View view) { return 0; } @Override public int getAccessibilityLiveRegion(View view) { return ACCESSIBILITY_LIVE_REGION_NONE; } @Override public void setAccessibilityLiveRegion(View view, int mode) { // No-op } @Override public int getPaddingStart(View view) { return view.getPaddingLeft(); } @Override public int getPaddingEnd(View view) { return view.getPaddingRight(); } @Override public void setPaddingRelative(View view, int start, int top, int end, int bottom) { view.setPadding(start, top, end, bottom); } @Override public void dispatchStartTemporaryDetach(View view) { if (!mTempDetachBound) { bindTempDetach(); } if (mDispatchStartTemporaryDetach != null) { try { mDispatchStartTemporaryDetach.invoke(view); } catch (Exception e) { Log.d(TAG, "Error calling dispatchStartTemporaryDetach", e); } } else { // Try this instead view.onStartTemporaryDetach(); } } @Override public void dispatchFinishTemporaryDetach(View view) { if (!mTempDetachBound) { bindTempDetach(); } if (mDispatchFinishTemporaryDetach != null) { try { mDispatchFinishTemporaryDetach.invoke(view); } catch (Exception e) { Log.d(TAG, "Error calling dispatchFinishTemporaryDetach", e); } } else { // Try this instead view.onFinishTemporaryDetach(); } } private void bindTempDetach() { try { mDispatchStartTemporaryDetach = View.class.getDeclaredMethod( "dispatchStartTemporaryDetach"); mDispatchFinishTemporaryDetach = View.class.getDeclaredMethod( "dispatchFinishTemporaryDetach"); } catch (NoSuchMethodException e) { Log.e(TAG, "Couldn't find method", e); } mTempDetachBound = true; } @Override public float getTranslationX(View view) { return 0; } @Override public float getTranslationY(View view) { return 0; } @Override public float getX(View view) { return 0; } @Override public float getY(View view) { return 0; } @Override public float getRotation(View view) { return 0; } @Override public float getRotationX(View view) { return 0; } @Override public float getRotationY(View view) { return 0; } @Override public float getScaleX(View view) { return 0; } @Override public float getScaleY(View view) { return 0; } @Override public int getMinimumWidth(View view) { return 0; } @Override public int getMinimumHeight(View view) { return 0; } @Override public ViewPropertyAnimatorCompat animate(View view) { return new ViewPropertyAnimatorCompat(view); } @Override public void setRotation(View view, float value) { // noop } @Override public void setTranslationX(View view, float value) { // noop } @Override public void setTranslationY(View view, float value) { // noop } @Override public void setAlpha(View view, float value) { // noop } @Override public void setRotationX(View view, float value) { // noop } @Override public void setRotationY(View view, float value) { // noop } @Override public void setScaleX(View view, float value) { // noop } @Override public void setScaleY(View view, float value) { // noop } @Override public void setX(View view, float value) { // noop } @Override public void setY(View view, float value) { // noop } @Override public void setPivotX(View view, float value) { // noop } @Override public void setPivotY(View view, float value) { // noop } @Override public float getPivotX(View view) { return 0; } @Override public float getPivotY(View view) { return 0; } @Override public void setTransitionName(View view, String transitionName) { } @Override public String getTransitionName(View view) { return null; } @Override public int getWindowSystemUiVisibility(View view) { return 0; } @Override public void requestApplyInsets(View view) { } @Override public void setElevation(View view, float elevation) { } @Override public float getElevation(View view) { return 0f; } @Override public void setTranslationZ(View view, float translationZ) { } @Override public float getTranslationZ(View view) { return 0f; } @Override public void setChildrenDrawingOrderEnabled(ViewGroup viewGroup, boolean enabled) { // noop } @Override public boolean getFitsSystemWindows(View view) { return false; } @Override public void setFitsSystemWindows(View view, boolean fitSystemWindows) { // noop } @Override public void jumpDrawablesToCurrentState(View view) { // Do nothing; API didn't exist. } @Override public void setOnApplyWindowInsetsListener(View view, OnApplyWindowInsetsListener listener) { // noop } @Override public void setSaveFromParentEnabled(View v, boolean enabled) { // noop } @Override public void setActivated(View view, boolean activated) { // noop } } static class EclairMr1ViewCompatImpl extends BaseViewCompatImpl { @Override public boolean isOpaque(View view) { return ViewCompatEclairMr1.isOpaque(view); } @Override public void setChildrenDrawingOrderEnabled(ViewGroup viewGroup, boolean enabled) { ViewCompatEclairMr1.setChildrenDrawingOrderEnabled(viewGroup, enabled); } } static class GBViewCompatImpl extends EclairMr1ViewCompatImpl { @Override public int getOverScrollMode(View v) { return ViewCompatGingerbread.getOverScrollMode(v); } @Override public void setOverScrollMode(View v, int mode) { ViewCompatGingerbread.setOverScrollMode(v, mode); } } static class HCViewCompatImpl extends GBViewCompatImpl { @Override long getFrameTime() { return ViewCompatHC.getFrameTime(); } @Override public float getAlpha(View view) { return ViewCompatHC.getAlpha(view); } @Override public void setLayerType(View view, int layerType, Paint paint) { ViewCompatHC.setLayerType(view, layerType, paint); } @Override public int getLayerType(View view) { return ViewCompatHC.getLayerType(view); } @Override public void setLayerPaint(View view, Paint paint) { // Make sure the paint is correct; this will be cheap if it's the same // instance as was used to call setLayerType earlier. setLayerType(view, getLayerType(view), paint); // This is expensive, but the only way to accomplish this before JB-MR1. view.invalidate(); } @Override public int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { return ViewCompatHC.resolveSizeAndState(size, measureSpec, childMeasuredState); } @Override public int getMeasuredWidthAndState(View view) { return ViewCompatHC.getMeasuredWidthAndState(view); } @Override public int getMeasuredHeightAndState(View view) { return ViewCompatHC.getMeasuredHeightAndState(view); } @Override public int getMeasuredState(View view) { return ViewCompatHC.getMeasuredState(view); } @Override public float getTranslationX(View view) { return ViewCompatHC.getTranslationX(view); } @Override public float getTranslationY(View view) { return ViewCompatHC.getTranslationY(view); } @Override public void setTranslationX(View view, float value) { ViewCompatHC.setTranslationX(view, value); } @Override public void setTranslationY(View view, float value) { ViewCompatHC.setTranslationY(view, value); } @Override public void setAlpha(View view, float value) { ViewCompatHC.setAlpha(view, value); } @Override public void setX(View view, float value) { ViewCompatHC.setX(view, value); } @Override public void setY(View view, float value) { ViewCompatHC.setY(view, value); } @Override public void setRotation(View view, float value) { ViewCompatHC.setRotation(view, value); } @Override public void setRotationX(View view, float value) { ViewCompatHC.setRotationX(view, value); } @Override public void setRotationY(View view, float value) { ViewCompatHC.setRotationY(view, value); } @Override public void setScaleX(View view, float value) { ViewCompatHC.setScaleX(view, value); } @Override public void setScaleY(View view, float value) { ViewCompatHC.setScaleY(view, value); } @Override public void setPivotX(View view, float value) { ViewCompatHC.setPivotX(view, value); } @Override public void setPivotY(View view, float value) { ViewCompatHC.setPivotY(view, value); } @Override public float getX(View view) { return ViewCompatHC.getX(view); } @Override public float getY(View view) { return ViewCompatHC.getY(view); } @Override public float getRotation(View view) { return ViewCompatHC.getRotation(view); } @Override public float getRotationX(View view) { return ViewCompatHC.getRotationX(view); } @Override public float getRotationY(View view) { return ViewCompatHC.getRotationY(view); } @Override public float getScaleX(View view) { return ViewCompatHC.getScaleX(view); } @Override public float getScaleY(View view) { return ViewCompatHC.getScaleY(view); } @Override public float getPivotX(View view) { return ViewCompatHC.getPivotX(view); } @Override public float getPivotY(View view) { return ViewCompatHC.getPivotY(view); } @Override public void jumpDrawablesToCurrentState(View view) { ViewCompatHC.jumpDrawablesToCurrentState(view); } @Override public void setSaveFromParentEnabled(View view, boolean enabled) { ViewCompatHC.setSaveFromParentEnabled(view, enabled); } @Override public void setActivated(View view, boolean activated) { ViewCompatHC.setActivated(view, activated); } } static class ICSViewCompatImpl extends HCViewCompatImpl { static Field mAccessibilityDelegateField; static boolean accessibilityDelegateCheckFailed = false; @Override public boolean canScrollHorizontally(View v, int direction) { return ViewCompatICS.canScrollHorizontally(v, direction); } @Override public boolean canScrollVertically(View v, int direction) { return ViewCompatICS.canScrollVertically(v, direction); } @Override public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) { ViewCompatICS.onPopulateAccessibilityEvent(v, event); } @Override public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) { ViewCompatICS.onInitializeAccessibilityEvent(v, event); } @Override public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) { ViewCompatICS.onInitializeAccessibilityNodeInfo(v, info.getInfo()); } @Override public void setAccessibilityDelegate(View v, @Nullable AccessibilityDelegateCompat delegate) { ViewCompatICS.setAccessibilityDelegate(v, delegate == null ? null : delegate.getBridge()); } @Override public boolean hasAccessibilityDelegate(View v) { if (accessibilityDelegateCheckFailed) { return false; // View implementation might have changed. } if (mAccessibilityDelegateField == null) { try { mAccessibilityDelegateField = View.class .getDeclaredField("mAccessibilityDelegate"); mAccessibilityDelegateField.setAccessible(true); } catch (Throwable t) { accessibilityDelegateCheckFailed = true; return false; } } try { return mAccessibilityDelegateField.get(v) != null; } catch (Throwable t) { accessibilityDelegateCheckFailed = true; return false; } } @Override public ViewPropertyAnimatorCompat animate(View view) { if (mViewPropertyAnimatorCompatMap == null) { mViewPropertyAnimatorCompatMap = new WeakHashMap(); } ViewPropertyAnimatorCompat vpa = mViewPropertyAnimatorCompatMap.get(view); if (vpa == null) { vpa = new ViewPropertyAnimatorCompat(view); mViewPropertyAnimatorCompatMap.put(view, vpa); } return vpa; } @Override public void setFitsSystemWindows(View view, boolean fitSystemWindows) { ViewCompatICS.setFitsSystemWindows(view, fitSystemWindows); } } static class JBViewCompatImpl extends ICSViewCompatImpl { @Override public boolean hasTransientState(View view) { return ViewCompatJB.hasTransientState(view); } @Override public void setHasTransientState(View view, boolean hasTransientState) { ViewCompatJB.setHasTransientState(view, hasTransientState); } @Override public void postInvalidateOnAnimation(View view) { ViewCompatJB.postInvalidateOnAnimation(view); } @Override public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) { ViewCompatJB.postInvalidateOnAnimation(view, left, top, right, bottom); } @Override public void postOnAnimation(View view, Runnable action) { ViewCompatJB.postOnAnimation(view, action); } @Override public void postOnAnimationDelayed(View view, Runnable action, long delayMillis) { ViewCompatJB.postOnAnimationDelayed(view, action, delayMillis); } @Override public int getImportantForAccessibility(View view) { return ViewCompatJB.getImportantForAccessibility(view); } @Override public void setImportantForAccessibility(View view, int mode) { // IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS is not available // on this platform so replace with IMPORTANT_FOR_ACCESSIBILITY_NO // which is closer semantically. if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { mode = IMPORTANT_FOR_ACCESSIBILITY_NO; } ViewCompatJB.setImportantForAccessibility(view, mode); } @Override public boolean performAccessibilityAction(View view, int action, Bundle arguments) { return ViewCompatJB.performAccessibilityAction(view, action, arguments); } @Override public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) { Object compat = ViewCompatJB.getAccessibilityNodeProvider(view); if (compat != null) { return new AccessibilityNodeProviderCompat(compat); } return null; } @Override public ViewParent getParentForAccessibility(View view) { return ViewCompatJB.getParentForAccessibility(view); } @Override public int getMinimumWidth(View view) { return ViewCompatJB.getMinimumWidth(view); } @Override public int getMinimumHeight(View view) { return ViewCompatJB.getMinimumHeight(view); } @Override public void requestApplyInsets(View view) { ViewCompatJB.requestApplyInsets(view); } @Override public boolean getFitsSystemWindows(View view) { return ViewCompatJB.getFitsSystemWindows(view); } } static class JbMr1ViewCompatImpl extends JBViewCompatImpl { @Override public int getLabelFor(View view) { return ViewCompatJellybeanMr1.getLabelFor(view); } @Override public void setLabelFor(View view, int id) { ViewCompatJellybeanMr1.setLabelFor(view, id); } @Override public void setLayerPaint(View view, Paint paint) { ViewCompatJellybeanMr1.setLayerPaint(view, paint); } @Override public int getLayoutDirection(View view) { return ViewCompatJellybeanMr1.getLayoutDirection(view); } @Override public void setLayoutDirection(View view, int layoutDirection) { ViewCompatJellybeanMr1.setLayoutDirection(view, layoutDirection); } @Override public int getPaddingStart(View view) { return ViewCompatJellybeanMr1.getPaddingStart(view); } @Override public int getPaddingEnd(View view) { return ViewCompatJellybeanMr1.getPaddingEnd(view); } @Override public void setPaddingRelative(View view, int start, int top, int end, int bottom) { ViewCompatJellybeanMr1.setPaddingRelative(view, start, top, end, bottom); } @Override public int getWindowSystemUiVisibility(View view) { return ViewCompatJellybeanMr1.getWindowSystemUiVisibility(view); } } static class KitKatViewCompatImpl extends JbMr1ViewCompatImpl { @Override public int getAccessibilityLiveRegion(View view) { return ViewCompatKitKat.getAccessibilityLiveRegion(view); } @Override public void setAccessibilityLiveRegion(View view, int mode) { ViewCompatKitKat.setAccessibilityLiveRegion(view, mode); } @Override public void setImportantForAccessibility(View view, int mode) { ViewCompatJB.setImportantForAccessibility(view, mode); } } static class Api21ViewCompatImpl extends KitKatViewCompatImpl { @Override public void setTransitionName(View view, String transitionName) { ViewCompatApi21.setTransitionName(view, transitionName); } @Override public String getTransitionName(View view) { return ViewCompatApi21.getTransitionName(view); } @Override public void requestApplyInsets(View view) { ViewCompatApi21.requestApplyInsets(view); } @Override public void setElevation(View view, float elevation) { ViewCompatApi21.setElevation(view, elevation); } @Override public float getElevation(View view) { return ViewCompatApi21.getElevation(view); } @Override public void setTranslationZ(View view, float translationZ) { ViewCompatApi21.setTranslationZ(view, translationZ); } @Override public float getTranslationZ(View view) { return ViewCompatApi21.getTranslationZ(view); } @Override public void setOnApplyWindowInsetsListener(View view, OnApplyWindowInsetsListener listener) { ViewCompatApi21.setOnApplyWindowInsetsListener(view, listener); } @Override public boolean isImportantForAccessibility(View view) { return ViewCompatApi21.isImportantForAccessibility(view); } } static final ViewCompatImpl IMPL; static { final int version = android.os.Build.VERSION.SDK_INT; if (version >= 21) { IMPL = new Api21ViewCompatImpl(); } else if (version >= 19) { IMPL = new KitKatViewCompatImpl(); } else if (version >= 17) { IMPL = new JbMr1ViewCompatImpl(); } else if (version >= 16) { IMPL = new JBViewCompatImpl(); } else if (version >= 14) { IMPL = new ICSViewCompatImpl(); } else if (version >= 11) { IMPL = new HCViewCompatImpl(); } else if (version >= 9) { IMPL = new GBViewCompatImpl(); } else if (version >= 7) { IMPL = new EclairMr1ViewCompatImpl(); } else { IMPL = new BaseViewCompatImpl(); } } /** * Check if this view can be scrolled horizontally in a certain direction. * * @param v The View against which to invoke the method. * @param direction Negative to check scrolling left, positive to check scrolling right. * @return true if this view can be scrolled in the specified direction, false otherwise. */ public static boolean canScrollHorizontally(View v, int direction) { return IMPL.canScrollHorizontally(v, direction); } /** * Check if this view can be scrolled vertically in a certain direction. * * @param v The View against which to invoke the method. * @param direction Negative to check scrolling up, positive to check scrolling down. * @return true if this view can be scrolled in the specified direction, false otherwise. */ public static boolean canScrollVertically(View v, int direction) { return IMPL.canScrollVertically(v, direction); } /** * Returns the over-scroll mode for this view. The result will be * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} * (allow over-scrolling only if the view content is larger than the container), * or {@link #OVER_SCROLL_NEVER}. * * @param v The View against which to invoke the method. * @return This view's over-scroll mode. */ @OverScroll public static int getOverScrollMode(View v) { return IMPL.getOverScrollMode(v); } /** * Set the over-scroll mode for this view. Valid over-scroll modes are * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} * (allow over-scrolling only if the view content is larger than the container), * or {@link #OVER_SCROLL_NEVER}. * * Setting the over-scroll mode of a view will have an effect only if the * view is capable of scrolling. * * @param v The View against which to invoke the method. * @param overScrollMode The new over-scroll mode for this view. */ public static void setOverScrollMode(View v, @OverScroll int overScrollMode) { IMPL.setOverScrollMode(v, overScrollMode); } /** * Called from {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} * giving a chance to this View to populate the accessibility event with its * text content. While this method is free to modify event * attributes other than text content, doing so should normally be performed in * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)}. *

* Example: Adding formatted date string to an accessibility event in addition * to the text added by the super implementation: *

 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
     *     super.onPopulateAccessibilityEvent(event);
     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
     *         mCurrentDate.getTimeInMillis(), flags);
     *     event.getText().add(selectedDateUtterance);
     * }
*

* If an {@link android.view.View.AccessibilityDelegate} has been specified via calling * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its * {@link android.view.View.AccessibilityDelegate#onPopulateAccessibilityEvent(View, * AccessibilityEvent)} * is responsible for handling this call. *

*

Note: Always call the super implementation before adding * information to the event, in case the default implementation has basic information to add. *

* * @param v The View against which to invoke the method. * @param event The accessibility event which to populate. * * @see View#sendAccessibilityEvent(int) * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) */ public static void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) { IMPL.onPopulateAccessibilityEvent(v, event); } /** * Initializes an {@link AccessibilityEvent} with information about * this View which is the event source. In other words, the source of * an accessibility event is the view whose state change triggered firing * the event. *

* Example: Setting the password property of an event in addition * to properties set by the super implementation: *

 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
     *     super.onInitializeAccessibilityEvent(event);
     *     event.setPassword(true);
     * }
*

* If an {@link android.view.View.AccessibilityDelegate} has been specified via calling * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its * {@link android.view.View.AccessibilityDelegate#onInitializeAccessibilityEvent(View, * AccessibilityEvent)} * is responsible for handling this call. *

*

Note: Always call the super implementation before adding * information to the event, in case the default implementation has basic information to add. *

* * @param v The View against which to invoke the method. * @param event The event to initialize. * * @see View#sendAccessibilityEvent(int) * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) */ public static void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) { IMPL.onInitializeAccessibilityEvent(v, event); } /** * Initializes an {@link android.view.accessibility.AccessibilityNodeInfo} with information * about this view. The base implementation sets: * *

* Subclasses should override this method, call the super implementation, * and set additional attributes. *

*

* If an {@link android.view.View.AccessibilityDelegate} has been specified via calling * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its * {@link android.view.View.AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, * android.view.accessibility.AccessibilityNodeInfo)} * is responsible for handling this call. *

* * @param v The View against which to invoke the method. * @param info The instance to initialize. */ public static void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) { IMPL.onInitializeAccessibilityNodeInfo(v, info); } /** * Sets a delegate for implementing accessibility support via compositon as * opposed to inheritance. The delegate's primary use is for implementing * backwards compatible widgets. For more details see * {@link android.view.View.AccessibilityDelegate}. * * @param v The View against which to invoke the method. * @param delegate The delegate instance. * * @see android.view.View.AccessibilityDelegate */ public static void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) { IMPL.setAccessibilityDelegate(v, delegate); } /** * Checks whether provided View has an accessibility delegate attached to it. * * @param v The View instance to check * @return True if the View has an accessibility delegate */ public static boolean hasAccessibilityDelegate(View v) { return IMPL.hasAccessibilityDelegate(v); } /** * Indicates whether the view is currently tracking transient state that the * app should not need to concern itself with saving and restoring, but that * the framework should take special note to preserve when possible. * * @param view View to check for transient state * @return true if the view has transient state */ public static boolean hasTransientState(View view) { return IMPL.hasTransientState(view); } /** * Set whether this view is currently tracking transient state that the * framework should attempt to preserve when possible. * * @param view View tracking transient state * @param hasTransientState true if this view has transient state */ public static void setHasTransientState(View view, boolean hasTransientState) { IMPL.setHasTransientState(view, hasTransientState); } /** *

Cause an invalidate to happen on the next animation time step, typically the * next display frame.

* *

This method can be invoked from outside of the UI thread * only when this View is attached to a window.

* * @param view View to invalidate */ public static void postInvalidateOnAnimation(View view) { IMPL.postInvalidateOnAnimation(view); } /** *

Cause an invalidate of the specified area to happen on the next animation * time step, typically the next display frame.

* *

This method can be invoked from outside of the UI thread * only when this View is attached to a window.

* * @param view View to invalidate * @param left The left coordinate of the rectangle to invalidate. * @param top The top coordinate of the rectangle to invalidate. * @param right The right coordinate of the rectangle to invalidate. * @param bottom The bottom coordinate of the rectangle to invalidate. */ public static void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) { IMPL.postInvalidateOnAnimation(view, left, top, right, bottom); } /** *

Causes the Runnable to execute on the next animation time step. * The runnable will be run on the user interface thread.

* *

This method can be invoked from outside of the UI thread * only when this View is attached to a window.

* * @param view View to post this Runnable to * @param action The Runnable that will be executed. */ public static void postOnAnimation(View view, Runnable action) { IMPL.postOnAnimation(view, action); } /** *

Causes the Runnable to execute on the next animation time step, * after the specified amount of time elapses. * The runnable will be run on the user interface thread.

* *

This method can be invoked from outside of the UI thread * only when this View is attached to a window.

* * @param view The view to post this Runnable to * @param action The Runnable that will be executed. * @param delayMillis The delay (in milliseconds) until the Runnable * will be executed. */ public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) { IMPL.postOnAnimationDelayed(view, action, delayMillis); } /** * Gets the mode for determining whether this View is important for accessibility * which is if it fires accessibility events and if it is reported to * accessibility services that query the screen. * * @param view The view whose property to get. * @return The mode for determining whether a View is important for accessibility. * * @see #IMPORTANT_FOR_ACCESSIBILITY_YES * @see #IMPORTANT_FOR_ACCESSIBILITY_NO * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO */ @ImportantForAccessibility public static int getImportantForAccessibility(View view) { return IMPL.getImportantForAccessibility(view); } /** * Sets how to determine whether this view is important for accessibility * which is if it fires accessibility events and if it is reported to * accessibility services that query the screen. *

* Note: If the current paltform version does not support the * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} mode, then * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO} will be used as it is the * closest terms of semantics. *

* * @param view The view whose property to set. * @param mode How to determine whether this view is important for accessibility. * * @see #IMPORTANT_FOR_ACCESSIBILITY_YES * @see #IMPORTANT_FOR_ACCESSIBILITY_NO * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO */ public static void setImportantForAccessibility(View view, @ImportantForAccessibility int mode) { IMPL.setImportantForAccessibility(view, mode); } /** * Performs the specified accessibility action on the view. For * possible accessibility actions look at {@link AccessibilityNodeInfoCompat}. *

* If an {@link AccessibilityDelegateCompat} has been specified via calling * {@link #setAccessibilityDelegate(View, AccessibilityDelegateCompat)} its * {@link AccessibilityDelegateCompat#performAccessibilityAction(View, int, Bundle)} * is responsible for handling this call. *

* * @param action The action to perform. * @param arguments Optional action arguments. * @return Whether the action was performed. */ public static boolean performAccessibilityAction(View view, int action, Bundle arguments) { return IMPL.performAccessibilityAction(view, action, arguments); } /** * Gets the provider for managing a virtual view hierarchy rooted at this View * and reported to {@link android.accessibilityservice.AccessibilityService}s * that explore the window content. *

* If this method returns an instance, this instance is responsible for managing * {@link AccessibilityNodeInfoCompat}s describing the virtual sub-tree rooted at * this View including the one representing the View itself. Similarly the returned * instance is responsible for performing accessibility actions on any virtual * view or the root view itself. *

*

* If an {@link AccessibilityDelegateCompat} has been specified via calling * {@link #setAccessibilityDelegate(View, AccessibilityDelegateCompat)} its * {@link AccessibilityDelegateCompat#getAccessibilityNodeProvider(View)} * is responsible for handling this call. *

* * @param view The view whose property to get. * @return The provider. * * @see AccessibilityNodeProviderCompat */ public static AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View view) { return IMPL.getAccessibilityNodeProvider(view); } /** * The opacity of the view. This is a value from 0 to 1, where 0 means the view is * completely transparent and 1 means the view is completely opaque. * *

By default this is 1.0f. Prior to API 11, the returned value is always 1.0f. * @return The opacity of the view. */ public static float getAlpha(View view) { return IMPL.getAlpha(view); } /** *

Specifies the type of layer backing this view. The layer can be * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or * {@link #LAYER_TYPE_HARDWARE hardware}.

* *

A layer is associated with an optional {@link android.graphics.Paint} * instance that controls how the layer is composed on screen. The following * properties of the paint are taken into account when composing the layer:

* * *

If this view has an alpha value set to < 1.0 by calling * setAlpha(float), the alpha value of the layer's paint is replaced by * this view's alpha value. Calling setAlpha(float) is therefore * equivalent to setting a hardware layer on this view and providing a paint with * the desired alpha value.

* *

Refer to the documentation of {@link #LAYER_TYPE_NONE disabled}, * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware} * for more information on when and how to use layers.

* * @param layerType The ype of layer to use with this view, must be one of * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or * {@link #LAYER_TYPE_HARDWARE} * @param paint The paint used to compose the layer. This argument is optional * and can be null. It is ignored when the layer type is * {@link #LAYER_TYPE_NONE} * * @param view View to set the layer type for * @param layerType The type of layer to use with this view, must be one of * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or * {@link #LAYER_TYPE_HARDWARE} * @param paint The paint used to compose the layer. This argument is optional * and can be null. It is ignored when the layer type is * {@link #LAYER_TYPE_NONE} */ public static void setLayerType(View view, @LayerType int layerType, Paint paint) { IMPL.setLayerType(view, layerType, paint); } /** * Indicates what type of layer is currently associated with this view. By default * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. * Refer to the documentation of * {@link #setLayerType(android.view.View, int, android.graphics.Paint)} * for more information on the different types of layers. * * @param view The view to fetch the layer type from * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or * {@link #LAYER_TYPE_HARDWARE} * * @see #setLayerType(android.view.View, int, android.graphics.Paint) * @see #LAYER_TYPE_NONE * @see #LAYER_TYPE_SOFTWARE * @see #LAYER_TYPE_HARDWARE */ @LayerType public static int getLayerType(View view) { return IMPL.getLayerType(view); } /** * Gets the id of a view for which a given view serves as a label for * accessibility purposes. * * @param view The view on which to invoke the corresponding method. * @return The labeled view id. */ public static int getLabelFor(View view) { return IMPL.getLabelFor(view); } /** * Sets the id of a view for which a given view serves as a label for * accessibility purposes. * * @param view The view on which to invoke the corresponding method. * @param labeledId The labeled view id. */ public static void setLabelFor(View view, @IdRes int labeledId) { IMPL.setLabelFor(view, labeledId); } /** * Updates the {@link Paint} object used with the current layer (used only if the current * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint * provided to {@link #setLayerType(android.view.View, int, android.graphics.Paint)} * will be used the next time the View is redrawn, but * {@link #setLayerPaint(android.view.View, android.graphics.Paint)} * must be called to ensure that the view gets redrawn immediately. * *

A layer is associated with an optional {@link android.graphics.Paint} * instance that controls how the layer is composed on screen. The following * properties of the paint are taken into account when composing the layer:

* * *

If this view has an alpha value set to < 1.0 by calling * View#setAlpha(float), the alpha value of the layer's paint is replaced by * this view's alpha value. Calling View#setAlpha(float) is therefore * equivalent to setting a hardware layer on this view and providing a paint with * the desired alpha value.

* * @param view View to set a layer paint for * @param paint The paint used to compose the layer. This argument is optional * and can be null. It is ignored when the layer type is * {@link #LAYER_TYPE_NONE} * * @see #setLayerType(View, int, android.graphics.Paint) */ public static void setLayerPaint(View view, Paint paint) { IMPL.setLayerPaint(view, paint); } /** * Returns the resolved layout direction for this view. * * @param view View to get layout direction for * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL. * * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version * is lower than Jellybean MR1 (API 17) */ @ResolvedLayoutDirectionMode public static int getLayoutDirection(View view) { return IMPL.getLayoutDirection(view); } /** * Set the layout direction for this view. This will propagate a reset of layout direction * resolution to the view's children and resolve layout direction for this view. * * @param view View to set layout direction for * @param layoutDirection the layout direction to set. Should be one of: * * {@link #LAYOUT_DIRECTION_LTR}, * {@link #LAYOUT_DIRECTION_RTL}, * {@link #LAYOUT_DIRECTION_INHERIT}, * {@link #LAYOUT_DIRECTION_LOCALE}. * * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution * proceeds up the parent chain of the view to get the value. If there is no parent, then it * will return the default {@link #LAYOUT_DIRECTION_LTR}. */ public static void setLayoutDirection(View view, @LayoutDirectionMode int layoutDirection) { IMPL.setLayoutDirection(view, layoutDirection); } /** * Gets the parent for accessibility purposes. Note that the parent for * accessibility is not necessary the immediate parent. It is the first * predecessor that is important for accessibility. * * @param view View to retrieve parent for * @return The parent for use in accessibility inspection */ public static ViewParent getParentForAccessibility(View view) { return IMPL.getParentForAccessibility(view); } /** * Indicates whether this View is opaque. An opaque View guarantees that it will * draw all the pixels overlapping its bounds using a fully opaque color. * * On API 7 and above this will call View's true isOpaque method. On previous platform * versions it will check the opacity of the view's background drawable if present. * * @return True if this View is guaranteed to be fully opaque, false otherwise. */ public static boolean isOpaque(View view) { return IMPL.isOpaque(view); } /** * Utility to reconcile a desired size and state, with constraints imposed * by a MeasureSpec. Will take the desired size, unless a different size * is imposed by the constraints. The returned value is a compound integer, * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting * size is smaller than the size the view wants to be. * * @param size How big the view wants to be * @param measureSpec Constraints imposed by the parent * @return Size information bit mask as defined by * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. */ public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { return IMPL.resolveSizeAndState(size, measureSpec, childMeasuredState); } /** * Return the full width measurement information for this view as computed * by the most recent call to {@link android.view.View#measure(int, int)}. * This result is a bit mask as defined by {@link #MEASURED_SIZE_MASK} and * {@link #MEASURED_STATE_TOO_SMALL}. * This should be used during measurement and layout calculations only. Use * {@link android.view.View#getWidth()} to see how wide a view is after layout. * * @return The measured width of this view as a bit mask. */ public static int getMeasuredWidthAndState(View view) { return IMPL.getMeasuredWidthAndState(view); } /** * Return the full height measurement information for this view as computed * by the most recent call to {@link android.view.View#measure(int, int)}. * This result is a bit mask as defined by {@link #MEASURED_SIZE_MASK} and * {@link #MEASURED_STATE_TOO_SMALL}. * This should be used during measurement and layout calculations only. Use * {@link android.view.View#getHeight()} to see how wide a view is after layout. * * @return The measured width of this view as a bit mask. */ public static int getMeasuredHeightAndState(View view) { return IMPL.getMeasuredHeightAndState(view); } /** * Return only the state bits of {@link #getMeasuredWidthAndState} * and {@link #getMeasuredHeightAndState}, combined into one integer. * The width component is in the regular bits {@link #MEASURED_STATE_MASK} * and the height component is at the shifted bits * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. */ public static int getMeasuredState(View view) { return IMPL.getMeasuredState(view); } /** * Gets the live region mode for the specified View. * * @param view The view from which to obtain the live region mode * @return The live region mode for the view. * * @see ViewCompat#setAccessibilityLiveRegion(View, int) */ @AccessibilityLiveRegion public static int getAccessibilityLiveRegion(View view) { return IMPL.getAccessibilityLiveRegion(view); } /** * Sets the live region mode for the specified view. This indicates to * accessibility services whether they should automatically notify the user * about changes to the view's content description or text, or to the * content descriptions or text of the view's children (where applicable). *

* For example, in a login screen with a TextView that displays an "incorrect * password" notification, that view should be marked as a live region with * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. *

* To disable change notifications for this view, use * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region * mode for most views. *

* To indicate that the user should be notified of changes, use * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. *

* If the view's changes should interrupt ongoing speech and notify the user * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}. * * @param view The view on which to set the live region mode * @param mode The live region mode for this view, one of: *

*/ public static void setAccessibilityLiveRegion(View view, @AccessibilityLiveRegion int mode) { IMPL.setAccessibilityLiveRegion(view, mode); } /** * Returns the start padding of the specified view depending on its resolved layout direction. * If there are inset and enabled scrollbars, this value may include the space * required to display the scrollbars as well. * * @param view The view to get padding for * @return the start padding in pixels */ public static int getPaddingStart(View view) { return IMPL.getPaddingStart(view); } /** * Returns the end padding of the specified view depending on its resolved layout direction. * If there are inset and enabled scrollbars, this value may include the space * required to display the scrollbars as well. * * @param view The view to get padding for * @return the end padding in pixels */ public static int getPaddingEnd(View view) { return IMPL.getPaddingEnd(view); } /** * Sets the relative padding. The view may add on the space required to display * the scrollbars, depending on the style and visibility of the scrollbars. * So the values returned from {@link #getPaddingStart}, {@link View#getPaddingTop}, * {@link #getPaddingEnd} and {@link View#getPaddingBottom} may be different * from the values set in this call. * * @param view The view on which to set relative padding * @param start the start padding in pixels * @param top the top padding in pixels * @param end the end padding in pixels * @param bottom the bottom padding in pixels */ public static void setPaddingRelative(View view, int start, int top, int end, int bottom) { IMPL.setPaddingRelative(view, start, top, end, bottom); } /** * Notify a view that it is being temporarily detached. */ public static void dispatchStartTemporaryDetach(View view) { IMPL.dispatchStartTemporaryDetach(view); } /** * Notify a view that its temporary detach has ended; the view is now reattached. */ public static void dispatchFinishTemporaryDetach(View view) { IMPL.dispatchFinishTemporaryDetach(view); } /** * The horizontal location of this view relative to its {@link View#getLeft() left} position. * This position is post-layout, in addition to wherever the object's * layout placed it. * *

Prior to API 11 this will return 0.

* * @return The horizontal position of this view relative to its left position, in pixels. */ public static float getTranslationX(View view) { return IMPL.getTranslationX(view); } /** * The vertical location of this view relative to its {@link View#getTop() left} position. * This position is post-layout, in addition to wherever the object's * layout placed it. * *

Prior to API 11 this will return 0.

* * @return The vertical position of this view relative to its top position, in pixels. */ public static float getTranslationY(View view) { return IMPL.getTranslationY(view); } /** * Returns the minimum width of the view. * *

Prior to API 16 this will return 0.

* * @return the minimum width the view will try to be. */ public static int getMinimumWidth(View view) { return IMPL.getMinimumWidth(view); } /** * Returns the minimum height of the view. * *

Prior to API 16 this will return 0.

* * @return the minimum height the view will try to be. */ public static int getMinimumHeight(View view) { return IMPL.getMinimumHeight(view); } /** * This method returns a ViewPropertyAnimator object, which can be used to animate * specific properties on this View. * *

Prior to API 14, this method will do nothing.

* * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View. */ public static ViewPropertyAnimatorCompat animate(View view) { return IMPL.animate(view); } /** * Sets the horizontal location of this view relative to its left position. * This effectively positions the object post-layout, in addition to wherever the object's * layout placed it. * *

Prior to API 11 this will have no effect.

* * @param value The horizontal position of this view relative to its left position, * in pixels. */ public static void setTranslationX(View view, float value) { IMPL.setTranslationX(view, value); } /** * Sets the vertical location of this view relative to its top position. * This effectively positions the object post-layout, in addition to wherever the object's * layout placed it. * *

Prior to API 11 this will have no effect.

* * @param value The vertical position of this view relative to its top position, * in pixels. * * @attr ref android.R.styleable#View_translationY */ public static void setTranslationY(View view, float value) { IMPL.setTranslationY(view, value); } /** *

Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is * completely transparent and 1 means the view is completely opaque.

* *

Note that setting alpha to a translucent value (0 < alpha < 1) can have significant * performance implications, especially for large views. It is best to use the alpha property * sparingly and transiently, as in the case of fading animations.

* *

Prior to API 11 this will have no effect.

* * @param value The opacity of the view. */ public static void setAlpha(View view, float value) { IMPL.setAlpha(view, value); } /** * Sets the visual x position of this view, in pixels. This is equivalent to setting the * {@link #setTranslationX(View, float) translationX} property to be the difference between * the x value passed in and the current left property of the view as determined * by the layout bounds. * *

Prior to API 11 this will have no effect.

* * @param value The visual x position of this view, in pixels. */ public static void setX(View view, float value) { IMPL.setX(view, value); } /** * Sets the visual y position of this view, in pixels. This is equivalent to setting the * {@link #setTranslationY(View, float) translationY} property to be the difference between * the y value passed in and the current top property of the view as determined by the * layout bounds. * *

Prior to API 11 this will have no effect.

* * @param value The visual y position of this view, in pixels. */ public static void setY(View view, float value) { IMPL.setY(view, value); } /** * Sets the degrees that the view is rotated around the pivot point. Increasing values * result in clockwise rotation. * *

Prior to API 11 this will have no effect.

* * @param value The degrees of rotation. */ public static void setRotation(View view, float value) { IMPL.setRotation(view, value); } /** * Sets the degrees that the view is rotated around the horizontal axis through the pivot point. * Increasing values result in clockwise rotation from the viewpoint of looking down the * x axis. * *

Prior to API 11 this will have no effect.

* * @param value The degrees of X rotation. */ public static void setRotationX(View view, float value) { IMPL.setRotationX(view, value); } /** * Sets the degrees that the view is rotated around the vertical axis through the pivot point. * Increasing values result in counter-clockwise rotation from the viewpoint of looking * down the y axis. * *

Prior to API 11 this will have no effect.

* * @param value The degrees of Y rotation. */ public static void setRotationY(View view, float value) { IMPL.setRotationY(view, value); } /** * Sets the amount that the view is scaled in x around the pivot point, as a proportion of * the view's unscaled width. A value of 1 means that no scaling is applied. * *

Prior to API 11 this will have no effect.

* * @param value The scaling factor. */ public static void setScaleX(View view, float value) { IMPL.setScaleX(view, value); } /** * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of * the view's unscaled width. A value of 1 means that no scaling is applied. * *

Prior to API 11 this will have no effect.

* * @param value The scaling factor. */ public static void setScaleY(View view, float value) { IMPL.setScaleY(view, value); } /** * The x location of the point around which the view is * {@link #setRotation(View, float) rotated} and {@link #setScaleX(View, float) scaled}. * *

Prior to API 11 this will have no effect.

* */ public static float getPivotX(View view) { return IMPL.getPivotX(view); } /** * Sets the x location of the point around which the view is * {@link #setRotation(View, float) rotated} and {@link #setScaleX(View, float) scaled}. * By default, the pivot point is centered on the object. * Setting this property disables this behavior and causes the view to use only the * explicitly set pivotX and pivotY values. * *

Prior to API 11 this will have no effect.

* * @param value The x location of the pivot point. */ public static void setPivotX(View view, float value) { IMPL.setPivotX(view, value); } /** * The y location of the point around which the view is {@link #setRotation(View, * float) rotated} and {@link #setScaleY(View, float) scaled}. * *

Prior to API 11 this will return 0.

* * @return The y location of the pivot point. */ public static float getPivotY(View view) { return IMPL.getPivotY(view); } /** * Sets the y location of the point around which the view is * {@link #setRotation(View, float) rotated} and {@link #setScaleY(View, float) scaled}. * By default, the pivot point is centered on the object. * Setting this property disables this behavior and causes the view to use only the * explicitly set pivotX and pivotY values. * *

Prior to API 11 this will have no effect.

* * @param value The y location of the pivot point. */ public static void setPivotY(View view, float value) { IMPL.setPivotX(view, value); } public static float getRotation(View view) { return IMPL.getRotation(view); } public static float getRotationX(View view) { return IMPL.getRotationX(view); } public static float getRotationY(View view) { return IMPL.getRotationY(view); } public static float getScaleX(View view) { return IMPL.getScaleX(view); } public static float getScaleY(View view) { return IMPL.getScaleY(view); } public static float getX(View view) { return IMPL.getX(view); } public static float getY(View view) { return IMPL.getY(view); } /** * Sets the base elevation of this view, in pixels. */ public static void setElevation(View view, float elevation) { IMPL.setElevation(view, elevation); } /** * The base elevation of this view relative to its parent, in pixels. * * @return The base depth position of the view, in pixels. */ public static float getElevation(View view) { return IMPL.getElevation(view); } /** * Sets the depth location of this view relative to its {@link #getElevation(View) elevation}. */ public static void setTranslationZ(View view, float translationZ) { IMPL.setTranslationZ(view, translationZ); } /** * The depth location of this view relative to its {@link #getElevation(View) elevation}. * * @return The depth of this view relative to its elevation. */ public static float getTranslationZ(View view) { return IMPL.getTranslationZ(view); } /** * Sets the name of the View to be used to identify Views in Transitions. * Names should be unique in the View hierarchy. * * @param view The View against which to invoke the method. * @param transitionName The name of the View to uniquely identify it for Transitions. */ public static void setTransitionName(View view, String transitionName) { IMPL.setTransitionName(view, transitionName); } /** * Returns the name of the View to be used to identify Views in Transitions. * Names should be unique in the View hierarchy. * *

This returns null if the View has not been given a name.

* * @param view The View against which to invoke the method. * @return The name used of the View to be used to identify Views in Transitions or null * if no name has been given. */ public static String getTransitionName(View view) { return IMPL.getTransitionName(view); } /** * Returns the current system UI visibility that is currently set for the entire window. */ public static int getWindowSystemUiVisibility(View view) { return IMPL.getWindowSystemUiVisibility(view); } /** * Ask that a new dispatch of {@code View.onApplyWindowInsets(WindowInsets)} be performed. This * falls back to {@code View.requestFitSystemWindows()} where available. */ public static void requestApplyInsets(View view) { IMPL.requestApplyInsets(view); } /** * Tells the ViewGroup whether to draw its children in the order defined by the method * {@code ViewGroup.getChildDrawingOrder(int, int)}. * * @param enabled true if the order of the children when drawing is determined by * {@link ViewGroup#getChildDrawingOrder(int, int)}, false otherwise * *

Prior to API 7 this will have no effect.

*/ public static void setChildrenDrawingOrderEnabled(ViewGroup viewGroup, boolean enabled) { IMPL.setChildrenDrawingOrderEnabled(viewGroup, enabled); } /** * Returns true if this view should adapt to fit system window insets. This method will always * return false before API 16 (Jellybean). */ public static boolean getFitsSystemWindows(View v) { return IMPL.getFitsSystemWindows(v); } /** * Sets whether or not this view should account for system screen decorations * such as the status bar and inset its content; that is, controlling whether * the default implementation of {@link View#fitSystemWindows(Rect)} will be * executed. See that method for more details. */ public static void setFitsSystemWindows(View view, boolean fitSystemWindows) { IMPL.setFitsSystemWindows(view, fitSystemWindows); } /** * On API 11 devices and above, call Drawable.jumpToCurrentState() * on all Drawable objects associated with this view. *

* On API 21 and above, also calls StateListAnimator#jumpToCurrentState() * if there is a StateListAnimator attached to this view. */ public static void jumpDrawablesToCurrentState(View v) { IMPL.jumpDrawablesToCurrentState(v); } /** * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying * window insets to this view. This will only take effect on devices with API 21 or above. */ public static void setOnApplyWindowInsetsListener(View v, OnApplyWindowInsetsListener listener) { IMPL.setOnApplyWindowInsetsListener(v, listener); } /** * Controls whether the entire hierarchy under this view will save its * state when a state saving traversal occurs from its parent. * * @param enabled Set to false to disable state saving, or true * (the default) to allow it. */ public static void setSaveFromParentEnabled(View v, boolean enabled) { IMPL.setSaveFromParentEnabled(v, enabled); } /** * Changes the activated state of this view. A view can be activated or not. * Note that activation is not the same as selection. Selection is * a transient property, representing the view (hierarchy) the user is * currently interacting with. Activation is a longer-term state that the * user can move views in and out of. * * @param activated true if the view must be activated, false otherwise */ public static void setActivated(View view, boolean activated) { IMPL.setActivated(view, activated); } // TODO: getters for various view properties (rotation, etc) }