TaskStackViewLayoutAlgorithm.java revision ffa2ec664479bff6b4b61d4c349d9db2cb37ca16
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.views; 18 19import android.graphics.Rect; 20import com.android.systemui.recents.Constants; 21import com.android.systemui.recents.RecentsConfiguration; 22import com.android.systemui.recents.misc.Utilities; 23 24/* The layout logic for a TaskStackView */ 25public class TaskStackViewLayoutAlgorithm { 26 27 // These are all going to change 28 static final float StackOverlapPct = 0.65f; // The overlap height relative to the task height 29 static final float StackPeekHeightPct = 0.1f; // The height of the peek space relative to the stack height 30 static final float StackPeekMinScale = 0.8f; // The min scale of the last card in the peek area 31 static final int StackPeekNumCards = 3; // The number of cards we see in the peek space 32 33 RecentsConfiguration mConfig; 34 35 // The various rects that define the stack view 36 Rect mRect = new Rect(); 37 Rect mStackRect = new Rect(); 38 Rect mStackRectSansPeek = new Rect(); 39 Rect mTaskRect = new Rect(); 40 41 // The min/max scroll 42 int mMinScroll; 43 int mMaxScroll; 44 45 public TaskStackViewLayoutAlgorithm(RecentsConfiguration config) { 46 mConfig = config; 47 } 48 49 /** Computes the stack and task rects */ 50 public void computeRects(int width, int height, int insetLeft, int insetBottom) { 51 // Note: We let the stack view be the full height because we want the cards to go under the 52 // navigation bar if possible. However, the stack rects which we use to calculate 53 // max scroll, etc. need to take the nav bar into account 54 55 // Compute the stack rects 56 mRect.set(0, 0, width, height); 57 mStackRect.set(mRect); 58 mStackRect.left += insetLeft; 59 mStackRect.bottom -= insetBottom; 60 61 int widthPadding = (int) (mConfig.taskStackWidthPaddingPct * mStackRect.width()); 62 int heightPadding = mConfig.taskStackTopPaddingPx; 63 if (Constants.DebugFlags.App.EnableSearchLayout) { 64 mStackRect.top += heightPadding; 65 mStackRect.left += widthPadding; 66 mStackRect.right -= widthPadding; 67 mStackRect.bottom -= heightPadding; 68 } else { 69 mStackRect.inset(widthPadding, heightPadding); 70 } 71 mStackRectSansPeek.set(mStackRect); 72 mStackRectSansPeek.top += StackPeekHeightPct * mStackRect.height(); 73 74 // Compute the task rect 75 int size = mStackRect.width(); 76 int left = mStackRect.left + (mStackRect.width() - size) / 2; 77 mTaskRect.set(left, mStackRectSansPeek.top, 78 left + size, mStackRectSansPeek.top + size); 79 } 80 81 void computeMinMaxScroll(int taskCount) { 82 // Compute the min and max scroll values 83 int numTasks = Math.max(1, taskCount); 84 int taskHeight = mTaskRect.height(); 85 int stackHeight = mStackRectSansPeek.height(); 86 int maxScrollHeight = taskHeight + getStackScrollForTaskIndex(numTasks - 1); 87 88 if (numTasks <= 1) { 89 // If there is only one task, then center the task in the stack rect (sans peek) 90 mMinScroll = mMaxScroll = -(stackHeight - taskHeight) / 2; 91 } else { 92 mMinScroll = Math.min(stackHeight, maxScrollHeight) - stackHeight; 93 mMaxScroll = maxScrollHeight - stackHeight; 94 } 95 } 96 97 /** Update/get the transform */ 98 public TaskViewTransform getStackTransform(int groupIndexInStack, int taskIndexInGroup, 99 int stackScroll, TaskViewTransform transformOut) { 100 // Return early if we have an invalid index 101 if (groupIndexInStack < 0) { 102 transformOut.reset(); 103 return transformOut; 104 } 105 106 // Map the items to an continuous position relative to the specified scroll 107 int numPeekCards = StackPeekNumCards; 108 float overlapHeight = StackOverlapPct * mTaskRect.height(); 109 float peekHeight = StackPeekHeightPct * mStackRect.height(); 110 float t = ((groupIndexInStack * overlapHeight) - stackScroll) / overlapHeight; 111 float boundedT = Math.max(t, -(numPeekCards + 1)); 112 113 // Set the scale relative to its position 114 int numFrontScaledCards = 3; 115 float minScale = StackPeekMinScale; 116 float scaleRange = 1f - minScale; 117 float scaleInc = scaleRange / (numPeekCards + numFrontScaledCards); 118 float scale = Math.max(minScale, Math.min(1f, minScale + 119 ((boundedT + (numPeekCards + 1)) * scaleInc))); 120 float scaleYOffset = ((1f - scale) * mTaskRect.height()) / 2; 121 transformOut.scale = scale; 122 123 // Set the y translation 124 if (boundedT < 0f) { 125 transformOut.translationY = (int) ((Math.max(-numPeekCards, boundedT) / 126 numPeekCards) * peekHeight - scaleYOffset); 127 } else { 128 transformOut.translationY = (int) (boundedT * overlapHeight - scaleYOffset); 129 } 130 transformOut.translationY += 100 * taskIndexInGroup; 131 132 // Set the z translation 133 int minZ = mConfig.taskViewTranslationZMinPx; 134 int incZ = mConfig.taskViewTranslationZIncrementPx; 135 transformOut.translationZ = (int) Math.max(minZ, minZ + ((boundedT + numPeekCards) * incZ)); 136 137 // Set the alphas 138 transformOut.dismissAlpha = Math.max(-1f, Math.min(0f, t + 1)) + 1f; 139 140 // Update the rect and visibility 141 transformOut.rect.set(mTaskRect); 142 if (t < -(numPeekCards + 1)) { 143 transformOut.visible = false; 144 } else { 145 transformOut.rect.offset(0, transformOut.translationY); 146 Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale); 147 transformOut.visible = Rect.intersects(mRect, transformOut.rect); 148 } 149 transformOut.t = t; 150 return transformOut; 151 } 152 153 /** 154 * Returns the overlap between one task and the next. 155 */ 156 float getTaskOverlapHeight() { 157 return StackOverlapPct * mTaskRect.height(); 158 } 159 160 /** 161 * Returns the scroll to such that the task transform at that index will have t=0. (If the scroll 162 * is not bounded) 163 */ 164 int getStackScrollForTaskIndex(int i) { 165 return (int) (i * getTaskOverlapHeight()); 166 } 167 168}