/* * Copyright (C) 2014 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 com.android.systemui.recents.views; import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.graphics.Rect; import android.graphics.RectF; import android.util.IntProperty; import android.util.Property; import android.view.View; import com.android.systemui.recents.misc.Utilities; import java.util.ArrayList; /** * The visual properties for a {@link TaskView}. */ public class TaskViewTransform { public static final Property<View, Rect> LTRB = new Property<View, Rect>(Rect.class, "leftTopRightBottom") { private Rect mTmpRect = new Rect(); @Override public void set(View v, Rect ltrb) { v.setLeftTopRightBottom(ltrb.left, ltrb.top, ltrb.right, ltrb.bottom); } @Override public Rect get(View v) { mTmpRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); return mTmpRect; } }; public float translationZ = 0; public float scale = 1f; public float alpha = 1f; public float dimAlpha = 0f; public float viewOutlineAlpha = 0f; public boolean visible = false; // This is a window-space rect used for positioning the task in the stack and freeform workspace public RectF rect = new RectF(); /** * Fills int this transform from the state of the given TaskView. */ public void fillIn(TaskView tv) { translationZ = tv.getTranslationZ(); scale = tv.getScaleX(); alpha = tv.getAlpha(); visible = true; dimAlpha = tv.getDimAlpha(); viewOutlineAlpha = tv.getViewBounds().getAlpha(); rect.set(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom()); } /** * Copies the transform state from another {@link TaskViewTransform}. */ public void copyFrom(TaskViewTransform other) { translationZ = other.translationZ; scale = other.scale; alpha = other.alpha; visible = other.visible; dimAlpha = other.dimAlpha; viewOutlineAlpha = other.viewOutlineAlpha; rect.set(other.rect); } /** * @return whether {@param other} is the same transform as this */ public boolean isSame(TaskViewTransform other) { return translationZ == other.translationZ && scale == other.scale && other.alpha == alpha && dimAlpha == other.dimAlpha && visible == other.visible && rect.equals(other.rect); } /** * Resets the current transform. */ public void reset() { translationZ = 0; scale = 1f; alpha = 1f; dimAlpha = 0f; viewOutlineAlpha = 0f; visible = false; rect.setEmpty(); } /** Convenience functions to compare against current property values */ public boolean hasAlphaChangedFrom(float v) { return (Float.compare(alpha, v) != 0); } public boolean hasScaleChangedFrom(float v) { return (Float.compare(scale, v) != 0); } public boolean hasTranslationZChangedFrom(float v) { return (Float.compare(translationZ, v) != 0); } public boolean hasRectChangedFrom(View v) { return ((int) rect.left != v.getLeft()) || ((int) rect.right != v.getRight()) || ((int) rect.top != v.getTop()) || ((int) rect.bottom != v.getBottom()); } /** * Applies this transform to a view. */ public void applyToTaskView(TaskView v, ArrayList<Animator> animators, AnimationProps animation, boolean allowShadows) { // Return early if not visible if (!visible) { return; } if (animation.isImmediate()) { if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) { v.setTranslationZ(translationZ); } if (hasScaleChangedFrom(v.getScaleX())) { v.setScaleX(scale); v.setScaleY(scale); } if (hasAlphaChangedFrom(v.getAlpha())) { v.setAlpha(alpha); } if (hasRectChangedFrom(v)) { v.setLeftTopRightBottom((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom); } } else { if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) { ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.TRANSLATION_Z, v.getTranslationZ(), translationZ); animators.add(animation.apply(AnimationProps.TRANSLATION_Z, anim)); } if (hasScaleChangedFrom(v.getScaleX())) { ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v, PropertyValuesHolder.ofFloat(View.SCALE_X, v.getScaleX(), scale), PropertyValuesHolder.ofFloat(View.SCALE_Y, v.getScaleX(), scale)); animators.add(animation.apply(AnimationProps.SCALE, anim)); } if (hasAlphaChangedFrom(v.getAlpha())) { ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.ALPHA, v.getAlpha(), alpha); animators.add(animation.apply(AnimationProps.ALPHA, anim)); } if (hasRectChangedFrom(v)) { Rect fromViewRect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); Rect toViewRect = new Rect(); rect.round(toViewRect); ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v, PropertyValuesHolder.ofObject(LTRB, Utilities.RECT_EVALUATOR, fromViewRect, toViewRect)); animators.add(animation.apply(AnimationProps.BOUNDS, anim)); } } } /** Reset the transform on a view. */ public static void reset(TaskView v) { v.setTranslationX(0f); v.setTranslationY(0f); v.setTranslationZ(0f); v.setScaleX(1f); v.setScaleY(1f); v.setAlpha(1f); v.getViewBounds().setClipBottom(0); v.setLeftTopRightBottom(0, 0, 0, 0); } @Override public String toString() { return "R: " + rect + " V: " + visible; } }