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#setTextAlignment(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.View#setTextDirection(int)
99 public static void setTextDirection(View view, int textDirection) {
100 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
101 view.setTextDirection(textDirection);
103 // Do nothing. RTL text isn't supported before JB MR1.
108 * @see android.view.ViewGroup.MarginLayoutParams#setMarginEnd(int)
110 public static void setMarginEnd(MarginLayoutParams layoutParams, int end) {
111 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
112 layoutParams.setMarginEnd(end);
114 layoutParams.rightMargin = end;
119 * @see android.view.ViewGroup.MarginLayoutParams#getMarginEnd()
121 public static int getMarginEnd(MarginLayoutParams layoutParams) {
122 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
123 return layoutParams.getMarginEnd();
125 return layoutParams.rightMargin;
130 * @see android.view.ViewGroup.MarginLayoutParams#setMarginStart(int)
132 public static void setMarginStart(MarginLayoutParams layoutParams, int start) {
133 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
134 layoutParams.setMarginStart(start);
136 layoutParams.leftMargin = start;
141 * @see android.view.ViewGroup.MarginLayoutParams#getMarginStart()
143 public static int getMarginStart(MarginLayoutParams layoutParams) {
144 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
145 return layoutParams.getMarginStart();
147 return layoutParams.leftMargin;
152 * @see android.view.View#setPaddingRelative(int, int, int, int)
154 public static void setPaddingRelative(View view, int start, int top, int end, int bottom) {
155 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
156 view.setPaddingRelative(start, top, end, bottom);
158 // Before JB MR1, all layouts are left-to-right, so start == left, etc.
159 view.setPadding(start, top, end, bottom);
164 * @see android.view.View#getPaddingStart()
166 public static int getPaddingStart(View view) {
167 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
168 return view.getPaddingStart();
170 // Before JB MR1, all layouts are left-to-right, so start == left.
171 return view.getPaddingLeft();
176 * @see android.view.View#getPaddingEnd()
178 public static int getPaddingEnd(View view) {
179 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
180 return view.getPaddingEnd();
182 // Before JB MR1, all layouts are left-to-right, so end == right.
183 return view.getPaddingRight();
188 * @see android.widget.TextView#setCompoundDrawablesRelative(Drawable, Drawable, Drawable,
191 public static void setCompoundDrawablesRelative(TextView textView, Drawable start, Drawable top,
192 Drawable end, Drawable bottom) {
193 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
194 // On JB MR1, due to a platform bug, setCompoundDrawablesRelative() is a no-op if the
195 // view has ever been measured. As a workaround, use setCompoundDrawables() directly.
196 // See: http://crbug.com/368196 and http://crbug.com/361709
197 boolean isRtl = isLayoutRtl(textView);
198 textView.setCompoundDrawables(isRtl ? end : start, top, isRtl ? start : end, bottom);
199 } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
200 textView.setCompoundDrawablesRelative(start, top, end, bottom);
202 textView.setCompoundDrawables(start, top, end, bottom);
207 * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,
208 * Drawable, Drawable, Drawable)
210 public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
211 Drawable start, Drawable top, Drawable end, Drawable bottom) {
212 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
213 // Work around the platform bug described in setCompoundDrawablesRelative() above.
214 boolean isRtl = isLayoutRtl(textView);
215 textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
216 isRtl ? start : end, bottom);
217 } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
218 textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
220 textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
225 * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int,
228 public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
229 int start, int top, int end, int bottom) {
230 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
231 // Work around the platform bug described in setCompoundDrawablesRelative() above.
232 boolean isRtl = isLayoutRtl(textView);
233 textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
234 isRtl ? start : end, bottom);
235 } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
236 textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
238 textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
243 * @see android.view.View#postInvalidateOnAnimation()
245 public static void postInvalidateOnAnimation(View view) {
246 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
247 view.postInvalidateOnAnimation();
249 view.postInvalidate();
254 * @see android.view.View#postOnAnimation()
256 public static void postOnAnimation(View view, Runnable action) {
257 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
258 view.postOnAnimation(action);
260 view.postDelayed(action, getFrameTime());
265 * @see android.view.View#postOnAnimationDelayed()
267 public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
268 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
269 view.postOnAnimationDelayed(action, delayMillis);
271 view.postDelayed(action, getFrameTime() + delayMillis);
275 private static long getFrameTime() {
276 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
277 return ValueAnimator.getFrameDelay();
279 // Any reasonable fake frame delay will have to do.
285 * @see android.widget.RemoteViews#setContentDescription(int, CharSequence)
287 public static void setContentDescriptionForRemoteView(RemoteViews remoteViews, int viewId,
288 CharSequence contentDescription) {
289 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
290 remoteViews.setContentDescription(viewId, contentDescription);
292 // setContentDescription() is unavailable in earlier versions.
297 * @see android.app.Activity#startActivity(Intent, Bundle)
299 public static void startActivity(Context context, Intent intent, Bundle options) {
300 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
301 context.startActivity(intent, options);
303 context.startActivity(intent);
308 * @see android.app.ActivityOptions#toBundle()
310 public static Bundle toBundle(ActivityOptions options) {
311 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
312 return options.toBundle();
318 // These methods have a new name, and the old name is deprecated.
321 * @see android.view.View#setBackground(Drawable)
323 @SuppressWarnings("deprecation")
324 public static void setBackgroundForView(View view, Drawable drawable) {
325 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
326 view.setBackground(drawable);
328 view.setBackgroundDrawable(drawable);
333 * @see android.view.ViewTreeObserver#removeOnGlobalLayoutListener()
335 @SuppressWarnings("deprecation")
336 public static void removeOnGlobalLayoutListener(
337 View view, ViewTreeObserver.OnGlobalLayoutListener listener) {
338 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
339 view.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
341 view.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
346 * @see android.widget.ImageView#setImageAlpha(int)
348 @SuppressWarnings("deprecation")
349 public static void setImageAlpha(ImageView iv, int alpha) {
350 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
351 iv.setImageAlpha(alpha);
358 * @see android.app.PendingIntent#getCreatorPackage()
360 @SuppressWarnings("deprecation")
361 public static String getCreatorPackage(PendingIntent intent) {
362 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
363 return intent.getCreatorPackage();
365 return intent.getTargetPackage();
370 * @see android.app.Notification.Builder#setLocalOnly(boolean)
372 @SuppressWarnings("deprecation")
373 public static Notification build(Notification.Builder builder) {
374 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
375 return builder.build();
377 return builder.getNotification();