Merge "Exact widget sizes functionalities into an utility class" into sc-dev am: 84fe7e3a1e am: 0ed1b41464
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/14881307 Change-Id: Ia0862ffdc3143ba227fb169540eee8be7d73f011
This commit is contained in:
@@ -4,7 +4,6 @@ import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget;
|
|||||||
|
|
||||||
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT;
|
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT;
|
||||||
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH;
|
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH;
|
||||||
import static com.android.launcher3.Utilities.ATLEAST_S;
|
|
||||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RESIZE_COMPLETED;
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RESIZE_COMPLETED;
|
||||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RESIZE_STARTED;
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RESIZE_STARTED;
|
||||||
import static com.android.launcher3.views.BaseDragLayer.LAYOUT_X;
|
import static com.android.launcher3.views.BaseDragLayer.LAYOUT_X;
|
||||||
@@ -13,18 +12,12 @@ import static com.android.launcher3.views.BaseDragLayer.LAYOUT_Y;
|
|||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.PropertyValuesHolder;
|
import android.animation.PropertyValuesHolder;
|
||||||
import android.appwidget.AppWidgetHostView;
|
|
||||||
import android.appwidget.AppWidgetManager;
|
|
||||||
import android.appwidget.AppWidgetProviderInfo;
|
import android.appwidget.AppWidgetProviderInfo;
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Point;
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.GradientDrawable;
|
import android.graphics.drawable.GradientDrawable;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.SizeF;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -39,10 +32,10 @@ import com.android.launcher3.model.data.ItemInfo;
|
|||||||
import com.android.launcher3.util.PendingRequestArgs;
|
import com.android.launcher3.util.PendingRequestArgs;
|
||||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||||
|
import com.android.launcher3.widget.util.WidgetSizes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class AppWidgetResizeFrame extends AbstractFloatingView implements View.OnKeyListener {
|
public class AppWidgetResizeFrame extends AbstractFloatingView implements View.OnKeyListener {
|
||||||
private static final int SNAP_DURATION = 150;
|
private static final int SNAP_DURATION = 150;
|
||||||
@@ -415,90 +408,12 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
|||||||
mRunningHInc += hSpanDelta;
|
mRunningHInc += hSpanDelta;
|
||||||
|
|
||||||
if (!onDismiss) {
|
if (!onDismiss) {
|
||||||
updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
|
WidgetSizes.updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mWidgetView.requestLayout();
|
mWidgetView.requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateWidgetSizeRanges(
|
|
||||||
AppWidgetHostView widgetView, Context context, int spanX, int spanY) {
|
|
||||||
List<SizeF> sizes = getWidgetSizes(context, spanX, spanY);
|
|
||||||
if (ATLEAST_S) {
|
|
||||||
widgetView.updateAppWidgetSize(new Bundle(), sizes);
|
|
||||||
} else {
|
|
||||||
Rect bounds = getMinMaxSizes(sizes);
|
|
||||||
widgetView.updateAppWidgetSize(new Bundle(), bounds.left, bounds.top, bounds.right,
|
|
||||||
bounds.bottom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the list of sizes for a widget of given span, in dp. */
|
|
||||||
public static ArrayList<SizeF> getWidgetSizes(Context context, int spanX, int spanY) {
|
|
||||||
ArrayList<SizeF> sizes = new ArrayList<>(2);
|
|
||||||
final float density = context.getResources().getDisplayMetrics().density;
|
|
||||||
Point cellSize = new Point();
|
|
||||||
|
|
||||||
for (DeviceProfile profile : LauncherAppState.getIDP(context).supportedProfiles) {
|
|
||||||
final float hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacingPx;
|
|
||||||
final float vBorderSpacing = (spanY - 1) * profile.cellLayoutBorderSpacingPx;
|
|
||||||
profile.getCellSize(cellSize);
|
|
||||||
sizes.add(new SizeF(
|
|
||||||
((spanX * cellSize.x) + hBorderSpacing) / density,
|
|
||||||
((spanY * cellSize.y) + vBorderSpacing) / density));
|
|
||||||
}
|
|
||||||
return sizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the bundle to be used as the default options for a widget with provided size
|
|
||||||
*/
|
|
||||||
public static Bundle getWidgetSizeOptions(
|
|
||||||
Context context, ComponentName provider, int spanX, int spanY) {
|
|
||||||
ArrayList<SizeF> sizes = getWidgetSizes(context, spanX, spanY);
|
|
||||||
Rect padding = getDefaultPaddingForWidget(context, provider, null);
|
|
||||||
float density = context.getResources().getDisplayMetrics().density;
|
|
||||||
float xPaddingDips = (padding.left + padding.right) / density;
|
|
||||||
float yPaddingDips = (padding.top + padding.bottom) / density;
|
|
||||||
|
|
||||||
ArrayList<SizeF> paddedSizes = sizes.stream()
|
|
||||||
.map(size -> new SizeF(
|
|
||||||
Math.max(0.f, size.getWidth() - xPaddingDips),
|
|
||||||
Math.max(0.f, size.getHeight() - yPaddingDips)))
|
|
||||||
.collect(Collectors.toCollection(ArrayList::new));
|
|
||||||
|
|
||||||
Rect rect = AppWidgetResizeFrame.getMinMaxSizes(paddedSizes);
|
|
||||||
Bundle options = new Bundle();
|
|
||||||
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, rect.left);
|
|
||||||
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, rect.top);
|
|
||||||
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, rect.right);
|
|
||||||
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, rect.bottom);
|
|
||||||
options.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, paddedSizes);
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the min and max widths and heights given a list of sizes, in dp.
|
|
||||||
*
|
|
||||||
* @param sizes List of sizes to get the min/max from.
|
|
||||||
* @return A rectangle with the left (resp. top) is used for the min width (resp. height) and
|
|
||||||
* the right (resp. bottom) for the max. The returned rectangle is set with 0s if the list is
|
|
||||||
* empty.
|
|
||||||
*/
|
|
||||||
private static Rect getMinMaxSizes(List<SizeF> sizes) {
|
|
||||||
if (sizes.isEmpty()) {
|
|
||||||
return new Rect();
|
|
||||||
} else {
|
|
||||||
SizeF first = sizes.get(0);
|
|
||||||
Rect result = new Rect((int) first.getWidth(), (int) first.getHeight(),
|
|
||||||
(int) first.getWidth(), (int) first.getHeight());
|
|
||||||
for (int i = 1; i < sizes.size(); i++) {
|
|
||||||
result.union((int) sizes.get(i).getWidth(), (int) sizes.get(i).getHeight());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow() {
|
protected void onDetachedFromWindow() {
|
||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ import com.android.launcher3.widget.PendingAddWidgetInfo;
|
|||||||
import com.android.launcher3.widget.PendingAppWidgetHostView;
|
import com.android.launcher3.widget.PendingAppWidgetHostView;
|
||||||
import com.android.launcher3.widget.WidgetManagerHelper;
|
import com.android.launcher3.widget.WidgetManagerHelper;
|
||||||
import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
|
import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
|
||||||
|
import com.android.launcher3.widget.util.WidgetSizes;
|
||||||
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;
|
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -1858,7 +1859,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||||||
item.spanX = resultSpan[0];
|
item.spanX = resultSpan[0];
|
||||||
item.spanY = resultSpan[1];
|
item.spanY = resultSpan[1];
|
||||||
AppWidgetHostView awhv = (AppWidgetHostView) cell;
|
AppWidgetHostView awhv = (AppWidgetHostView) cell;
|
||||||
AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0],
|
WidgetSizes.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0],
|
||||||
resultSpan[1]);
|
resultSpan[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2532,8 +2533,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||||||
((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
|
((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
|
||||||
|
|
||||||
if (finalView != null && updateWidgetSize) {
|
if (finalView != null && updateWidgetSize) {
|
||||||
AppWidgetResizeFrame.updateWidgetSizeRanges(finalView, mLauncher, item.spanX,
|
WidgetSizes.updateWidgetSizeRanges(finalView, mLauncher, item.spanX, item.spanY);
|
||||||
item.spanY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int animationStyle = ANIMATE_INTO_POSITION_AND_DISAPPEAR;
|
int animationStyle = ANIMATE_INTO_POSITION_AND_DISAPPEAR;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import android.view.View.AccessibilityDelegate;
|
|||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
|
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
|
||||||
|
|
||||||
import com.android.launcher3.AppWidgetResizeFrame;
|
|
||||||
import com.android.launcher3.BubbleTextView;
|
import com.android.launcher3.BubbleTextView;
|
||||||
import com.android.launcher3.ButtonDropTarget;
|
import com.android.launcher3.ButtonDropTarget;
|
||||||
import com.android.launcher3.CellLayout;
|
import com.android.launcher3.CellLayout;
|
||||||
@@ -51,6 +50,7 @@ import com.android.launcher3.util.Thunk;
|
|||||||
import com.android.launcher3.views.OptionsPopupView;
|
import com.android.launcher3.views.OptionsPopupView;
|
||||||
import com.android.launcher3.views.OptionsPopupView.OptionItem;
|
import com.android.launcher3.views.OptionsPopupView.OptionItem;
|
||||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||||
|
import com.android.launcher3.widget.util.WidgetSizes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -367,7 +367,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
layout.markCellsAsOccupiedForView(host);
|
layout.markCellsAsOccupiedForView(host);
|
||||||
AppWidgetResizeFrame.updateWidgetSizeRanges(((LauncherAppWidgetHostView) host), mLauncher,
|
WidgetSizes.updateWidgetSizeRanges(((LauncherAppWidgetHostView) host), mLauncher,
|
||||||
info.spanX, info.spanY);
|
info.spanX, info.spanY);
|
||||||
host.requestLayout();
|
host.requestLayout();
|
||||||
mLauncher.getModelWriter().updateItemInDatabase(info);
|
mLauncher.getModelWriter().updateItemInDatabase(info);
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import android.os.Process;
|
|||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.launcher3.AppWidgetResizeFrame;
|
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherSettings;
|
import com.android.launcher3.LauncherSettings;
|
||||||
import com.android.launcher3.logger.LauncherAtom;
|
import com.android.launcher3.logger.LauncherAtom;
|
||||||
import com.android.launcher3.util.ContentWriter;
|
import com.android.launcher3.util.ContentWriter;
|
||||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||||
|
import com.android.launcher3.widget.util.WidgetSizes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a widget (either instantiated or about to be) in the Launcher.
|
* Represents a widget (either instantiated or about to be) in the Launcher.
|
||||||
@@ -196,7 +196,7 @@ public class LauncherAppWidgetInfo extends ItemInfo {
|
|||||||
*/
|
*/
|
||||||
public void onBindAppWidget(Launcher launcher, AppWidgetHostView hostView) {
|
public void onBindAppWidget(Launcher launcher, AppWidgetHostView hostView) {
|
||||||
if (!mHasNotifiedInitialWidgetSizeChanged) {
|
if (!mHasNotifiedInitialWidgetSizeChanged) {
|
||||||
AppWidgetResizeFrame.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
|
WidgetSizes.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
|
||||||
mHasNotifiedInitialWidgetSizeChanged = true;
|
mHasNotifiedInitialWidgetSizeChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ import static android.appwidget.AppWidgetManager.ACTION_APPWIDGET_BIND;
|
|||||||
import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
|
import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
|
||||||
import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_PROVIDER;
|
import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_PROVIDER;
|
||||||
|
|
||||||
import static com.android.launcher3.AppWidgetResizeFrame.getWidgetSizeOptions;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.SearchManager;
|
import android.app.SearchManager;
|
||||||
@@ -49,6 +47,7 @@ import com.android.launcher3.R;
|
|||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
import com.android.launcher3.graphics.FragmentWithPreview;
|
import com.android.launcher3.graphics.FragmentWithPreview;
|
||||||
|
import com.android.launcher3.widget.util.WidgetSizes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A frame layout which contains a QSB. This internally uses fragment to bind the view, which
|
* A frame layout which contains a QSB. This internally uses fragment to bind the view, which
|
||||||
@@ -292,7 +291,8 @@ public class QsbContainerView extends FrameLayout {
|
|||||||
|
|
||||||
protected Bundle createBindOptions() {
|
protected Bundle createBindOptions() {
|
||||||
InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
|
InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
|
||||||
return getWidgetSizeOptions(getContext(), mWidgetInfo.provider, idp.numColumns, 1);
|
return WidgetSizes.getWidgetSizeOptions(getContext(), mWidgetInfo.provider,
|
||||||
|
idp.numColumns, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected View getDefaultView(ViewGroup container, boolean showSetupIcon) {
|
protected View getDefaultView(ViewGroup container, boolean showSetupIcon) {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.launcher3.widget;
|
package com.android.launcher3.widget;
|
||||||
|
|
||||||
import static com.android.launcher3.AppWidgetResizeFrame.getWidgetSizeOptions;
|
|
||||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
|
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
|
||||||
|
|
||||||
import android.appwidget.AppWidgetHostView;
|
import android.appwidget.AppWidgetHostView;
|
||||||
@@ -24,6 +23,7 @@ import android.os.Bundle;
|
|||||||
|
|
||||||
import com.android.launcher3.LauncherSettings;
|
import com.android.launcher3.LauncherSettings;
|
||||||
import com.android.launcher3.PendingAddItemInfo;
|
import com.android.launcher3.PendingAddItemInfo;
|
||||||
|
import com.android.launcher3.widget.util.WidgetSizes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Meta data used for late binding of {@link LauncherAppWidgetProviderInfo}.
|
* Meta data used for late binding of {@link LauncherAppWidgetProviderInfo}.
|
||||||
@@ -61,6 +61,6 @@ public class PendingAddWidgetInfo extends PendingAddItemInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Bundle getDefaultSizeOptions(Context context) {
|
public Bundle getDefaultSizeOptions(Context context) {
|
||||||
return getWidgetSizeOptions(context, componentName, spanX, spanY);
|
return WidgetSizes.getWidgetSizeOptions(context, componentName, spanX, spanY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.launcher3.widget.util;
|
||||||
|
|
||||||
|
import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget;
|
||||||
|
|
||||||
|
import static com.android.launcher3.Utilities.ATLEAST_S;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.appwidget.AppWidgetHostView;
|
||||||
|
import android.appwidget.AppWidgetManager;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Size;
|
||||||
|
import android.util.SizeF;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.launcher3.DeviceProfile;
|
||||||
|
import com.android.launcher3.LauncherAppState;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/** A utility class for widget sizes related calculations. */
|
||||||
|
public final class WidgetSizes {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of all possible sizes, in dp, for a widget of given spans on this device.
|
||||||
|
*/
|
||||||
|
public static ArrayList<SizeF> getWidgetSizes(Context context, int spanX, int spanY) {
|
||||||
|
ArrayList<SizeF> sizes = new ArrayList<>(2);
|
||||||
|
final float density = context.getResources().getDisplayMetrics().density;
|
||||||
|
final Point cellSize = new Point();
|
||||||
|
|
||||||
|
for (DeviceProfile profile : LauncherAppState.getIDP(context).supportedProfiles) {
|
||||||
|
Size widgetSizePx = getWidgetSizePx(profile, spanX, spanY, cellSize);
|
||||||
|
sizes.add(new SizeF(widgetSizePx.getWidth() / density,
|
||||||
|
widgetSizePx.getHeight() / density));
|
||||||
|
}
|
||||||
|
return sizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the size, in pixels, a widget of given spans & {@code profile}. */
|
||||||
|
public static Size getWidgetSizePx(DeviceProfile profile, int spanX, int spanY) {
|
||||||
|
return getWidgetSizePx(profile, spanX, spanY, /* recycledCellSize= */ null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size getWidgetSizePx(DeviceProfile profile, int spanX, int spanY,
|
||||||
|
@Nullable Point recycledCellSize) {
|
||||||
|
final int hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacingPx;
|
||||||
|
final int vBorderSpacing = (spanY - 1) * profile.cellLayoutBorderSpacingPx;
|
||||||
|
if (recycledCellSize == null) {
|
||||||
|
recycledCellSize = new Point();
|
||||||
|
}
|
||||||
|
profile.getCellSize(recycledCellSize);
|
||||||
|
return new Size(((spanX * recycledCellSize.x) + hBorderSpacing),
|
||||||
|
((spanY * recycledCellSize.y) + vBorderSpacing));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a given {@code widgetView} with size, {@code spanX}, {@code spanY}.
|
||||||
|
*
|
||||||
|
* <p>On Android S+, it also updates the given {@code widgetView} with a list of sizes derived
|
||||||
|
* from {@code spanX}, {@code spanY} in all supported device profiles.
|
||||||
|
*/
|
||||||
|
@SuppressLint("NewApi") // Already added API check.
|
||||||
|
public static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Context context,
|
||||||
|
int spanX, int spanY) {
|
||||||
|
List<SizeF> sizes = getWidgetSizes(context, spanX, spanY);
|
||||||
|
if (ATLEAST_S) {
|
||||||
|
widgetView.updateAppWidgetSize(new Bundle(), sizes);
|
||||||
|
} else {
|
||||||
|
Rect bounds = getMinMaxSizes(sizes);
|
||||||
|
widgetView.updateAppWidgetSize(new Bundle(), bounds.left, bounds.top, bounds.right,
|
||||||
|
bounds.bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bundle to be used as the default options for a widget with provided size.
|
||||||
|
*/
|
||||||
|
public static Bundle getWidgetSizeOptions(Context context, ComponentName provider, int spanX,
|
||||||
|
int spanY) {
|
||||||
|
ArrayList<SizeF> sizes = getWidgetSizes(context, spanX, spanY);
|
||||||
|
Rect padding = getDefaultPaddingForWidget(context, provider, null);
|
||||||
|
float density = context.getResources().getDisplayMetrics().density;
|
||||||
|
float xPaddingDips = (padding.left + padding.right) / density;
|
||||||
|
float yPaddingDips = (padding.top + padding.bottom) / density;
|
||||||
|
|
||||||
|
ArrayList<SizeF> paddedSizes = sizes.stream()
|
||||||
|
.map(size -> new SizeF(
|
||||||
|
Math.max(0.f, size.getWidth() - xPaddingDips),
|
||||||
|
Math.max(0.f, size.getHeight() - yPaddingDips)))
|
||||||
|
.collect(Collectors.toCollection(ArrayList::new));
|
||||||
|
|
||||||
|
Rect rect = getMinMaxSizes(paddedSizes);
|
||||||
|
Bundle options = new Bundle();
|
||||||
|
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, rect.left);
|
||||||
|
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, rect.top);
|
||||||
|
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, rect.right);
|
||||||
|
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, rect.bottom);
|
||||||
|
options.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, paddedSizes);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the min and max widths and heights given a list of sizes, in dp.
|
||||||
|
*
|
||||||
|
* @param sizes List of sizes to get the min/max from.
|
||||||
|
* @return A rectangle with the left (resp. top) is used for the min width (resp. height) and
|
||||||
|
* the right (resp. bottom) for the max. The returned rectangle is set with 0s if the list is
|
||||||
|
* empty.
|
||||||
|
*/
|
||||||
|
private static Rect getMinMaxSizes(List<SizeF> sizes) {
|
||||||
|
if (sizes.isEmpty()) {
|
||||||
|
return new Rect();
|
||||||
|
} else {
|
||||||
|
SizeF first = sizes.get(0);
|
||||||
|
Rect result = new Rect((int) first.getWidth(), (int) first.getHeight(),
|
||||||
|
(int) first.getWidth(), (int) first.getHeight());
|
||||||
|
for (int i = 1; i < sizes.size(); i++) {
|
||||||
|
result.union((int) sizes.get(i).getWidth(), (int) sizes.get(i).getHeight());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user