1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.base;
7 import android.animation.ValueAnimator;
8 import android.app.ActivityOptions;
9 import android.app.Notification;
10 import android.app.PendingIntent;
11 import android.content.Context;
12 import android.content.Intent;
13 import android.content.res.Configuration;
14 import android.graphics.drawable.Drawable;
15 import android.os.Build;
16 import android.os.Bundle;
17 import android.view.View;
18 import android.view.ViewGroup.MarginLayoutParams;
19 import android.view.ViewTreeObserver;
20 import android.widget.ImageView;
21 import android.widget.RemoteViews;
22 import android.widget.TextView;
25 * Utility class to use new APIs that were added after ICS (API level 14).
27 public class ApiCompatibilityUtils {
29 private static final String TAG = "ApiCompatibilityUtils";
31 private ApiCompatibilityUtils() {
35 * Returns true if view's layout direction is right-to-left.
37 * @param view the View whose layout is being considered
39 public static boolean isLayoutRtl(View view) {
40 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
41 return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
43 // All layouts are LTR before JB MR1.
49 * @see Configuration#getLayoutDirection()
51 public static int getLayoutDirection(Configuration configuration) {
52 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
53 return configuration.getLayoutDirection();
55 // All layouts are LTR before JB MR1.
56 return View.LAYOUT_DIRECTION_LTR;
61 * @return True if the running version of the Android supports printing.
63 public static boolean isPrintingSupported() {
64 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
68 * @return True if the running version of the Android supports HTML clipboard.
70 public static boolean isHTMLClipboardSupported() {
71 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
75 * @see android.view.View#setLayoutDirection(int)
77 public static void setLayoutDirection(View view, int layoutDirection) {
78 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
79 view.setLayoutDirection(layoutDirection);
81 // Do nothing. RTL layouts aren't supported before JB MR1.
86 * @see android.view.View#setTextDirection(int)
88 public static void setTextAlignment(View view, int textAlignment) {
89 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
90 view.setTextAlignment(textAlignment);
92 // Do nothing. RTL text isn't supported before JB MR1.
97 * @see android.view.ViewGroup.MarginLayoutParams#setMarginEnd(int)
99 public static void setMarginEnd(MarginLayoutParams layoutParams, int end) {
100 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
101 layoutParams.setMarginEnd(end);
103 layoutParams.rightMargin = end;
108 * @see android.view.ViewGroup.MarginLayoutParams#getMarginEnd()
110 public static int getMarginEnd(MarginLayoutParams layoutParams) {
111 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
112 return layoutParams.getMarginEnd();
114 return layoutParams.rightMargin;
119 * @see android.view.ViewGroup.MarginLayoutParams#setMarginStart(int)
121 public static void setMarginStart(MarginLayoutParams layoutParams, int start) {
122 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
123 layoutParams.setMarginStart(start);
125 layoutParams.leftMargin = start;
130 * @see android.view.ViewGroup.MarginLayoutParams#getMarginStart()
132 public static int getMarginStart(MarginLayoutParams layoutParams) {
133 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
134 return layoutParams.getMarginStart();
136 return layoutParams.leftMargin;
141 * @see android.view.View#setPaddingRelative(int, int, int, int)
143 public static void setPaddingRelative(View view, int start, int top, int end, int bottom) {
144 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
145 view.setPaddingRelative(start, top, end, bottom);
147 // Before JB MR1, all layouts are left-to-right, so start == left, etc.
148 view.setPadding(start, top, end, bottom);
153 * @see android.view.View#getPaddingStart()
155 public static int getPaddingStart(View view) {
156 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
157 return view.getPaddingStart();
159 // Before JB MR1, all layouts are left-to-right, so start == left.
160 return view.getPaddingLeft();
165 * @see android.view.View#getPaddingEnd()
167 public static int getPaddingEnd(View view) {
168 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
169 return view.getPaddingEnd();
171 // Before JB MR1, all layouts are left-to-right, so end == right.
172 return view.getPaddingRight();
177 * @see android.widget.TextView#setCompoundDrawablesRelative(Drawable, Drawable, Drawable,
180 public static void setCompoundDrawablesRelative(TextView textView, Drawable start, Drawable top,
181 Drawable end, Drawable bottom) {
182 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
183 // On JB MR1, due to a platform bug, setCompoundDrawablesRelative() is a no-op if the
184 // view has ever been measured. As a workaround, use setCompoundDrawables() directly.
185 // See: http://crbug.com/368196 and http://crbug.com/361709
186 boolean isRtl = isLayoutRtl(textView);
187 textView.setCompoundDrawables(isRtl ? end : start, top, isRtl ? start : end, bottom);
188 } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
189 textView.setCompoundDrawablesRelative(start, top, end, bottom);
191 textView.setCompoundDrawables(start, top, end, bottom);
196 * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,
197 * Drawable, Drawable, Drawable)
199 public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
200 Drawable start, Drawable top, Drawable end, Drawable bottom) {
201 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
202 // Work around the platform bug described in setCompoundDrawablesRelative() above.
203 boolean isRtl = isLayoutRtl(textView);
204 textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
205 isRtl ? start : end, bottom);
206 } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
207 textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
209 textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
214 * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int,
217 public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
218 int start, int top, int end, int bottom) {
219 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
220 // Work around the platform bug described in setCompoundDrawablesRelative() above.
221 boolean isRtl = isLayoutRtl(textView);
222 textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
223 isRtl ? start : end, bottom);
224 } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
225 textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
227 textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
232 * @see android.view.View#postInvalidateOnAnimation()
234 public static void postInvalidateOnAnimation(View view) {
235 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
236 view.postInvalidateOnAnimation();
238 view.postInvalidate();
243 * @see android.view.View#postOnAnimation()
245 public static void postOnAnimation(View view, Runnable action) {
246 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
247 view.postOnAnimation(action);
249 view.postDelayed(action, getFrameTime());
254 * @see android.view.View#postOnAnimationDelayed()
256 public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
257 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
258 view.postOnAnimationDelayed(action, delayMillis);
260 view.postDelayed(action, getFrameTime() + delayMillis);
264 private static long getFrameTime() {
265 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
266 return ValueAnimator.getFrameDelay();
268 // Any reasonable fake frame delay will have to do.
274 * @see android.widget.RemoteViews#setContentDescription(int, CharSequence)
276 public static void setContentDescriptionForRemoteView(RemoteViews remoteViews, int viewId,
277 CharSequence contentDescription) {
278 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
279 remoteViews.setContentDescription(viewId, contentDescription);
281 // setContentDescription() is unavailable in earlier versions.
286 * @see android.app.Activity#startActivity(Intent, Bundle)
288 public static void startActivity(Context context, Intent intent, Bundle options) {
289 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
290 context.startActivity(intent, options);
292 context.startActivity(intent);
297 * @see android.app.ActivityOptions#toBundle()
299 public static Bundle toBundle(ActivityOptions options) {
300 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
301 return options.toBundle();
307 // These methods have a new name, and the old name is deprecated.
310 * @see android.view.View#setBackground(Drawable)
312 @SuppressWarnings("deprecation")
313 public static void setBackgroundForView(View view, Drawable drawable) {
314 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
315 view.setBackground(drawable);
317 view.setBackgroundDrawable(drawable);
322 * @see android.view.ViewTreeObserver#removeOnGlobalLayoutListener()
324 @SuppressWarnings("deprecation")
325 public static void removeOnGlobalLayoutListener(
326 View view, ViewTreeObserver.OnGlobalLayoutListener listener) {
327 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
328 view.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
330 view.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
335 * @see android.widget.ImageView#setImageAlpha(int)
337 @SuppressWarnings("deprecation")
338 public static void setImageAlpha(ImageView iv, int alpha) {
339 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
340 iv.setImageAlpha(alpha);
347 * @see android.app.PendingIntent#getCreatorPackage()
349 @SuppressWarnings("deprecation")
350 public static String getCreatorPackage(PendingIntent intent) {
351 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
352 return intent.getCreatorPackage();
354 return intent.getTargetPackage();
359 * @see android.app.Notification.Builder#setLocalOnly(boolean)
361 @SuppressWarnings("deprecation")
362 public static Notification build(Notification.Builder builder) {
363 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
364 return builder.build();
366 return builder.getNotification();