mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-17 09:38:19 +00:00
Merge "Exact widget sizes functionalities into an utility class" into sc-dev
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_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_STARTED;
|
||||
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.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SizeF;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
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.widget.LauncherAppWidgetHostView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.util.WidgetSizes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AppWidgetResizeFrame extends AbstractFloatingView implements View.OnKeyListener {
|
||||
private static final int SNAP_DURATION = 150;
|
||||
@@ -415,90 +408,12 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
mRunningHInc += hSpanDelta;
|
||||
|
||||
if (!onDismiss) {
|
||||
updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
|
||||
WidgetSizes.updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
|
||||
}
|
||||
}
|
||||
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
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
@@ -114,6 +114,7 @@ import com.android.launcher3.widget.PendingAddWidgetInfo;
|
||||
import com.android.launcher3.widget.PendingAppWidgetHostView;
|
||||
import com.android.launcher3.widget.WidgetManagerHelper;
|
||||
import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
|
||||
import com.android.launcher3.widget.util.WidgetSizes;
|
||||
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -1854,7 +1855,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
item.spanX = resultSpan[0];
|
||||
item.spanY = resultSpan[1];
|
||||
AppWidgetHostView awhv = (AppWidgetHostView) cell;
|
||||
AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0],
|
||||
WidgetSizes.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0],
|
||||
resultSpan[1]);
|
||||
}
|
||||
|
||||
@@ -2528,8 +2529,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
|
||||
|
||||
if (finalView != null && updateWidgetSize) {
|
||||
AppWidgetResizeFrame.updateWidgetSizeRanges(finalView, mLauncher, item.spanX,
|
||||
item.spanY);
|
||||
WidgetSizes.updateWidgetSizeRanges(finalView, mLauncher, item.spanX, item.spanY);
|
||||
}
|
||||
|
||||
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.AccessibilityAction;
|
||||
|
||||
import com.android.launcher3.AppWidgetResizeFrame;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.ButtonDropTarget;
|
||||
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.OptionItem;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
import com.android.launcher3.widget.util.WidgetSizes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -367,7 +367,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||
}
|
||||
|
||||
layout.markCellsAsOccupiedForView(host);
|
||||
AppWidgetResizeFrame.updateWidgetSizeRanges(((LauncherAppWidgetHostView) host), mLauncher,
|
||||
WidgetSizes.updateWidgetSizeRanges(((LauncherAppWidgetHostView) host), mLauncher,
|
||||
info.spanX, info.spanY);
|
||||
host.requestLayout();
|
||||
mLauncher.getModelWriter().updateItemInDatabase(info);
|
||||
|
||||
@@ -26,13 +26,13 @@ import android.os.Process;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AppWidgetResizeFrame;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.util.ContentWriter;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
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.
|
||||
@@ -196,7 +196,7 @@ public class LauncherAppWidgetInfo extends ItemInfo {
|
||||
*/
|
||||
public void onBindAppWidget(Launcher launcher, AppWidgetHostView hostView) {
|
||||
if (!mHasNotifiedInitialWidgetSizeChanged) {
|
||||
AppWidgetResizeFrame.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
|
||||
WidgetSizes.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
|
||||
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_PROVIDER;
|
||||
|
||||
import static com.android.launcher3.AppWidgetResizeFrame.getWidgetSizeOptions;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.SearchManager;
|
||||
@@ -49,6 +47,7 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
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
|
||||
@@ -292,7 +291,8 @@ public class QsbContainerView extends FrameLayout {
|
||||
|
||||
protected Bundle createBindOptions() {
|
||||
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) {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.android.launcher3.widget;
|
||||
|
||||
import static com.android.launcher3.AppWidgetResizeFrame.getWidgetSizeOptions;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
|
||||
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
@@ -24,6 +23,7 @@ import android.os.Bundle;
|
||||
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.PendingAddItemInfo;
|
||||
import com.android.launcher3.widget.util.WidgetSizes;
|
||||
|
||||
/**
|
||||
* Meta data used for late binding of {@link LauncherAppWidgetProviderInfo}.
|
||||
@@ -61,6 +61,6 @@ public class PendingAddWidgetInfo extends PendingAddItemInfo {
|
||||
}
|
||||
|
||||
public Bundle getDefaultSizeOptions(Context context) {
|
||||
return getWidgetSizeOptions(context, componentName, spanX, spanY);
|
||||
return WidgetSizes.getWidgetSizeOptions(context, componentName, spanX, spanY);
|
||||
}
|
||||
}
|
||||
|
||||
145
src/com/android/launcher3/widget/util/WidgetSizes.java
Normal file
145
src/com/android/launcher3/widget/util/WidgetSizes.java
Normal file
@@ -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