| /* |
| * Copyright (C) 2018 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.quickstep.util; |
| |
| import static java.lang.annotation.RetentionPolicy.SOURCE; |
| |
| import android.content.Context; |
| import android.content.res.Resources; |
| import android.graphics.Rect; |
| |
| import androidx.annotation.AnyThread; |
| import androidx.annotation.IntDef; |
| |
| import com.android.launcher3.DeviceProfile; |
| import com.android.launcher3.R; |
| import com.android.launcher3.config.FeatureFlags; |
| import com.android.quickstep.SysUINavigationMode; |
| |
| import java.lang.annotation.Retention; |
| |
| public class LayoutUtils { |
| |
| private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1; |
| private static final int MULTI_WINDOW_STRATEGY_DEVICE_PROFILE = 2; |
| |
| @Retention(SOURCE) |
| @IntDef({MULTI_WINDOW_STRATEGY_HALF_SCREEN, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE}) |
| private @interface MultiWindowStrategy {} |
| |
| /** |
| * The height for the swipe up motion |
| */ |
| public static float getDefaultSwipeHeight(Context context, DeviceProfile dp) { |
| float swipeHeight = dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx; |
| if (SysUINavigationMode.getMode(context) == SysUINavigationMode.Mode.NO_BUTTON) { |
| swipeHeight -= dp.getInsets().bottom; |
| } |
| return swipeHeight; |
| } |
| |
| public static void calculateLauncherTaskSize(Context context, DeviceProfile dp, Rect outRect) { |
| float extraSpace; |
| if (dp.isVerticalBarLayout()) { |
| extraSpace = 0; |
| } else { |
| Resources res = context.getResources(); |
| |
| if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) { |
| //TODO: this needs to account for the swipe gesture height and accessibility |
| // UI when shown. |
| extraSpace = 0; |
| } else { |
| extraSpace = getDefaultSwipeHeight(context, dp) + dp.verticalDragHandleSizePx |
| + res.getDimensionPixelSize( |
| R.dimen.dynamic_grid_hotseat_extra_vertical_size) |
| + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding); |
| } |
| } |
| calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_HALF_SCREEN, outRect); |
| } |
| |
| public static void calculateFallbackTaskSize(Context context, DeviceProfile dp, Rect outRect) { |
| calculateTaskSize(context, dp, 0, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE, outRect); |
| } |
| |
| @AnyThread |
| public static void calculateTaskSize(Context context, DeviceProfile dp, |
| float extraVerticalSpace, @MultiWindowStrategy int multiWindowStrategy, Rect outRect) { |
| float taskWidth, taskHeight, paddingHorz; |
| Resources res = context.getResources(); |
| Rect insets = dp.getInsets(); |
| |
| if (dp.isMultiWindowMode) { |
| if (multiWindowStrategy == MULTI_WINDOW_STRATEGY_HALF_SCREEN) { |
| DeviceProfile fullDp = dp.getFullScreenProfile(); |
| // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to |
| // account for system insets |
| taskWidth = fullDp.availableWidthPx; |
| taskHeight = fullDp.availableHeightPx; |
| float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size) |
| / 2; |
| |
| if (fullDp.isLandscape) { |
| taskWidth = taskWidth / 2 - halfDividerSize; |
| } else { |
| taskHeight = taskHeight / 2 - halfDividerSize; |
| } |
| } else { |
| // multiWindowStrategy == MULTI_WINDOW_STRATEGY_DEVICE_PROFILE |
| taskWidth = dp.widthPx; |
| taskHeight = dp.heightPx; |
| } |
| paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space); |
| } else { |
| taskWidth = dp.availableWidthPx; |
| taskHeight = dp.availableHeightPx; |
| |
| final int paddingResId; |
| if (dp.isVerticalBarLayout()) { |
| paddingResId = R.dimen.landscape_task_card_horz_space; |
| } else if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) { |
| paddingResId = R.dimen.portrait_task_card_horz_space_big_overview; |
| } else { |
| paddingResId = R.dimen.portrait_task_card_horz_space; |
| } |
| paddingHorz = res.getDimension(paddingResId); |
| } |
| |
| float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin); |
| float bottomMargin = thumbnailBottomMargin(res); |
| float paddingVert = res.getDimension(R.dimen.task_card_vert_space); |
| |
| // Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless |
| // we override the insets ourselves. |
| int launcherVisibleWidth = dp.widthPx - insets.left - insets.right; |
| int launcherVisibleHeight = dp.heightPx - insets.top - insets.bottom; |
| |
| float availableHeight = launcherVisibleHeight |
| - topIconMargin - extraVerticalSpace - paddingVert - bottomMargin; |
| float availableWidth = launcherVisibleWidth - paddingHorz; |
| |
| float scale = Math.min(availableWidth / taskWidth, availableHeight / taskHeight); |
| float outWidth = scale * taskWidth; |
| float outHeight = scale * taskHeight; |
| |
| // Center in the visible space |
| float x = insets.left + (launcherVisibleWidth - outWidth) / 2; |
| float y = insets.top + Math.max(topIconMargin, |
| (launcherVisibleHeight - extraVerticalSpace - outHeight) / 2); |
| outRect.set(Math.round(x), Math.round(y), |
| Math.round(x) + Math.round(outWidth), Math.round(y) + Math.round(outHeight)); |
| } |
| |
| public static int getShelfTrackingDistance(Context context, DeviceProfile dp) { |
| // Track the bottom of the window. |
| int shelfHeight = dp.hotseatBarSizePx + dp.getInsets().bottom; |
| int spaceBetweenShelfAndRecents = (int) context.getResources().getDimension( |
| R.dimen.task_card_vert_space); |
| return shelfHeight + spaceBetweenShelfAndRecents; |
| } |
| |
| /** |
| * Get the margin that the task thumbnail view should use. |
| * @return the margin in pixels. |
| */ |
| public static int thumbnailBottomMargin(Resources resources) { |
| if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) { |
| return resources.getDimensionPixelSize(R.dimen.overview_actions_height); |
| } else { |
| return 0; |
| } |
| } |
| } |