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 17 package com.android.systemui.recents.views; 18 19 import android.animation.Animator; 20 import android.animation.ObjectAnimator; 21 import android.animation.PropertyValuesHolder; 22 import android.graphics.Rect; 23 import android.graphics.RectF; 24 import android.util.IntProperty; 25 import android.util.Property; 26 import android.view.View; 27 28 import com.android.systemui.recents.misc.Utilities; 29 30 import java.util.ArrayList; 31 32 /** 33 * The visual properties for a {@link TaskView}. 34 */ 35 public class TaskViewTransform { 36 37 public static final Property<View, Rect> LTRB = 38 new Property<View, Rect>(Rect.class, "leftTopRightBottom") { 39 40 private Rect mTmpRect = new Rect(); 41 42 @Override 43 public void set(View v, Rect ltrb) { 44 v.setLeftTopRightBottom(ltrb.left, ltrb.top, ltrb.right, ltrb.bottom); 45 } 46 47 @Override 48 public Rect get(View v) { 49 mTmpRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); 50 return mTmpRect; 51 } 52 }; 53 54 public float translationZ = 0; 55 public float scale = 1f; 56 public float alpha = 1f; 57 public float dimAlpha = 0f; 58 public float viewOutlineAlpha = 0f; 59 60 public boolean visible = false; 61 62 // This is a window-space rect used for positioning the task in the stack and freeform workspace 63 public RectF rect = new RectF(); 64 65 /** 66 * Fills int this transform from the state of the given TaskView. 67 */ fillIn(TaskView tv)68 public void fillIn(TaskView tv) { 69 translationZ = tv.getTranslationZ(); 70 scale = tv.getScaleX(); 71 alpha = tv.getAlpha(); 72 visible = true; 73 dimAlpha = tv.getDimAlpha(); 74 viewOutlineAlpha = tv.getViewBounds().getAlpha(); 75 rect.set(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom()); 76 } 77 78 /** 79 * Copies the transform state from another {@link TaskViewTransform}. 80 */ copyFrom(TaskViewTransform other)81 public void copyFrom(TaskViewTransform other) { 82 translationZ = other.translationZ; 83 scale = other.scale; 84 alpha = other.alpha; 85 visible = other.visible; 86 dimAlpha = other.dimAlpha; 87 viewOutlineAlpha = other.viewOutlineAlpha; 88 rect.set(other.rect); 89 } 90 91 /** 92 * @return whether {@param other} is the same transform as this 93 */ isSame(TaskViewTransform other)94 public boolean isSame(TaskViewTransform other) { 95 return translationZ == other.translationZ 96 && scale == other.scale 97 && other.alpha == alpha 98 && dimAlpha == other.dimAlpha 99 && visible == other.visible 100 && rect.equals(other.rect); 101 } 102 103 /** 104 * Resets the current transform. 105 */ reset()106 public void reset() { 107 translationZ = 0; 108 scale = 1f; 109 alpha = 1f; 110 dimAlpha = 0f; 111 viewOutlineAlpha = 0f; 112 visible = false; 113 rect.setEmpty(); 114 } 115 116 /** Convenience functions to compare against current property values */ hasAlphaChangedFrom(float v)117 public boolean hasAlphaChangedFrom(float v) { 118 return (Float.compare(alpha, v) != 0); 119 } 120 hasScaleChangedFrom(float v)121 public boolean hasScaleChangedFrom(float v) { 122 return (Float.compare(scale, v) != 0); 123 } 124 hasTranslationZChangedFrom(float v)125 public boolean hasTranslationZChangedFrom(float v) { 126 return (Float.compare(translationZ, v) != 0); 127 } 128 hasRectChangedFrom(View v)129 public boolean hasRectChangedFrom(View v) { 130 return ((int) rect.left != v.getLeft()) || ((int) rect.right != v.getRight()) || 131 ((int) rect.top != v.getTop()) || ((int) rect.bottom != v.getBottom()); 132 } 133 134 /** 135 * Applies this transform to a view. 136 */ applyToTaskView(TaskView v, ArrayList<Animator> animators, AnimationProps animation, boolean allowShadows)137 public void applyToTaskView(TaskView v, ArrayList<Animator> animators, 138 AnimationProps animation, boolean allowShadows) { 139 // Return early if not visible 140 if (!visible) { 141 return; 142 } 143 144 if (animation.isImmediate()) { 145 if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) { 146 v.setTranslationZ(translationZ); 147 } 148 if (hasScaleChangedFrom(v.getScaleX())) { 149 v.setScaleX(scale); 150 v.setScaleY(scale); 151 } 152 if (hasAlphaChangedFrom(v.getAlpha())) { 153 v.setAlpha(alpha); 154 } 155 if (hasRectChangedFrom(v)) { 156 v.setLeftTopRightBottom((int) rect.left, (int) rect.top, (int) rect.right, 157 (int) rect.bottom); 158 } 159 } else { 160 if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) { 161 ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.TRANSLATION_Z, 162 v.getTranslationZ(), translationZ); 163 animators.add(animation.apply(AnimationProps.TRANSLATION_Z, anim)); 164 } 165 if (hasScaleChangedFrom(v.getScaleX())) { 166 ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v, 167 PropertyValuesHolder.ofFloat(View.SCALE_X, v.getScaleX(), scale), 168 PropertyValuesHolder.ofFloat(View.SCALE_Y, v.getScaleX(), scale)); 169 animators.add(animation.apply(AnimationProps.SCALE, anim)); 170 } 171 if (hasAlphaChangedFrom(v.getAlpha())) { 172 ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.ALPHA, v.getAlpha(), alpha); 173 animators.add(animation.apply(AnimationProps.ALPHA, anim)); 174 } 175 if (hasRectChangedFrom(v)) { 176 Rect fromViewRect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); 177 Rect toViewRect = new Rect(); 178 rect.round(toViewRect); 179 ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v, 180 PropertyValuesHolder.ofObject(LTRB, Utilities.RECT_EVALUATOR, 181 fromViewRect, toViewRect)); 182 animators.add(animation.apply(AnimationProps.BOUNDS, anim)); 183 } 184 } 185 } 186 187 /** Reset the transform on a view. */ reset(TaskView v)188 public static void reset(TaskView v) { 189 v.setTranslationX(0f); 190 v.setTranslationY(0f); 191 v.setTranslationZ(0f); 192 v.setScaleX(1f); 193 v.setScaleY(1f); 194 v.setAlpha(1f); 195 v.getViewBounds().setClipBottom(0); 196 v.setLeftTopRightBottom(0, 0, 0, 0); 197 } 198 199 @Override toString()200 public String toString() { 201 return "R: " + rect + " V: " + visible; 202 } 203 } 204