| /* |
| * Copyright (C) 2016 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.grid; |
| |
| import android.content.Context; |
| import android.content.res.Resources; |
| import android.graphics.Point; |
| import android.graphics.Rect; |
| import android.view.WindowManager; |
| |
| import com.android.systemui.R; |
| import com.android.systemui.recents.misc.Utilities; |
| import com.android.systemui.recents.views.TaskStackLayoutAlgorithm; |
| import com.android.systemui.recents.views.TaskViewTransform; |
| |
| public class TaskGridLayoutAlgorithm { |
| |
| private final String TAG = "TaskGridLayoutAlgorithm"; |
| private final int MAX_LAYOUT_TASK_COUNT = 8; |
| |
| /** The horizontal padding around the whole recents view. */ |
| private int mPaddingLeftRight; |
| /** The vertical padding around the whole recents view. */ |
| private int mPaddingTopBottom; |
| /** The padding between task views. */ |
| private int mPaddingTaskView; |
| |
| private Rect mDisplayRect; |
| private Rect mWindowRect; |
| private Point mScreenSize = new Point(); |
| |
| private Rect mTaskGridRect; |
| |
| /** The height, in pixels, of each task view's title bar. */ |
| private int mTitleBarHeight; |
| |
| /** The aspect ratio of each task thumbnail, without the title bar. */ |
| private float mAppAspectRatio; |
| private Rect mSystemInsets = new Rect(); |
| |
| /** |
| * When the amount of tasks is determined, the size and position of every task view can be |
| * decided. Each instance of TaskGridRectInfo store the task view information for a certain |
| * amount of tasks. |
| */ |
| class TaskGridRectInfo { |
| Rect size; |
| int[] xOffsets; |
| int[] yOffsets; |
| |
| public TaskGridRectInfo(int taskCount) { |
| size = new Rect(); |
| xOffsets = new int[taskCount]; |
| yOffsets = new int[taskCount]; |
| |
| int layoutTaskCount = Math.min(MAX_LAYOUT_TASK_COUNT, taskCount); |
| |
| int tasksPerLine = layoutTaskCount < 2 ? 1 : ( |
| layoutTaskCount < 5 ? 2 : ( |
| layoutTaskCount < 7 ? 3 : 4)); |
| int lines = layoutTaskCount < 3 ? 1 : 2; |
| |
| int taskWidth, taskHeight; |
| int maxTaskWidth = (mDisplayRect.width() - 2 * mPaddingLeftRight |
| - (tasksPerLine - 1) * mPaddingTaskView) / tasksPerLine; |
| int maxTaskHeight = (mDisplayRect.height() - 2 * mPaddingTopBottom |
| - (lines - 1) * mPaddingTaskView) / lines; |
| |
| if (maxTaskHeight >= maxTaskWidth / mAppAspectRatio + mTitleBarHeight) { |
| // Width bound. |
| taskWidth = maxTaskWidth; |
| taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight); |
| } else { |
| // Height bound. |
| taskHeight = maxTaskHeight; |
| taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio); |
| } |
| size.set(0, 0, taskWidth, taskHeight); |
| |
| int emptySpaceX = mDisplayRect.width() - 2 * mPaddingLeftRight |
| - (tasksPerLine * taskWidth) - (tasksPerLine - 1) * mPaddingTaskView; |
| int emptySpaceY = mDisplayRect.height() - 2 * mPaddingTopBottom |
| - (lines * taskHeight) - (lines - 1) * mPaddingTaskView; |
| for (int taskIndex = 0; taskIndex < taskCount; taskIndex++) { |
| // We also need to invert the index in order to display the most recent tasks first. |
| int taskLayoutIndex = taskCount - taskIndex - 1; |
| |
| int xIndex = taskLayoutIndex % tasksPerLine; |
| int yIndex = taskLayoutIndex / tasksPerLine; |
| xOffsets[taskIndex] = |
| emptySpaceX / 2 + mPaddingLeftRight + (taskWidth + mPaddingTaskView) * xIndex; |
| yOffsets[taskIndex] = |
| emptySpaceY / 2 + mPaddingTopBottom + (taskHeight + mPaddingTaskView) * yIndex; |
| } |
| } |
| } |
| |
| /** |
| * We can find task view sizes and positions from mTaskGridRectInfoList[k - 1] when there |
| * are k tasks. |
| */ |
| TaskGridRectInfo[] mTaskGridRectInfoList; |
| |
| public TaskGridLayoutAlgorithm(Context context) { |
| reloadOnConfigurationChange(context); |
| } |
| |
| public void reloadOnConfigurationChange(Context context) { |
| Resources res = context.getResources(); |
| mPaddingLeftRight = res.getDimensionPixelSize(R.dimen.recents_grid_padding_left_right); |
| mPaddingTopBottom = res.getDimensionPixelSize(R.dimen.recents_grid_padding_top_bottom); |
| mPaddingTaskView = res.getDimensionPixelSize(R.dimen.recents_grid_padding_task_view); |
| |
| mTaskGridRect = new Rect(); |
| mTitleBarHeight = res.getDimensionPixelSize(R.dimen.recents_grid_task_view_header_height); |
| |
| WindowManager windowManager = (WindowManager) context |
| .getSystemService(Context.WINDOW_SERVICE); |
| windowManager.getDefaultDisplay().getRealSize(mScreenSize); |
| |
| updateAppAspectRatio(); |
| } |
| |
| public TaskViewTransform getTransform(int taskIndex, int taskCount, |
| TaskViewTransform transformOut, TaskStackLayoutAlgorithm stackLayout) { |
| |
| TaskGridRectInfo gridInfo = mTaskGridRectInfoList[taskCount - 1]; |
| mTaskGridRect.set(gridInfo.size); |
| |
| int x = gridInfo.xOffsets[taskIndex]; |
| int y = gridInfo.yOffsets[taskIndex]; |
| float z = stackLayout.mMaxTranslationZ; |
| |
| float dimAlpha = 0f; |
| float viewOutlineAlpha = 0f; |
| // We also need to invert the index in order to display the most recent tasks first. |
| int taskLayoutIndex = taskCount - taskIndex - 1; |
| boolean isTaskViewVisible = (taskLayoutIndex < MAX_LAYOUT_TASK_COUNT); |
| |
| // Fill out the transform |
| transformOut.scale = 1f; |
| transformOut.alpha = isTaskViewVisible ? 1f : 0f; |
| transformOut.translationZ = z; |
| transformOut.dimAlpha = dimAlpha; |
| transformOut.viewOutlineAlpha = viewOutlineAlpha; |
| transformOut.rect.set(mTaskGridRect); |
| transformOut.rect.offset(x, y); |
| Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale); |
| // We only show the 8 most recent tasks. |
| transformOut.visible = isTaskViewVisible; |
| return transformOut; |
| } |
| |
| public void initialize(Rect displayRect, Rect windowRect) { |
| mDisplayRect = displayRect; |
| mWindowRect = windowRect; |
| |
| // Pre-calculate the positions and offsets of task views so that we can reuse them directly |
| // in the future. |
| mTaskGridRectInfoList = new TaskGridRectInfo[MAX_LAYOUT_TASK_COUNT]; |
| for (int i = 0; i < MAX_LAYOUT_TASK_COUNT; i++) { |
| mTaskGridRectInfoList[i] = new TaskGridRectInfo(i + 1); |
| } |
| } |
| |
| public void setSystemInsets(Rect systemInsets) { |
| mSystemInsets = systemInsets; |
| updateAppAspectRatio(); |
| } |
| |
| private void updateAppAspectRatio() { |
| int usableWidth = mScreenSize.x - mSystemInsets.left - mSystemInsets.right; |
| int usableHeight = mScreenSize.y - mSystemInsets.top - mSystemInsets.bottom; |
| mAppAspectRatio = (float) usableWidth / (float) usableHeight; |
| } |
| |
| public Rect getStackActionButtonRect() { |
| Rect buttonRect = new Rect(mDisplayRect); |
| buttonRect.right -= mPaddingLeftRight; |
| buttonRect.left += mPaddingLeftRight; |
| buttonRect.bottom = buttonRect.top + mPaddingTopBottom; |
| return buttonRect; |
| } |
| |
| public Rect getTaskGridRect() { |
| return mTaskGridRect; |
| } |
| } |