DeviceProfile.java revision d017f882eb67b630adb082dd2227e20f5bc77b05
1b38002419dcb456b51f5d320b224737f16a07088Winson Chung/* 2b38002419dcb456b51f5d320b224737f16a07088Winson Chung * Copyright (C) 2008 The Android Open Source Project 3b38002419dcb456b51f5d320b224737f16a07088Winson Chung * 4b38002419dcb456b51f5d320b224737f16a07088Winson Chung * Licensed under the Apache License, Version 2.0 (the "License"); 5b38002419dcb456b51f5d320b224737f16a07088Winson Chung * you may not use this file except in compliance with the License. 6b38002419dcb456b51f5d320b224737f16a07088Winson Chung * You may obtain a copy of the License at 7b38002419dcb456b51f5d320b224737f16a07088Winson Chung * 8b38002419dcb456b51f5d320b224737f16a07088Winson Chung * http://www.apache.org/licenses/LICENSE-2.0 9b38002419dcb456b51f5d320b224737f16a07088Winson Chung * 10b38002419dcb456b51f5d320b224737f16a07088Winson Chung * Unless required by applicable law or agreed to in writing, software 11b38002419dcb456b51f5d320b224737f16a07088Winson Chung * distributed under the License is distributed on an "AS IS" BASIS, 12b38002419dcb456b51f5d320b224737f16a07088Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b38002419dcb456b51f5d320b224737f16a07088Winson Chung * See the License for the specific language governing permissions and 14b38002419dcb456b51f5d320b224737f16a07088Winson Chung * limitations under the License. 15b38002419dcb456b51f5d320b224737f16a07088Winson Chung */ 16b38002419dcb456b51f5d320b224737f16a07088Winson Chung 17b38002419dcb456b51f5d320b224737f16a07088Winson Chungpackage com.android.launcher3; 18b38002419dcb456b51f5d320b224737f16a07088Winson Chung 19b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.appwidget.AppWidgetHostView; 20b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.content.ComponentName; 21b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.content.Context; 22b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.content.res.Configuration; 23b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.content.res.Resources; 24b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.Paint; 25b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.Paint.FontMetrics; 26b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.Point; 27b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.PointF; 28b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.Rect; 29b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.util.DisplayMetrics; 30b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.Display; 31b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.Gravity; 32b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.Surface; 33b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.View; 34d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggiimport android.view.ViewGroup; 35b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.ViewGroup.LayoutParams; 36b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.WindowManager; 37b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.widget.FrameLayout; 38b38002419dcb456b51f5d320b224737f16a07088Winson Chung 39b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport java.util.ArrayList; 40b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport java.util.Collections; 41b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport java.util.Comparator; 42b38002419dcb456b51f5d320b224737f16a07088Winson Chung 43b38002419dcb456b51f5d320b224737f16a07088Winson Chung 44b38002419dcb456b51f5d320b224737f16a07088Winson Chungclass DeviceProfileQuery { 45b38002419dcb456b51f5d320b224737f16a07088Winson Chung float widthDps; 46b38002419dcb456b51f5d320b224737f16a07088Winson Chung float heightDps; 47b38002419dcb456b51f5d320b224737f16a07088Winson Chung float value; 48b38002419dcb456b51f5d320b224737f16a07088Winson Chung PointF dimens; 49b38002419dcb456b51f5d320b224737f16a07088Winson Chung 50b38002419dcb456b51f5d320b224737f16a07088Winson Chung DeviceProfileQuery(float w, float h, float v) { 51b38002419dcb456b51f5d320b224737f16a07088Winson Chung widthDps = w; 52b38002419dcb456b51f5d320b224737f16a07088Winson Chung heightDps = h; 53b38002419dcb456b51f5d320b224737f16a07088Winson Chung value = v; 54b38002419dcb456b51f5d320b224737f16a07088Winson Chung dimens = new PointF(w, h); 55b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 56b38002419dcb456b51f5d320b224737f16a07088Winson Chung} 57b38002419dcb456b51f5d320b224737f16a07088Winson Chung 58b38002419dcb456b51f5d320b224737f16a07088Winson Chungpublic class DeviceProfile { 59b38002419dcb456b51f5d320b224737f16a07088Winson Chung public static interface DeviceProfileCallbacks { 60b38002419dcb456b51f5d320b224737f16a07088Winson Chung public void onAvailableSizeChanged(DeviceProfile grid); 61b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 62b38002419dcb456b51f5d320b224737f16a07088Winson Chung 63b38002419dcb456b51f5d320b224737f16a07088Winson Chung String name; 64b38002419dcb456b51f5d320b224737f16a07088Winson Chung float minWidthDps; 65b38002419dcb456b51f5d320b224737f16a07088Winson Chung float minHeightDps; 66b38002419dcb456b51f5d320b224737f16a07088Winson Chung float numRows; 67b38002419dcb456b51f5d320b224737f16a07088Winson Chung float numColumns; 68b38002419dcb456b51f5d320b224737f16a07088Winson Chung float numHotseatIcons; 69b38002419dcb456b51f5d320b224737f16a07088Winson Chung private float iconSize; 70b38002419dcb456b51f5d320b224737f16a07088Winson Chung private float iconTextSize; 71b38002419dcb456b51f5d320b224737f16a07088Winson Chung private int iconDrawablePaddingOriginalPx; 72b38002419dcb456b51f5d320b224737f16a07088Winson Chung private float hotseatIconSize; 73b38002419dcb456b51f5d320b224737f16a07088Winson Chung 74b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isLandscape; 75b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isTablet; 76b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isLargeTablet; 7742b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung boolean isLayoutRtl; 78b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean transposeLayoutWithOrientation; 79b38002419dcb456b51f5d320b224737f16a07088Winson Chung 80b38002419dcb456b51f5d320b224737f16a07088Winson Chung int desiredWorkspaceLeftRightMarginPx; 81b38002419dcb456b51f5d320b224737f16a07088Winson Chung int edgeMarginPx; 82b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect defaultWidgetPadding; 83b38002419dcb456b51f5d320b224737f16a07088Winson Chung 84b38002419dcb456b51f5d320b224737f16a07088Winson Chung int widthPx; 85b38002419dcb456b51f5d320b224737f16a07088Winson Chung int heightPx; 86b38002419dcb456b51f5d320b224737f16a07088Winson Chung int availableWidthPx; 87b38002419dcb456b51f5d320b224737f16a07088Winson Chung int availableHeightPx; 88b38002419dcb456b51f5d320b224737f16a07088Winson Chung int defaultPageSpacingPx; 89b38002419dcb456b51f5d320b224737f16a07088Winson Chung 90b38002419dcb456b51f5d320b224737f16a07088Winson Chung int overviewModeMinIconZoneHeightPx; 91b38002419dcb456b51f5d320b224737f16a07088Winson Chung int overviewModeMaxIconZoneHeightPx; 92d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi int overviewModeBarItemWidthPx; 93d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi int overviewModeBarSpacerWidthPx; 94b38002419dcb456b51f5d320b224737f16a07088Winson Chung float overviewModeIconZoneRatio; 95b38002419dcb456b51f5d320b224737f16a07088Winson Chung float overviewModeScaleFactor; 96b38002419dcb456b51f5d320b224737f16a07088Winson Chung 97b38002419dcb456b51f5d320b224737f16a07088Winson Chung int iconSizePx; 98b38002419dcb456b51f5d320b224737f16a07088Winson Chung int iconTextSizePx; 99b38002419dcb456b51f5d320b224737f16a07088Winson Chung int iconDrawablePaddingPx; 100b38002419dcb456b51f5d320b224737f16a07088Winson Chung int cellWidthPx; 101b38002419dcb456b51f5d320b224737f16a07088Winson Chung int cellHeightPx; 102b38002419dcb456b51f5d320b224737f16a07088Winson Chung int allAppsIconSizePx; 103b38002419dcb456b51f5d320b224737f16a07088Winson Chung int allAppsIconTextSizePx; 104b38002419dcb456b51f5d320b224737f16a07088Winson Chung int allAppsCellWidthPx; 105b38002419dcb456b51f5d320b224737f16a07088Winson Chung int allAppsCellHeightPx; 106b38002419dcb456b51f5d320b224737f16a07088Winson Chung int allAppsCellPaddingPx; 107b38002419dcb456b51f5d320b224737f16a07088Winson Chung int folderBackgroundOffset; 108b38002419dcb456b51f5d320b224737f16a07088Winson Chung int folderIconSizePx; 109b38002419dcb456b51f5d320b224737f16a07088Winson Chung int folderCellWidthPx; 110b38002419dcb456b51f5d320b224737f16a07088Winson Chung int folderCellHeightPx; 111b38002419dcb456b51f5d320b224737f16a07088Winson Chung int hotseatCellWidthPx; 112b38002419dcb456b51f5d320b224737f16a07088Winson Chung int hotseatCellHeightPx; 113b38002419dcb456b51f5d320b224737f16a07088Winson Chung int hotseatIconSizePx; 114b38002419dcb456b51f5d320b224737f16a07088Winson Chung int hotseatBarHeightPx; 115b38002419dcb456b51f5d320b224737f16a07088Winson Chung int hotseatAllAppsRank; 116b38002419dcb456b51f5d320b224737f16a07088Winson Chung int allAppsNumRows; 117b38002419dcb456b51f5d320b224737f16a07088Winson Chung int allAppsNumCols; 118b38002419dcb456b51f5d320b224737f16a07088Winson Chung int searchBarSpaceWidthPx; 119b38002419dcb456b51f5d320b224737f16a07088Winson Chung int searchBarSpaceMaxWidthPx; 120b38002419dcb456b51f5d320b224737f16a07088Winson Chung int searchBarSpaceHeightPx; 121b38002419dcb456b51f5d320b224737f16a07088Winson Chung int searchBarHeightPx; 122b38002419dcb456b51f5d320b224737f16a07088Winson Chung int pageIndicatorHeightPx; 123b38002419dcb456b51f5d320b224737f16a07088Winson Chung 12459a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung float dragViewScale; 12559a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung 126b38002419dcb456b51f5d320b224737f16a07088Winson Chung private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>(); 127b38002419dcb456b51f5d320b224737f16a07088Winson Chung 128b38002419dcb456b51f5d320b224737f16a07088Winson Chung DeviceProfile(String n, float w, float h, float r, float c, 129b38002419dcb456b51f5d320b224737f16a07088Winson Chung float is, float its, float hs, float his) { 130b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Ensure that we have an odd number of hotseat items (since we need to place all apps) 13116f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) { 132b38002419dcb456b51f5d320b224737f16a07088Winson Chung throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces"); 133b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 134b38002419dcb456b51f5d320b224737f16a07088Winson Chung 135b38002419dcb456b51f5d320b224737f16a07088Winson Chung name = n; 136b38002419dcb456b51f5d320b224737f16a07088Winson Chung minWidthDps = w; 137b38002419dcb456b51f5d320b224737f16a07088Winson Chung minHeightDps = h; 138b38002419dcb456b51f5d320b224737f16a07088Winson Chung numRows = r; 139b38002419dcb456b51f5d320b224737f16a07088Winson Chung numColumns = c; 140b38002419dcb456b51f5d320b224737f16a07088Winson Chung iconSize = is; 141b38002419dcb456b51f5d320b224737f16a07088Winson Chung iconTextSize = its; 142b38002419dcb456b51f5d320b224737f16a07088Winson Chung numHotseatIcons = hs; 143b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseatIconSize = his; 144b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 145b38002419dcb456b51f5d320b224737f16a07088Winson Chung 146b38002419dcb456b51f5d320b224737f16a07088Winson Chung DeviceProfile(Context context, 147b38002419dcb456b51f5d320b224737f16a07088Winson Chung ArrayList<DeviceProfile> profiles, 148b38002419dcb456b51f5d320b224737f16a07088Winson Chung float minWidth, float minHeight, 149b38002419dcb456b51f5d320b224737f16a07088Winson Chung int wPx, int hPx, 150b38002419dcb456b51f5d320b224737f16a07088Winson Chung int awPx, int ahPx, 151b38002419dcb456b51f5d320b224737f16a07088Winson Chung Resources res) { 152b38002419dcb456b51f5d320b224737f16a07088Winson Chung DisplayMetrics dm = res.getDisplayMetrics(); 153b38002419dcb456b51f5d320b224737f16a07088Winson Chung ArrayList<DeviceProfileQuery> points = 154b38002419dcb456b51f5d320b224737f16a07088Winson Chung new ArrayList<DeviceProfileQuery>(); 155b38002419dcb456b51f5d320b224737f16a07088Winson Chung transposeLayoutWithOrientation = 156b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation); 157b38002419dcb456b51f5d320b224737f16a07088Winson Chung minWidthDps = minWidth; 158b38002419dcb456b51f5d320b224737f16a07088Winson Chung minHeightDps = minHeight; 159b38002419dcb456b51f5d320b224737f16a07088Winson Chung 160b38002419dcb456b51f5d320b224737f16a07088Winson Chung ComponentName cn = new ComponentName(context.getPackageName(), 161b38002419dcb456b51f5d320b224737f16a07088Winson Chung this.getClass().getName()); 162b38002419dcb456b51f5d320b224737f16a07088Winson Chung defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null); 163b38002419dcb456b51f5d320b224737f16a07088Winson Chung edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin); 164b38002419dcb456b51f5d320b224737f16a07088Winson Chung desiredWorkspaceLeftRightMarginPx = 2 * edgeMarginPx; 165b38002419dcb456b51f5d320b224737f16a07088Winson Chung pageIndicatorHeightPx = 166b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height); 167b38002419dcb456b51f5d320b224737f16a07088Winson Chung defaultPageSpacingPx = 168b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing); 169b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsCellPaddingPx = 170b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getDimensionPixelSize(R.dimen.dynamic_grid_all_apps_cell_padding); 171b38002419dcb456b51f5d320b224737f16a07088Winson Chung overviewModeMinIconZoneHeightPx = 172b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height); 173b38002419dcb456b51f5d320b224737f16a07088Winson Chung overviewModeMaxIconZoneHeightPx = 174b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height); 175d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi overviewModeBarItemWidthPx = 176d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width); 177d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi overviewModeBarSpacerWidthPx = 178d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width); 179b38002419dcb456b51f5d320b224737f16a07088Winson Chung overviewModeIconZoneRatio = 180b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f; 181b38002419dcb456b51f5d320b224737f16a07088Winson Chung overviewModeScaleFactor = 182b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getInteger(R.integer.config_dynamic_grid_overview_scale_percentage) / 100f; 183b38002419dcb456b51f5d320b224737f16a07088Winson Chung 184b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Interpolate the rows 185b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (DeviceProfile p : profiles) { 186b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numRows)); 187b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 188b38002419dcb456b51f5d320b224737f16a07088Winson Chung numRows = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); 189b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Interpolate the columns 190b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.clear(); 191b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (DeviceProfile p : profiles) { 192b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numColumns)); 193b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 194b38002419dcb456b51f5d320b224737f16a07088Winson Chung numColumns = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); 195b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Interpolate the hotseat length 196b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.clear(); 197b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (DeviceProfile p : profiles) { 198b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numHotseatIcons)); 199b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 200b38002419dcb456b51f5d320b224737f16a07088Winson Chung numHotseatIcons = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); 201b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseatAllAppsRank = (int) (numHotseatIcons / 2); 202b38002419dcb456b51f5d320b224737f16a07088Winson Chung 203b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Interpolate the icon size 204b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.clear(); 205b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (DeviceProfile p : profiles) { 206b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconSize)); 207b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 208b38002419dcb456b51f5d320b224737f16a07088Winson Chung iconSize = invDistWeightedInterpolate(minWidth, minHeight, points); 209b38002419dcb456b51f5d320b224737f16a07088Winson Chung // AllApps uses the original non-scaled icon size 210b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm); 211b38002419dcb456b51f5d320b224737f16a07088Winson Chung 212b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Interpolate the icon text size 213b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.clear(); 214b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (DeviceProfile p : profiles) { 215b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconTextSize)); 216b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 217b38002419dcb456b51f5d320b224737f16a07088Winson Chung iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points); 218b38002419dcb456b51f5d320b224737f16a07088Winson Chung iconDrawablePaddingOriginalPx = 219b38002419dcb456b51f5d320b224737f16a07088Winson Chung res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding); 220b38002419dcb456b51f5d320b224737f16a07088Winson Chung // AllApps uses the original non-scaled icon text size 221b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsIconTextSizePx = DynamicGrid.pxFromDp(iconTextSize, dm); 222b38002419dcb456b51f5d320b224737f16a07088Winson Chung 223b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Interpolate the hotseat icon size 224b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.clear(); 225b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (DeviceProfile p : profiles) { 226b38002419dcb456b51f5d320b224737f16a07088Winson Chung points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.hotseatIconSize)); 227b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 228b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Hotseat 229b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points); 230b38002419dcb456b51f5d320b224737f16a07088Winson Chung 231b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Calculate the remaining vars 232b38002419dcb456b51f5d320b224737f16a07088Winson Chung updateFromConfiguration(context, res, wPx, hPx, awPx, ahPx); 233b38002419dcb456b51f5d320b224737f16a07088Winson Chung updateAvailableDimensions(context); 234b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 235b38002419dcb456b51f5d320b224737f16a07088Winson Chung 236b38002419dcb456b51f5d320b224737f16a07088Winson Chung void addCallback(DeviceProfileCallbacks cb) { 237b38002419dcb456b51f5d320b224737f16a07088Winson Chung mCallbacks.add(cb); 238b38002419dcb456b51f5d320b224737f16a07088Winson Chung cb.onAvailableSizeChanged(this); 239b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 240b38002419dcb456b51f5d320b224737f16a07088Winson Chung void removeCallback(DeviceProfileCallbacks cb) { 241b38002419dcb456b51f5d320b224737f16a07088Winson Chung mCallbacks.remove(cb); 242b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 243b38002419dcb456b51f5d320b224737f16a07088Winson Chung 244b38002419dcb456b51f5d320b224737f16a07088Winson Chung private int getDeviceOrientation(Context context) { 245b38002419dcb456b51f5d320b224737f16a07088Winson Chung WindowManager windowManager = (WindowManager) 246b38002419dcb456b51f5d320b224737f16a07088Winson Chung context.getSystemService(Context.WINDOW_SERVICE); 247b38002419dcb456b51f5d320b224737f16a07088Winson Chung Resources resources = context.getResources(); 248b38002419dcb456b51f5d320b224737f16a07088Winson Chung DisplayMetrics dm = resources.getDisplayMetrics(); 249b38002419dcb456b51f5d320b224737f16a07088Winson Chung Configuration config = resources.getConfiguration(); 250b38002419dcb456b51f5d320b224737f16a07088Winson Chung int rotation = windowManager.getDefaultDisplay().getRotation(); 251b38002419dcb456b51f5d320b224737f16a07088Winson Chung 252b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isLandscape = (config.orientation == Configuration.ORIENTATION_LANDSCAPE) && 253b38002419dcb456b51f5d320b224737f16a07088Winson Chung (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180); 254b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isRotatedPortrait = (config.orientation == Configuration.ORIENTATION_PORTRAIT) && 255b38002419dcb456b51f5d320b224737f16a07088Winson Chung (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270); 256b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (isLandscape || isRotatedPortrait) { 257b38002419dcb456b51f5d320b224737f16a07088Winson Chung return CellLayout.LANDSCAPE; 258b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 259b38002419dcb456b51f5d320b224737f16a07088Winson Chung return CellLayout.PORTRAIT; 260b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 261b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 262b38002419dcb456b51f5d320b224737f16a07088Winson Chung 263b38002419dcb456b51f5d320b224737f16a07088Winson Chung private void updateAvailableDimensions(Context context) { 264b38002419dcb456b51f5d320b224737f16a07088Winson Chung WindowManager windowManager = (WindowManager) 265b38002419dcb456b51f5d320b224737f16a07088Winson Chung context.getSystemService(Context.WINDOW_SERVICE); 266b38002419dcb456b51f5d320b224737f16a07088Winson Chung Display display = windowManager.getDefaultDisplay(); 267b38002419dcb456b51f5d320b224737f16a07088Winson Chung Resources resources = context.getResources(); 268b38002419dcb456b51f5d320b224737f16a07088Winson Chung DisplayMetrics dm = resources.getDisplayMetrics(); 269b38002419dcb456b51f5d320b224737f16a07088Winson Chung Configuration config = resources.getConfiguration(); 270b38002419dcb456b51f5d320b224737f16a07088Winson Chung 271b38002419dcb456b51f5d320b224737f16a07088Winson Chung // There are three possible configurations that the dynamic grid accounts for, portrait, 272b38002419dcb456b51f5d320b224737f16a07088Winson Chung // landscape with the nav bar at the bottom, and landscape with the nav bar at the side. 273b38002419dcb456b51f5d320b224737f16a07088Winson Chung // To prevent waiting for fitSystemWindows(), we make the observation that in landscape, 274b38002419dcb456b51f5d320b224737f16a07088Winson Chung // the height is the smallest height (either with the nav bar at the bottom or to the 275b38002419dcb456b51f5d320b224737f16a07088Winson Chung // side) and otherwise, the height is simply the largest possible height for a portrait 276b38002419dcb456b51f5d320b224737f16a07088Winson Chung // device. 277b38002419dcb456b51f5d320b224737f16a07088Winson Chung Point size = new Point(); 278b38002419dcb456b51f5d320b224737f16a07088Winson Chung Point smallestSize = new Point(); 279b38002419dcb456b51f5d320b224737f16a07088Winson Chung Point largestSize = new Point(); 280b38002419dcb456b51f5d320b224737f16a07088Winson Chung display.getSize(size); 281b38002419dcb456b51f5d320b224737f16a07088Winson Chung display.getCurrentSizeRange(smallestSize, largestSize); 282b38002419dcb456b51f5d320b224737f16a07088Winson Chung availableWidthPx = size.x; 283b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { 284b38002419dcb456b51f5d320b224737f16a07088Winson Chung availableHeightPx = smallestSize.y; 285b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 286b38002419dcb456b51f5d320b224737f16a07088Winson Chung availableHeightPx = largestSize.y; 287b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 288b38002419dcb456b51f5d320b224737f16a07088Winson Chung 289b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Check to see if the icons fit in the new available height. If not, then we need to 290b38002419dcb456b51f5d320b224737f16a07088Winson Chung // shrink the icon size. 291b38002419dcb456b51f5d320b224737f16a07088Winson Chung float scale = 1f; 292b38002419dcb456b51f5d320b224737f16a07088Winson Chung int drawablePadding = iconDrawablePaddingOriginalPx; 293b38002419dcb456b51f5d320b224737f16a07088Winson Chung updateIconSize(1f, drawablePadding, resources, dm); 294b38002419dcb456b51f5d320b224737f16a07088Winson Chung float usedHeight = (cellHeightPx * numRows); 29559a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung 29659a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung Rect workspacePadding = getWorkspacePadding(); 297b38002419dcb456b51f5d320b224737f16a07088Winson Chung int maxHeight = (availableHeightPx - workspacePadding.top - workspacePadding.bottom); 298b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (usedHeight > maxHeight) { 299b38002419dcb456b51f5d320b224737f16a07088Winson Chung scale = maxHeight / usedHeight; 300b38002419dcb456b51f5d320b224737f16a07088Winson Chung drawablePadding = 0; 301b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 302b38002419dcb456b51f5d320b224737f16a07088Winson Chung updateIconSize(scale, drawablePadding, resources, dm); 303b38002419dcb456b51f5d320b224737f16a07088Winson Chung 304b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Make the callbacks 305b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (DeviceProfileCallbacks cb : mCallbacks) { 306b38002419dcb456b51f5d320b224737f16a07088Winson Chung cb.onAvailableSizeChanged(this); 307b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 308b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 309b38002419dcb456b51f5d320b224737f16a07088Winson Chung 310b38002419dcb456b51f5d320b224737f16a07088Winson Chung private void updateIconSize(float scale, int drawablePadding, Resources resources, 311b38002419dcb456b51f5d320b224737f16a07088Winson Chung DisplayMetrics dm) { 312b38002419dcb456b51f5d320b224737f16a07088Winson Chung iconSizePx = (int) (DynamicGrid.pxFromDp(iconSize, dm) * scale); 313b38002419dcb456b51f5d320b224737f16a07088Winson Chung iconTextSizePx = (int) (DynamicGrid.pxFromSp(iconTextSize, dm) * scale); 314b38002419dcb456b51f5d320b224737f16a07088Winson Chung iconDrawablePaddingPx = drawablePadding; 315b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseatIconSizePx = (int) (DynamicGrid.pxFromDp(hotseatIconSize, dm) * scale); 316b38002419dcb456b51f5d320b224737f16a07088Winson Chung 317b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Search Bar 318b38002419dcb456b51f5d320b224737f16a07088Winson Chung searchBarSpaceMaxWidthPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width); 319b38002419dcb456b51f5d320b224737f16a07088Winson Chung searchBarHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height); 320b38002419dcb456b51f5d320b224737f16a07088Winson Chung searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx); 32169e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung searchBarSpaceHeightPx = searchBarHeightPx + getSearchBarTopOffset(); 322b38002419dcb456b51f5d320b224737f16a07088Winson Chung 323b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Calculate the actual text height 324b38002419dcb456b51f5d320b224737f16a07088Winson Chung Paint textPaint = new Paint(); 325b38002419dcb456b51f5d320b224737f16a07088Winson Chung textPaint.setTextSize(iconTextSizePx); 326b38002419dcb456b51f5d320b224737f16a07088Winson Chung FontMetrics fm = textPaint.getFontMetrics(); 327b38002419dcb456b51f5d320b224737f16a07088Winson Chung cellWidthPx = iconSizePx; 328b38002419dcb456b51f5d320b224737f16a07088Winson Chung cellHeightPx = iconSizePx + iconDrawablePaddingPx + (int) Math.ceil(fm.bottom - fm.top); 32959a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung final float scaleDps = resources.getDimensionPixelSize(R.dimen.dragViewScale); 33059a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung dragViewScale = (iconSizePx + scaleDps) / iconSizePx; 331b38002419dcb456b51f5d320b224737f16a07088Winson Chung 332b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Hotseat 333b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx; 334b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseatCellWidthPx = iconSizePx; 335b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseatCellHeightPx = iconSizePx; 336b38002419dcb456b51f5d320b224737f16a07088Winson Chung 337b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Folder 338b38002419dcb456b51f5d320b224737f16a07088Winson Chung folderCellWidthPx = cellWidthPx + 3 * edgeMarginPx; 339b38002419dcb456b51f5d320b224737f16a07088Winson Chung folderCellHeightPx = cellHeightPx + edgeMarginPx; 340b38002419dcb456b51f5d320b224737f16a07088Winson Chung folderBackgroundOffset = -edgeMarginPx; 341b38002419dcb456b51f5d320b224737f16a07088Winson Chung folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset; 342b38002419dcb456b51f5d320b224737f16a07088Winson Chung 343b38002419dcb456b51f5d320b224737f16a07088Winson Chung // All Apps 344b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect padding = getWorkspacePadding(isLandscape ? 345b38002419dcb456b51f5d320b224737f16a07088Winson Chung CellLayout.LANDSCAPE : CellLayout.PORTRAIT); 346b38002419dcb456b51f5d320b224737f16a07088Winson Chung int pageIndicatorOffset = 347b38002419dcb456b51f5d320b224737f16a07088Winson Chung resources.getDimensionPixelSize(R.dimen.apps_customize_page_indicator_offset); 348b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsCellWidthPx = allAppsIconSizePx; 349b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsCellHeightPx = allAppsIconSizePx + drawablePadding + iconTextSizePx; 350b38002419dcb456b51f5d320b224737f16a07088Winson Chung int maxLongEdgeCellCount = 351b38002419dcb456b51f5d320b224737f16a07088Winson Chung resources.getInteger(R.integer.config_dynamic_grid_max_long_edge_cell_count); 352b38002419dcb456b51f5d320b224737f16a07088Winson Chung int maxShortEdgeCellCount = 353b38002419dcb456b51f5d320b224737f16a07088Winson Chung resources.getInteger(R.integer.config_dynamic_grid_max_short_edge_cell_count); 354b38002419dcb456b51f5d320b224737f16a07088Winson Chung int minEdgeCellCount = 355b38002419dcb456b51f5d320b224737f16a07088Winson Chung resources.getInteger(R.integer.config_dynamic_grid_min_edge_cell_count); 356b38002419dcb456b51f5d320b224737f16a07088Winson Chung int maxRows = (isLandscape ? maxShortEdgeCellCount : maxLongEdgeCellCount); 357b38002419dcb456b51f5d320b224737f16a07088Winson Chung int maxCols = (isLandscape ? maxLongEdgeCellCount : maxShortEdgeCellCount); 358b38002419dcb456b51f5d320b224737f16a07088Winson Chung 359b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) / 360b38002419dcb456b51f5d320b224737f16a07088Winson Chung (allAppsCellHeightPx + allAppsCellPaddingPx); 361b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows)); 362b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsNumCols = (availableWidthPx) / 363b38002419dcb456b51f5d320b224737f16a07088Winson Chung (allAppsCellWidthPx + allAppsCellPaddingPx); 364b38002419dcb456b51f5d320b224737f16a07088Winson Chung allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols)); 365b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 366b38002419dcb456b51f5d320b224737f16a07088Winson Chung 367b38002419dcb456b51f5d320b224737f16a07088Winson Chung void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx, 368b38002419dcb456b51f5d320b224737f16a07088Winson Chung int awPx, int ahPx) { 36942b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung Configuration configuration = resources.getConfiguration(); 37042b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung isLandscape = (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE); 371b38002419dcb456b51f5d320b224737f16a07088Winson Chung isTablet = resources.getBoolean(R.bool.is_tablet); 372b38002419dcb456b51f5d320b224737f16a07088Winson Chung isLargeTablet = resources.getBoolean(R.bool.is_large_tablet); 37342b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung isLayoutRtl = (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); 374b38002419dcb456b51f5d320b224737f16a07088Winson Chung widthPx = wPx; 375b38002419dcb456b51f5d320b224737f16a07088Winson Chung heightPx = hPx; 376b38002419dcb456b51f5d320b224737f16a07088Winson Chung availableWidthPx = awPx; 377b38002419dcb456b51f5d320b224737f16a07088Winson Chung availableHeightPx = ahPx; 378b38002419dcb456b51f5d320b224737f16a07088Winson Chung 379b38002419dcb456b51f5d320b224737f16a07088Winson Chung updateAvailableDimensions(context); 380b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 381b38002419dcb456b51f5d320b224737f16a07088Winson Chung 382b38002419dcb456b51f5d320b224737f16a07088Winson Chung private float dist(PointF p0, PointF p1) { 383b38002419dcb456b51f5d320b224737f16a07088Winson Chung return (float) Math.sqrt((p1.x - p0.x)*(p1.x-p0.x) + 384b38002419dcb456b51f5d320b224737f16a07088Winson Chung (p1.y-p0.y)*(p1.y-p0.y)); 385b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 386b38002419dcb456b51f5d320b224737f16a07088Winson Chung 387b38002419dcb456b51f5d320b224737f16a07088Winson Chung private float weight(PointF a, PointF b, 388b38002419dcb456b51f5d320b224737f16a07088Winson Chung float pow) { 389b38002419dcb456b51f5d320b224737f16a07088Winson Chung float d = dist(a, b); 390b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (d == 0f) { 391b38002419dcb456b51f5d320b224737f16a07088Winson Chung return Float.POSITIVE_INFINITY; 392b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 393b38002419dcb456b51f5d320b224737f16a07088Winson Chung return (float) (1f / Math.pow(d, pow)); 394b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 395b38002419dcb456b51f5d320b224737f16a07088Winson Chung 396b38002419dcb456b51f5d320b224737f16a07088Winson Chung private float invDistWeightedInterpolate(float width, float height, 397b38002419dcb456b51f5d320b224737f16a07088Winson Chung ArrayList<DeviceProfileQuery> points) { 398b38002419dcb456b51f5d320b224737f16a07088Winson Chung float sum = 0; 399b38002419dcb456b51f5d320b224737f16a07088Winson Chung float weights = 0; 400b38002419dcb456b51f5d320b224737f16a07088Winson Chung float pow = 5; 401b38002419dcb456b51f5d320b224737f16a07088Winson Chung float kNearestNeighbors = 3; 402b38002419dcb456b51f5d320b224737f16a07088Winson Chung final PointF xy = new PointF(width, height); 403b38002419dcb456b51f5d320b224737f16a07088Winson Chung 404b38002419dcb456b51f5d320b224737f16a07088Winson Chung ArrayList<DeviceProfileQuery> pointsByNearness = points; 405b38002419dcb456b51f5d320b224737f16a07088Winson Chung Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() { 406b38002419dcb456b51f5d320b224737f16a07088Winson Chung public int compare(DeviceProfileQuery a, DeviceProfileQuery b) { 407b38002419dcb456b51f5d320b224737f16a07088Winson Chung return (int) (dist(xy, a.dimens) - dist(xy, b.dimens)); 408b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 409b38002419dcb456b51f5d320b224737f16a07088Winson Chung }); 410b38002419dcb456b51f5d320b224737f16a07088Winson Chung 411b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (int i = 0; i < pointsByNearness.size(); ++i) { 412b38002419dcb456b51f5d320b224737f16a07088Winson Chung DeviceProfileQuery p = pointsByNearness.get(i); 413b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (i < kNearestNeighbors) { 414b38002419dcb456b51f5d320b224737f16a07088Winson Chung float w = weight(xy, p.dimens, pow); 415b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (w == Float.POSITIVE_INFINITY) { 416b38002419dcb456b51f5d320b224737f16a07088Winson Chung return p.value; 417b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 418b38002419dcb456b51f5d320b224737f16a07088Winson Chung weights += w; 419b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 420b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 421b38002419dcb456b51f5d320b224737f16a07088Winson Chung 422b38002419dcb456b51f5d320b224737f16a07088Winson Chung for (int i = 0; i < pointsByNearness.size(); ++i) { 423b38002419dcb456b51f5d320b224737f16a07088Winson Chung DeviceProfileQuery p = pointsByNearness.get(i); 424b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (i < kNearestNeighbors) { 425b38002419dcb456b51f5d320b224737f16a07088Winson Chung float w = weight(xy, p.dimens, pow); 426b38002419dcb456b51f5d320b224737f16a07088Winson Chung sum += w * p.value / weights; 427b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 428b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 429b38002419dcb456b51f5d320b224737f16a07088Winson Chung 430b38002419dcb456b51f5d320b224737f16a07088Winson Chung return sum; 431b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 432b38002419dcb456b51f5d320b224737f16a07088Winson Chung 43369e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung /** Returns the search bar top offset */ 43469e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung int getSearchBarTopOffset() { 43569e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung if (isTablet() && !isVerticalBarLayout()) { 43669e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung return 4 * edgeMarginPx; 43769e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung } else { 43869e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung return 2 * edgeMarginPx; 43969e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung } 44069e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung } 44169e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung 442b38002419dcb456b51f5d320b224737f16a07088Winson Chung /** Returns the search bar bounds in the current orientation */ 443b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect getSearchBarBounds() { 444b38002419dcb456b51f5d320b224737f16a07088Winson Chung return getSearchBarBounds(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT); 445b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 446b38002419dcb456b51f5d320b224737f16a07088Winson Chung /** Returns the search bar bounds in the specified orientation */ 447b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect getSearchBarBounds(int orientation) { 448b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect bounds = new Rect(); 449b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (orientation == CellLayout.LANDSCAPE && 450b38002419dcb456b51f5d320b224737f16a07088Winson Chung transposeLayoutWithOrientation) { 45142b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung if (isLayoutRtl) { 45242b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung bounds.set(availableWidthPx - searchBarSpaceHeightPx, edgeMarginPx, 45342b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung availableWidthPx, availableHeightPx - edgeMarginPx); 45442b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung } else { 45542b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung bounds.set(0, edgeMarginPx, searchBarSpaceHeightPx, 45642b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung availableHeightPx - edgeMarginPx); 45742b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung } 458b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 459b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (isTablet()) { 460b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Pad the left and right of the workspace to ensure consistent spacing 461b38002419dcb456b51f5d320b224737f16a07088Winson Chung // between all icons 462b38002419dcb456b51f5d320b224737f16a07088Winson Chung int width = (orientation == CellLayout.LANDSCAPE) 463b38002419dcb456b51f5d320b224737f16a07088Winson Chung ? Math.max(widthPx, heightPx) 464b38002419dcb456b51f5d320b224737f16a07088Winson Chung : Math.min(widthPx, heightPx); 465b38002419dcb456b51f5d320b224737f16a07088Winson Chung // XXX: If the icon size changes across orientations, we will have to take 466b38002419dcb456b51f5d320b224737f16a07088Winson Chung // that into account here too. 467b38002419dcb456b51f5d320b224737f16a07088Winson Chung int gap = (int) ((width - 2 * edgeMarginPx - 468b38002419dcb456b51f5d320b224737f16a07088Winson Chung (numColumns * cellWidthPx)) / (2 * (numColumns + 1))); 4692cb2471e7fbade9a785c523df5941f2855e99041Winson Chung bounds.set(edgeMarginPx + gap, getSearchBarTopOffset(), 4702cb2471e7fbade9a785c523df5941f2855e99041Winson Chung availableWidthPx - (edgeMarginPx + gap), 471b38002419dcb456b51f5d320b224737f16a07088Winson Chung searchBarSpaceHeightPx); 472b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 4732cb2471e7fbade9a785c523df5941f2855e99041Winson Chung bounds.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left, 4742cb2471e7fbade9a785c523df5941f2855e99041Winson Chung getSearchBarTopOffset(), 475b38002419dcb456b51f5d320b224737f16a07088Winson Chung availableWidthPx - (desiredWorkspaceLeftRightMarginPx - 476b38002419dcb456b51f5d320b224737f16a07088Winson Chung defaultWidgetPadding.right), searchBarSpaceHeightPx); 477b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 478b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 479b38002419dcb456b51f5d320b224737f16a07088Winson Chung return bounds; 480b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 481b38002419dcb456b51f5d320b224737f16a07088Winson Chung 482a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung /** Returns the bounds of the workspace page indicators. */ 483a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung Rect getWorkspacePageIndicatorBounds(Rect insets) { 484a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung Rect workspacePadding = getWorkspacePadding(); 485a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung int pageIndicatorTop = heightPx - insets.bottom - workspacePadding.bottom; 486a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung return new Rect(workspacePadding.left, pageIndicatorTop, 487a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung widthPx - workspacePadding.right, pageIndicatorTop + pageIndicatorHeightPx); 488a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung } 489a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung 490b38002419dcb456b51f5d320b224737f16a07088Winson Chung /** Returns the workspace padding in the specified orientation */ 491b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect getWorkspacePadding() { 492b38002419dcb456b51f5d320b224737f16a07088Winson Chung return getWorkspacePadding(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT); 493b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 494b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect getWorkspacePadding(int orientation) { 495b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect searchBarBounds = getSearchBarBounds(orientation); 496b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect padding = new Rect(); 497b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (orientation == CellLayout.LANDSCAPE && 498b38002419dcb456b51f5d320b224737f16a07088Winson Chung transposeLayoutWithOrientation) { 499b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Pad the left and right of the workspace with search/hotseat bar sizes 50042b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung if (isLayoutRtl) { 50142b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung padding.set(hotseatBarHeightPx, edgeMarginPx, 50242b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung searchBarBounds.width(), edgeMarginPx); 50342b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung } else { 50442b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung padding.set(searchBarBounds.width(), edgeMarginPx, 50542b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung hotseatBarHeightPx, edgeMarginPx); 50642b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung } 507b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 508b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (isTablet()) { 509b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Pad the left and right of the workspace to ensure consistent spacing 510b38002419dcb456b51f5d320b224737f16a07088Winson Chung // between all icons 51159a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung float gapScale = 1f + (dragViewScale - 1f) / 2f; 512b38002419dcb456b51f5d320b224737f16a07088Winson Chung int width = (orientation == CellLayout.LANDSCAPE) 513b38002419dcb456b51f5d320b224737f16a07088Winson Chung ? Math.max(widthPx, heightPx) 514b38002419dcb456b51f5d320b224737f16a07088Winson Chung : Math.min(widthPx, heightPx); 51559a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung int height = (orientation != CellLayout.LANDSCAPE) 51659a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung ? Math.max(widthPx, heightPx) 51759a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung : Math.min(widthPx, heightPx); 51859a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung int paddingTop = searchBarBounds.bottom; 51959a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx; 52059a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung int availableWidth = Math.max(0, width - (int) ((numColumns * cellWidthPx) + 52159a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung (numColumns * gapScale * cellWidthPx))); 52259a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung int availableHeight = Math.max(0, height - paddingTop - paddingBottom 52359a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung - (int) (2 * numRows * cellHeightPx)); 52459a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung padding.set(availableWidth / 2, paddingTop + availableHeight / 2, 52559a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung availableWidth / 2, paddingBottom + availableHeight / 2); 526b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 527b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Pad the top and bottom of the workspace with search/hotseat bar sizes 528b38002419dcb456b51f5d320b224737f16a07088Winson Chung padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left, 529b38002419dcb456b51f5d320b224737f16a07088Winson Chung searchBarBounds.bottom, 530b38002419dcb456b51f5d320b224737f16a07088Winson Chung desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right, 531b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseatBarHeightPx + pageIndicatorHeightPx); 532b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 533b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 534b38002419dcb456b51f5d320b224737f16a07088Winson Chung return padding; 535b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 536b38002419dcb456b51f5d320b224737f16a07088Winson Chung 537b38002419dcb456b51f5d320b224737f16a07088Winson Chung int getWorkspacePageSpacing(int orientation) { 53859a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung if ((orientation == CellLayout.LANDSCAPE && 53959a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung transposeLayoutWithOrientation) || isLargeTablet()) { 540b38002419dcb456b51f5d320b224737f16a07088Winson Chung // In landscape mode the page spacing is set to the default. 541b38002419dcb456b51f5d320b224737f16a07088Winson Chung return defaultPageSpacingPx; 542b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 543b38002419dcb456b51f5d320b224737f16a07088Winson Chung // In portrait, we want the pages spaced such that there is no 544b38002419dcb456b51f5d320b224737f16a07088Winson Chung // overhang of the previous / next page into the current page viewport. 545b38002419dcb456b51f5d320b224737f16a07088Winson Chung // We assume symmetrical padding in portrait mode. 546b38002419dcb456b51f5d320b224737f16a07088Winson Chung return 2 * getWorkspacePadding().left; 547b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 548b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 549b38002419dcb456b51f5d320b224737f16a07088Winson Chung 550b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect getOverviewModeButtonBarRect() { 551b38002419dcb456b51f5d320b224737f16a07088Winson Chung int zoneHeight = (int) (overviewModeIconZoneRatio * availableHeightPx); 552b38002419dcb456b51f5d320b224737f16a07088Winson Chung zoneHeight = Math.min(overviewModeMaxIconZoneHeightPx, 553b38002419dcb456b51f5d320b224737f16a07088Winson Chung Math.max(overviewModeMinIconZoneHeightPx, zoneHeight)); 554b38002419dcb456b51f5d320b224737f16a07088Winson Chung return new Rect(0, availableHeightPx - zoneHeight, 0, availableHeightPx); 555b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 556b38002419dcb456b51f5d320b224737f16a07088Winson Chung 557b38002419dcb456b51f5d320b224737f16a07088Winson Chung float getOverviewModeScale() { 558b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect workspacePadding = getWorkspacePadding(); 559b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect overviewBar = getOverviewModeButtonBarRect(); 560b38002419dcb456b51f5d320b224737f16a07088Winson Chung int pageSpace = availableHeightPx - workspacePadding.top - workspacePadding.bottom; 561b38002419dcb456b51f5d320b224737f16a07088Winson Chung return (overviewModeScaleFactor * (pageSpace - overviewBar.height())) / pageSpace; 562b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 563b38002419dcb456b51f5d320b224737f16a07088Winson Chung 564b38002419dcb456b51f5d320b224737f16a07088Winson Chung // The rect returned will be extended to below the system ui that covers the workspace 565b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect getHotseatRect() { 566b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (isVerticalBarLayout()) { 567b38002419dcb456b51f5d320b224737f16a07088Winson Chung return new Rect(availableWidthPx - hotseatBarHeightPx, 0, 568b38002419dcb456b51f5d320b224737f16a07088Winson Chung Integer.MAX_VALUE, availableHeightPx); 569b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 570b38002419dcb456b51f5d320b224737f16a07088Winson Chung return new Rect(0, availableHeightPx - hotseatBarHeightPx, 571b38002419dcb456b51f5d320b224737f16a07088Winson Chung availableWidthPx, Integer.MAX_VALUE); 572b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 573b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 574b38002419dcb456b51f5d320b224737f16a07088Winson Chung 575b38002419dcb456b51f5d320b224737f16a07088Winson Chung int calculateCellWidth(int width, int countX) { 576b38002419dcb456b51f5d320b224737f16a07088Winson Chung return width / countX; 577b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 578b38002419dcb456b51f5d320b224737f16a07088Winson Chung int calculateCellHeight(int height, int countY) { 579b38002419dcb456b51f5d320b224737f16a07088Winson Chung return height / countY; 580b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 581b38002419dcb456b51f5d320b224737f16a07088Winson Chung 582b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isPhone() { 583b38002419dcb456b51f5d320b224737f16a07088Winson Chung return !isTablet && !isLargeTablet; 584b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 585b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isTablet() { 586b38002419dcb456b51f5d320b224737f16a07088Winson Chung return isTablet; 587b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 588b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isLargeTablet() { 589b38002419dcb456b51f5d320b224737f16a07088Winson Chung return isLargeTablet; 590b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 591b38002419dcb456b51f5d320b224737f16a07088Winson Chung 592b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean isVerticalBarLayout() { 593b38002419dcb456b51f5d320b224737f16a07088Winson Chung return isLandscape && transposeLayoutWithOrientation; 594b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 595b38002419dcb456b51f5d320b224737f16a07088Winson Chung 596b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean shouldFadeAdjacentWorkspaceScreens() { 597b38002419dcb456b51f5d320b224737f16a07088Winson Chung return isVerticalBarLayout() || isLargeTablet(); 598b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 599b38002419dcb456b51f5d320b224737f16a07088Winson Chung 600d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi int getVisibleChildCount(ViewGroup parent) { 601d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi int visibleChildren = 0; 602d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi for (int i = 0; i < parent.getChildCount(); i++) { 603d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi if (parent.getChildAt(i).getVisibility() != View.GONE) { 604d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi visibleChildren++; 605d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi } 606d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi } 607d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi return visibleChildren; 608d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi } 609d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi 610d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi int calculateOverviewModeWidth(int visibleChildCount) { 611d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi return visibleChildCount * overviewModeBarItemWidthPx + 612d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi (visibleChildCount-1) * overviewModeBarSpacerWidthPx; 613d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi } 614d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi 615b38002419dcb456b51f5d320b224737f16a07088Winson Chung public void layout(Launcher launcher) { 616b38002419dcb456b51f5d320b224737f16a07088Winson Chung FrameLayout.LayoutParams lp; 617b38002419dcb456b51f5d320b224737f16a07088Winson Chung Resources res = launcher.getResources(); 618b38002419dcb456b51f5d320b224737f16a07088Winson Chung boolean hasVerticalBarLayout = isVerticalBarLayout(); 619b38002419dcb456b51f5d320b224737f16a07088Winson Chung 620b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Layout the search bar space 621b38002419dcb456b51f5d320b224737f16a07088Winson Chung View searchBar = launcher.getSearchBar(); 622b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams(); 623b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (hasVerticalBarLayout) { 62469e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung // Vertical search bar space 625b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.TOP | Gravity.LEFT; 626b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.width = searchBarSpaceHeightPx; 627b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = LayoutParams.MATCH_PARENT; 628b38002419dcb456b51f5d320b224737f16a07088Winson Chung searchBar.setPadding( 629b38002419dcb456b51f5d320b224737f16a07088Winson Chung 0, 2 * edgeMarginPx, 0, 630b38002419dcb456b51f5d320b224737f16a07088Winson Chung 2 * edgeMarginPx); 631b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 63269e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung // Horizontal search bar space 633b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; 634b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.width = searchBarSpaceWidthPx; 635b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = searchBarSpaceHeightPx; 636b38002419dcb456b51f5d320b224737f16a07088Winson Chung searchBar.setPadding( 637b38002419dcb456b51f5d320b224737f16a07088Winson Chung 2 * edgeMarginPx, 63869e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung getSearchBarTopOffset(), 639b38002419dcb456b51f5d320b224737f16a07088Winson Chung 2 * edgeMarginPx, 0); 640b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 641b38002419dcb456b51f5d320b224737f16a07088Winson Chung searchBar.setLayoutParams(lp); 642b38002419dcb456b51f5d320b224737f16a07088Winson Chung 643b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Layout the search bar 644b38002419dcb456b51f5d320b224737f16a07088Winson Chung View qsbBar = launcher.getQsbBar(); 645b38002419dcb456b51f5d320b224737f16a07088Winson Chung LayoutParams vglp = qsbBar.getLayoutParams(); 646b38002419dcb456b51f5d320b224737f16a07088Winson Chung vglp.width = LayoutParams.MATCH_PARENT; 647b38002419dcb456b51f5d320b224737f16a07088Winson Chung vglp.height = LayoutParams.MATCH_PARENT; 648b38002419dcb456b51f5d320b224737f16a07088Winson Chung qsbBar.setLayoutParams(vglp); 649b38002419dcb456b51f5d320b224737f16a07088Winson Chung 650b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Layout the voice proxy 651b38002419dcb456b51f5d320b224737f16a07088Winson Chung View voiceButtonProxy = launcher.findViewById(R.id.voice_button_proxy); 652b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (voiceButtonProxy != null) { 653b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (hasVerticalBarLayout) { 654b38002419dcb456b51f5d320b224737f16a07088Winson Chung // TODO: MOVE THIS INTO SEARCH BAR MEASURE 655b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 656b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp = (FrameLayout.LayoutParams) voiceButtonProxy.getLayoutParams(); 657b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.TOP | Gravity.END; 658b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.width = (widthPx - searchBarSpaceWidthPx) / 2 + 659b38002419dcb456b51f5d320b224737f16a07088Winson Chung 2 * iconSizePx; 660b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = searchBarSpaceHeightPx; 661b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 662b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 663b38002419dcb456b51f5d320b224737f16a07088Winson Chung 664b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Layout the workspace 665b38002419dcb456b51f5d320b224737f16a07088Winson Chung PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace); 666b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp = (FrameLayout.LayoutParams) workspace.getLayoutParams(); 667b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.CENTER; 668b38002419dcb456b51f5d320b224737f16a07088Winson Chung int orientation = isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT; 669b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect padding = getWorkspacePadding(orientation); 670b38002419dcb456b51f5d320b224737f16a07088Winson Chung workspace.setLayoutParams(lp); 671b38002419dcb456b51f5d320b224737f16a07088Winson Chung workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom); 672b38002419dcb456b51f5d320b224737f16a07088Winson Chung workspace.setPageSpacing(getWorkspacePageSpacing(orientation)); 673b38002419dcb456b51f5d320b224737f16a07088Winson Chung 674b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Layout the hotseat 675b38002419dcb456b51f5d320b224737f16a07088Winson Chung View hotseat = launcher.findViewById(R.id.hotseat); 676b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams(); 677b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (hasVerticalBarLayout) { 678b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Vertical hotseat 67942b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung lp.gravity = Gravity.END; 680b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.width = hotseatBarHeightPx; 681b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = LayoutParams.MATCH_PARENT; 682b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx); 683b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else if (isTablet()) { 68459a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung // Pad the hotseat with the workspace padding calculated above 685b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.BOTTOM; 686b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.width = LayoutParams.MATCH_PARENT; 687b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = hotseatBarHeightPx; 68859a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung hotseat.setPadding(edgeMarginPx + padding.left, 0, 68959a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung edgeMarginPx + padding.right, 690b38002419dcb456b51f5d320b224737f16a07088Winson Chung 2 * edgeMarginPx); 691b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 692b38002419dcb456b51f5d320b224737f16a07088Winson Chung // For phones, layout the hotseat without any bottom margin 693b38002419dcb456b51f5d320b224737f16a07088Winson Chung // to ensure that we have space for the folders 694b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.BOTTOM; 695b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.width = LayoutParams.MATCH_PARENT; 696b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = hotseatBarHeightPx; 697b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0, 698b38002419dcb456b51f5d320b224737f16a07088Winson Chung 2 * edgeMarginPx, 0); 699b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 700b38002419dcb456b51f5d320b224737f16a07088Winson Chung hotseat.setLayoutParams(lp); 701b38002419dcb456b51f5d320b224737f16a07088Winson Chung 702b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Layout the page indicators 703b38002419dcb456b51f5d320b224737f16a07088Winson Chung View pageIndicator = launcher.findViewById(R.id.page_indicator); 704b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (pageIndicator != null) { 705b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (hasVerticalBarLayout) { 706b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Hide the page indicators when we have vertical search/hotseat 707b38002419dcb456b51f5d320b224737f16a07088Winson Chung pageIndicator.setVisibility(View.GONE); 708b38002419dcb456b51f5d320b224737f16a07088Winson Chung } else { 709b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Put the page indicators above the hotseat 710b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams(); 711b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 712b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.width = LayoutParams.WRAP_CONTENT; 713b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = LayoutParams.WRAP_CONTENT; 714b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.bottomMargin = hotseatBarHeightPx; 715b38002419dcb456b51f5d320b224737f16a07088Winson Chung pageIndicator.setLayoutParams(lp); 716b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 717b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 718b38002419dcb456b51f5d320b224737f16a07088Winson Chung 719b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Layout AllApps 720b38002419dcb456b51f5d320b224737f16a07088Winson Chung AppsCustomizeTabHost host = (AppsCustomizeTabHost) 721b38002419dcb456b51f5d320b224737f16a07088Winson Chung launcher.findViewById(R.id.apps_customize_pane); 722b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (host != null) { 723b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Center the all apps page indicator 724b38002419dcb456b51f5d320b224737f16a07088Winson Chung int pageIndicatorHeight = (int) (pageIndicatorHeightPx * Math.min(1f, 725b38002419dcb456b51f5d320b224737f16a07088Winson Chung (allAppsIconSizePx / DynamicGrid.DEFAULT_ICON_SIZE_PX))); 726b38002419dcb456b51f5d320b224737f16a07088Winson Chung pageIndicator = host.findViewById(R.id.apps_customize_page_indicator); 727b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (pageIndicator != null) { 728b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams(); 729b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 730b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.width = LayoutParams.WRAP_CONTENT; 731b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = pageIndicatorHeight; 732b38002419dcb456b51f5d320b224737f16a07088Winson Chung pageIndicator.setLayoutParams(lp); 733b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 734b38002419dcb456b51f5d320b224737f16a07088Winson Chung 735b38002419dcb456b51f5d320b224737f16a07088Winson Chung AppsCustomizePagedView pagedView = (AppsCustomizePagedView) 736b38002419dcb456b51f5d320b224737f16a07088Winson Chung host.findViewById(R.id.apps_customize_pane_content); 737b38002419dcb456b51f5d320b224737f16a07088Winson Chung padding = new Rect(); 738b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (pagedView != null) { 739b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Constrain the dimensions of all apps so that it does not span the full width 740b38002419dcb456b51f5d320b224737f16a07088Winson Chung int paddingLR = (availableWidthPx - (allAppsCellWidthPx * allAppsNumCols)) / 741b38002419dcb456b51f5d320b224737f16a07088Winson Chung (2 * (allAppsNumCols + 1)); 742b38002419dcb456b51f5d320b224737f16a07088Winson Chung int paddingTB = (availableHeightPx - (allAppsCellHeightPx * allAppsNumRows)) / 743b38002419dcb456b51f5d320b224737f16a07088Winson Chung (2 * (allAppsNumRows + 1)); 744b38002419dcb456b51f5d320b224737f16a07088Winson Chung paddingLR = Math.min(paddingLR, (int)((paddingLR + paddingTB) * 0.75f)); 745b38002419dcb456b51f5d320b224737f16a07088Winson Chung paddingTB = Math.min(paddingTB, (int)((paddingLR + paddingTB) * 0.75f)); 746b38002419dcb456b51f5d320b224737f16a07088Winson Chung int maxAllAppsWidth = (allAppsNumCols * (allAppsCellWidthPx + 2 * paddingLR)); 747b38002419dcb456b51f5d320b224737f16a07088Winson Chung int gridPaddingLR = (availableWidthPx - maxAllAppsWidth) / 2; 748495f44d5fcd877786ffa5e8eea055e18f28e3d85Winson Chung // Only adjust the side paddings on landscape phones, or tablets 749495f44d5fcd877786ffa5e8eea055e18f28e3d85Winson Chung if ((isTablet() || isLandscape) && gridPaddingLR > (allAppsCellWidthPx / 4)) { 750b38002419dcb456b51f5d320b224737f16a07088Winson Chung padding.left = padding.right = gridPaddingLR; 751b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 752b38002419dcb456b51f5d320b224737f16a07088Winson Chung // The icons are centered, so we can't just offset by the page indicator height 753b38002419dcb456b51f5d320b224737f16a07088Winson Chung // because the empty space will actually be pageIndicatorHeight + paddingTB 754b38002419dcb456b51f5d320b224737f16a07088Winson Chung padding.bottom = Math.max(0, pageIndicatorHeight - paddingTB); 755b38002419dcb456b51f5d320b224737f16a07088Winson Chung pagedView.setAllAppsPadding(padding); 756b38002419dcb456b51f5d320b224737f16a07088Winson Chung pagedView.setWidgetsPageIndicatorPadding(pageIndicatorHeight); 757b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 758b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 759b38002419dcb456b51f5d320b224737f16a07088Winson Chung 760b38002419dcb456b51f5d320b224737f16a07088Winson Chung // Layout the Overview Mode 761d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi ViewGroup overviewMode = launcher.getOverviewPanel(); 762b38002419dcb456b51f5d320b224737f16a07088Winson Chung if (overviewMode != null) { 763b38002419dcb456b51f5d320b224737f16a07088Winson Chung Rect r = getOverviewModeButtonBarRect(); 764b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp = (FrameLayout.LayoutParams) overviewMode.getLayoutParams(); 765b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 766d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi lp.width = Math.min(availableWidthPx, 767d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi calculateOverviewModeWidth(getVisibleChildCount(overviewMode))); 768b38002419dcb456b51f5d320b224737f16a07088Winson Chung lp.height = r.height(); 769b38002419dcb456b51f5d320b224737f16a07088Winson Chung overviewMode.setLayoutParams(lp); 770b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 771b38002419dcb456b51f5d320b224737f16a07088Winson Chung } 772b38002419dcb456b51f5d320b224737f16a07088Winson Chung} 773