TaskGridLayoutAlgorithm.java revision bf8e290376b8ee6d04c330b22f5275e82103def3
1bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet/* 2bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * Copyright (C) 2016 The Android Open Source Project 3bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * 4bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * Licensed under the Apache License, Version 2.0 (the "License"); 5bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * you may not use this file except in compliance with the License. 6bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * You may obtain a copy of the License at 7bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * 8bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * http://www.apache.org/licenses/LICENSE-2.0 9bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * 10bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * Unless required by applicable law or agreed to in writing, software 11bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * distributed under the License is distributed on an "AS IS" BASIS, 12bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * See the License for the specific language governing permissions and 14bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet * limitations under the License. 15bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet */ 16bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 17bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetpackage com.android.systemui.recents.views.grid; 18bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 19bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport android.content.Context; 20bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport android.content.res.Resources; 21bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport android.graphics.Point; 22bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport android.graphics.Rect; 23bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport android.view.WindowManager; 24bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 25bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport com.android.systemui.R; 26bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport com.android.systemui.recents.misc.Utilities; 27bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport com.android.systemui.recents.views.TaskStackLayoutAlgorithm; 28bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetimport com.android.systemui.recents.views.TaskViewTransform; 29bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 30bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornetpublic class TaskGridLayoutAlgorithm { 31bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 32bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private final String TAG = "TaskGridLayoutAlgorithm"; 33bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private final int MAX_LAYOUT_TASK_COUNT = 8; 34bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 35bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet /** The horizontal padding around the whole recents view. */ 36bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private int mPaddingLeftRight; 37bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet /** The vertical padding around the whole recents view. */ 38bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private int mPaddingTopBottom; 39bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet /** The padding between task views. */ 40bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private int mPaddingTaskView; 41bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 42bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private Rect mDisplayRect; 43bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private Rect mWindowRect; 44bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private Point mScreenSize = new Point(); 45bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 46bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private Rect mTaskGridRect; 47bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 48bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet /** The height, in pixels, of each task view's title bar. */ 49bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private int mTitleBarHeight; 50bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 51bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet /** The aspect ratio of each task thumbnail, without the title bar. */ 52bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private float mAppAspectRatio; 53bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private Rect mSystemInsets = new Rect(); 54bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 55bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet public TaskGridLayoutAlgorithm(Context context) { 56bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet reloadOnConfigurationChange(context); 57bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 58bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 59bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet public void reloadOnConfigurationChange(Context context) { 60bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet Resources res = context.getResources(); 61bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mPaddingLeftRight = res.getDimensionPixelSize(R.dimen.recents_grid_padding_left_right); 62bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mPaddingTopBottom = res.getDimensionPixelSize(R.dimen.recents_grid_padding_top_bottom); 63bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mPaddingTaskView = res.getDimensionPixelSize(R.dimen.recents_grid_padding_task_view); 64bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 65bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mTaskGridRect = new Rect(); 66bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mTitleBarHeight = res.getDimensionPixelSize(R.dimen.recents_grid_task_view_header_height); 67bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 68bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet WindowManager windowManager = (WindowManager) context 69bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet .getSystemService(Context.WINDOW_SERVICE); 70bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet windowManager.getDefaultDisplay().getRealSize(mScreenSize); 71bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 72bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet updateAppAspectRatio(); 73bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 74bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 75bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet public TaskViewTransform getTransform(int taskIndex, int taskCount, 76bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet TaskViewTransform transformOut, TaskStackLayoutAlgorithm stackLayout) { 77bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 78bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int layoutTaskCount = Math.min(MAX_LAYOUT_TASK_COUNT, taskCount); 79bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 80bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet // We also need to invert the index in order to display the most recent tasks first. 81bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int taskLayoutIndex = taskCount - taskIndex - 1; 82bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 83bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int tasksPerLine = layoutTaskCount < 2 ? 1 : ( 84bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet layoutTaskCount < 5 ? 2 : ( 85bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet layoutTaskCount < 7 ? 3 : 4)); 86bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int lines = layoutTaskCount < 3 ? 1 : 2; 87bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 88bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int taskWidth, taskHeight; 89bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int maxTaskWidth = (mDisplayRect.width() - 2 * mPaddingLeftRight 90bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet - (tasksPerLine - 1) * mPaddingTaskView) / tasksPerLine; 91bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int maxTaskHeight = (mDisplayRect.height() - 2 * mPaddingTopBottom 92bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet - (lines - 1) * mPaddingTaskView) / lines; 93bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 94bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet if (maxTaskHeight >= maxTaskWidth / mAppAspectRatio + mTitleBarHeight) { 95bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet // Width bound. 96bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet taskWidth = maxTaskWidth; 97bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight); 98bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } else { 99bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet // Height bound. 100bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet taskHeight = maxTaskHeight; 101bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio); 102bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 103bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int emptySpaceX = mDisplayRect.width() - 2 * mPaddingLeftRight 104bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet - (tasksPerLine * taskWidth) - (tasksPerLine - 1) * mPaddingTaskView; 105bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int emptySpaceY = mDisplayRect.height() - 2 * mPaddingTopBottom 106bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet - (lines * taskHeight) - (lines - 1) * mPaddingTaskView; 107bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 108bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mTaskGridRect.set(0, 0, taskWidth, taskHeight); 109bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 110bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int xIndex = taskLayoutIndex % tasksPerLine; 111bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int yIndex = taskLayoutIndex / tasksPerLine; 112bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int x = emptySpaceX / 2 + mPaddingLeftRight + (taskWidth + mPaddingTaskView) * xIndex; 113bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int y = emptySpaceY / 2 + mPaddingTopBottom + (taskHeight + mPaddingTaskView) * yIndex; 114bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet float z = stackLayout.mMaxTranslationZ; 115bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 116bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet float dimAlpha = 0f; 117bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet float viewOutlineAlpha = 0f; 118bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet boolean isTaskViewVisible = (taskLayoutIndex < MAX_LAYOUT_TASK_COUNT); 119bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 120bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet // Fill out the transform 121bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet transformOut.scale = 1f; 122bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet transformOut.alpha = isTaskViewVisible ? 1f : 0f; 123bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet transformOut.translationZ = z; 124bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet transformOut.dimAlpha = dimAlpha; 125bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet transformOut.viewOutlineAlpha = viewOutlineAlpha; 126bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet transformOut.rect.set(mTaskGridRect); 127bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet transformOut.rect.offset(x, y); 128bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale); 129bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet // We only show the 8 most recent tasks. 130bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet transformOut.visible = isTaskViewVisible; 131bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet return transformOut; 132bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 133bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 134bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet public void initialize(Rect displayRect, Rect windowRect) { 135bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mDisplayRect = displayRect; 136bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mWindowRect = windowRect; 137bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 138bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 139bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet public void setSystemInsets(Rect systemInsets) { 140bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mSystemInsets = systemInsets; 141bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet updateAppAspectRatio(); 142bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 143bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 144bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet private void updateAppAspectRatio() { 145bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int usableWidth = mScreenSize.x - mSystemInsets.left - mSystemInsets.right; 146bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet int usableHeight = mScreenSize.y - mSystemInsets.top - mSystemInsets.bottom; 147bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet mAppAspectRatio = (float) usableWidth / (float) usableHeight; 148bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 149bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet 150bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet public Rect getStackActionButtonRect() { 151bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet Rect buttonRect = new Rect(mDisplayRect); 152bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet buttonRect.right -= mPaddingLeftRight; 153bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet buttonRect.left += mPaddingLeftRight; 154bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet buttonRect.bottom = buttonRect.top + mPaddingTopBottom; 155bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet return buttonRect; 156bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet } 157bf8e290376b8ee6d04c330b22f5275e82103def3Manu Cornet} 158