Utilities.java revision 59924fe0d9136cf349759bea1e06b661603f95fe
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.systemui.recents.misc; 18 19import android.animation.Animator; 20import android.animation.AnimatorSet; 21import android.annotation.FloatRange; 22import android.content.res.Resources; 23import android.graphics.Color; 24import android.graphics.Rect; 25import android.graphics.RectF; 26import android.graphics.drawable.Drawable; 27import android.util.ArraySet; 28import android.util.IntProperty; 29import android.util.Property; 30import android.util.TypedValue; 31import android.view.View; 32import android.view.ViewParent; 33 34import com.android.systemui.recents.model.Task; 35import com.android.systemui.recents.views.TaskViewTransform; 36 37import java.util.ArrayList; 38import java.util.Collections; 39import java.util.List; 40 41/* Common code */ 42public class Utilities { 43 44 public static final Property<Drawable, Integer> DRAWABLE_ALPHA = 45 new IntProperty<Drawable>("drawableAlpha") { 46 @Override 47 public void setValue(Drawable object, int alpha) { 48 object.setAlpha(alpha); 49 } 50 51 @Override 52 public Integer get(Drawable object) { 53 return object.getAlpha(); 54 } 55 }; 56 57 public static final Property<Drawable, Rect> DRAWABLE_RECT = 58 new Property<Drawable, Rect>(Rect.class, "drawableBounds") { 59 @Override 60 public void set(Drawable object, Rect bounds) { 61 object.setBounds(bounds); 62 } 63 64 @Override 65 public Rect get(Drawable object) { 66 return object.getBounds(); 67 } 68 }; 69 70 public static final RectFEvaluator RECTF_EVALUATOR = new RectFEvaluator(); 71 72 public static final Rect EMPTY_RECT = new Rect(); 73 74 /** 75 * @return the first parent walking up the view hierarchy that has the given class type. 76 * 77 * @param parentClass must be a class derived from {@link View} 78 */ 79 public static <T extends View> T findParent(View v, Class<T> parentClass) { 80 ViewParent parent = v.getParent(); 81 while (parent != null) { 82 if (parent.getClass().equals(parentClass)) { 83 return (T) parent; 84 } 85 parent = parent.getParent(); 86 } 87 return null; 88 } 89 90 /** 91 * Initializes the {@param setOut} with the given object. 92 */ 93 public static <T> ArraySet<T> objectToSet(T obj, ArraySet<T> setOut) { 94 setOut.clear(); 95 if (obj != null) { 96 setOut.add(obj); 97 } 98 return setOut; 99 } 100 101 /** 102 * Replaces the contents of {@param setOut} with the contents of the {@param array}. 103 */ 104 public static <T> ArraySet<T> arrayToSet(T[] array, ArraySet<T> setOut) { 105 setOut.clear(); 106 if (array != null) { 107 Collections.addAll(setOut, array); 108 } 109 return setOut; 110 } 111 112 /** 113 * @return the clamped {@param value} between the provided {@param min} and {@param max}. 114 */ 115 public static float clamp(float value, float min, float max) { 116 return Math.max(min, Math.min(max, value)); 117 } 118 119 /** 120 * @return the clamped {@param value} between the provided {@param min} and {@param max}. 121 */ 122 public static int clamp(int value, int min, int max) { 123 return Math.max(min, Math.min(max, value)); 124 } 125 126 /** 127 * @return the clamped {@param value} between 0 and 1. 128 */ 129 public static float clamp01(float value) { 130 return Math.max(0f, Math.min(1f, value)); 131 } 132 133 /** 134 * Scales the {@param value} to be proportionally between the {@param min} and 135 * {@param max} values. 136 * 137 * @param value must be between 0 and 1 138 */ 139 public static float mapRange(@FloatRange(from=0.0,to=1.0) float value, float min, float max) { 140 return min + (value * (max - min)); 141 } 142 143 /** 144 * Scales the {@param value} proportionally from {@param min} and {@param max} to 0 and 1. 145 * 146 * @param value must be between {@param min} and {@param max} 147 */ 148 public static float unmapRange(float value, float min, float max) { 149 return (value - min) / (max - min); 150 } 151 152 /** Scales a rect about its centroid */ 153 public static void scaleRectAboutCenter(RectF r, float scale) { 154 if (scale != 1.0f) { 155 float cx = r.centerX(); 156 float cy = r.centerY(); 157 r.offset(-cx, -cy); 158 r.left *= scale; 159 r.top *= scale; 160 r.right *= scale; 161 r.bottom *= scale; 162 r.offset(cx, cy); 163 } 164 } 165 166 /** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */ 167 public static float computeContrastBetweenColors(int bg, int fg) { 168 float bgR = Color.red(bg) / 255f; 169 float bgG = Color.green(bg) / 255f; 170 float bgB = Color.blue(bg) / 255f; 171 bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f); 172 bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f); 173 bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f); 174 float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB; 175 176 float fgR = Color.red(fg) / 255f; 177 float fgG = Color.green(fg) / 255f; 178 float fgB = Color.blue(fg) / 255f; 179 fgR = (fgR < 0.03928f) ? fgR / 12.92f : (float) Math.pow((fgR + 0.055f) / 1.055f, 2.4f); 180 fgG = (fgG < 0.03928f) ? fgG / 12.92f : (float) Math.pow((fgG + 0.055f) / 1.055f, 2.4f); 181 fgB = (fgB < 0.03928f) ? fgB / 12.92f : (float) Math.pow((fgB + 0.055f) / 1.055f, 2.4f); 182 float fgL = 0.2126f * fgR + 0.7152f * fgG + 0.0722f * fgB; 183 184 return Math.abs((fgL + 0.05f) / (bgL + 0.05f)); 185 } 186 187 /** Returns the base color overlaid with another overlay color with a specified alpha. */ 188 public static int getColorWithOverlay(int baseColor, int overlayColor, float overlayAlpha) { 189 return Color.rgb( 190 (int) (overlayAlpha * Color.red(baseColor) + 191 (1f - overlayAlpha) * Color.red(overlayColor)), 192 (int) (overlayAlpha * Color.green(baseColor) + 193 (1f - overlayAlpha) * Color.green(overlayColor)), 194 (int) (overlayAlpha * Color.blue(baseColor) + 195 (1f - overlayAlpha) * Color.blue(overlayColor))); 196 } 197 198 /** 199 * Cancels an animation ensuring that if it has listeners, onCancel and onEnd 200 * are not called. 201 */ 202 public static void cancelAnimationWithoutCallbacks(Animator animator) { 203 if (animator != null && animator.isStarted()) { 204 removeAnimationListenersRecursive(animator); 205 animator.cancel(); 206 } 207 } 208 209 /** 210 * Recursively removes all the listeners of all children of this animator 211 */ 212 public static void removeAnimationListenersRecursive(Animator animator) { 213 if (animator instanceof AnimatorSet) { 214 ArrayList<Animator> animators = ((AnimatorSet) animator).getChildAnimations(); 215 for (int i = animators.size() - 1; i >= 0; i--) { 216 removeAnimationListenersRecursive(animators.get(i)); 217 } 218 } 219 animator.removeAllListeners(); 220 } 221 222 /** 223 * Updates {@param transforms} to be the same size as {@param tasks}. 224 */ 225 public static void matchTaskListSize(List<Task> tasks, List<TaskViewTransform> transforms) { 226 // We can reuse the task transforms where possible to reduce object allocation 227 int taskTransformCount = transforms.size(); 228 int taskCount = tasks.size(); 229 if (taskTransformCount < taskCount) { 230 // If there are less transforms than tasks, then add as many transforms as necessary 231 for (int i = taskTransformCount; i < taskCount; i++) { 232 transforms.add(new TaskViewTransform()); 233 } 234 } else if (taskTransformCount > taskCount) { 235 // If there are more transforms than tasks, then just subset the transform list 236 transforms.subList(taskCount, taskTransformCount).clear(); 237 } 238 } 239 240 /** 241 * Used for debugging, converts DP to PX. 242 */ 243 public static float dpToPx(Resources res, float dp) { 244 return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics()); 245 } 246} 247