diff --git a/lawnchair/res/values/config.xml b/lawnchair/res/values/config.xml
index a5ab4bc714..aa855ce821 100644
--- a/lawnchair/res/values/config.xml
+++ b/lawnchair/res/values/config.xml
@@ -114,8 +114,8 @@
false
true
false
- false
- false
+ true
+ true
true
false
false
diff --git a/lawnchair/src/app/lawnchair/widget/WidgetStackContentView.kt b/lawnchair/src/app/lawnchair/widget/WidgetStackContentView.kt
index e9f6309023..9c2e48e218 100644
--- a/lawnchair/src/app/lawnchair/widget/WidgetStackContentView.kt
+++ b/lawnchair/src/app/lawnchair/widget/WidgetStackContentView.kt
@@ -27,11 +27,14 @@ import android.widget.FrameLayout
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
import app.lawnchair.smartspace.PageIndicator
+import com.android.launcher3.DeviceProfile
import com.android.launcher3.Launcher
import com.android.launcher3.R
import com.android.launcher3.model.data.LauncherAppWidgetInfo
+import com.android.launcher3.util.MultiTranslateDelegate
import com.android.launcher3.widget.LauncherAppWidgetHostView
import com.android.launcher3.widget.LauncherWidgetHolder
+import com.android.launcher3.widget.NavigableAppWidgetHostView
import com.android.launcher3.widget.PendingAppWidgetHostView
import com.android.launcher3.widget.WidgetInflater
import com.android.launcher3.widget.WidgetManagerHelper
@@ -392,6 +395,12 @@ class WidgetStackContentView @JvmOverloads constructor(
} else {
stopAutoRotate()
}
+
+ // Apply scaling to all widgets after stack info is updated
+ // This ensures widgets scale correctly when stack is resized
+ handler.post {
+ applyWidgetScaling()
+ }
}
/**
@@ -573,6 +582,13 @@ class WidgetStackContentView @JvmOverloads constructor(
pendingView.isClickable = false
pendingView.isFocusable = false
+ // Apply scaling after view is created
+ if (pendingView is NavigableAppWidgetHostView) {
+ pendingView.post {
+ applyScalingToWidget(pendingView)
+ }
+ }
+
// Update position after successful restore
stackInfo?.let { info ->
val needsPositionUpdate = widgetInfo.screenId != info.screenId ||
@@ -646,6 +662,14 @@ class WidgetStackContentView @JvmOverloads constructor(
)
hostView?.isClickable = false
hostView?.isFocusable = false
+
+ // Apply scaling after view is created
+ if (hostView is NavigableAppWidgetHostView) {
+ hostView.post {
+ applyScalingToWidget(hostView)
+ }
+ }
+
return hostView
}
@@ -721,6 +745,15 @@ class WidgetStackContentView @JvmOverloads constructor(
)
pendingView.isClickable = false
pendingView.isFocusable = false
+
+ // Apply scaling after view is created
+ if (pendingView is NavigableAppWidgetHostView) {
+ // Post to apply scaling after layout
+ pendingView.post {
+ applyScalingToWidget(pendingView)
+ }
+ }
+
return pendingView as? LauncherAppWidgetHostView
}
@@ -773,6 +806,14 @@ class WidgetStackContentView @JvmOverloads constructor(
hostView?.isClickable = false
hostView?.isFocusable = false
+ // Apply scaling after view is created
+ if (hostView is NavigableAppWidgetHostView) {
+ // Post to apply scaling after layout
+ hostView.post {
+ applyScalingToWidget(hostView)
+ }
+ }
+
return hostView
}
@@ -836,6 +877,57 @@ class WidgetStackContentView @JvmOverloads constructor(
}
}
+ override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+ super.onLayout(changed, left, top, right, bottom)
+ // Apply scaling to all widget views after layout
+ applyWidgetScaling()
+ }
+
+ /**
+ * Applies scaling to all widget views to fit within the stack bounds.
+ * Similar to ShortcutAndWidgetContainer.layoutChild() logic.
+ */
+ private fun applyWidgetScaling() {
+ synchronized(widgetViews) {
+ widgetViews.forEach { widgetView ->
+ if (widgetView is NavigableAppWidgetHostView) {
+ applyScalingToWidget(widgetView)
+ }
+ }
+ }
+ }
+
+ /**
+ * Applies scaling to a single widget view to fit within the stack bounds.
+ * Similar to ShortcutAndWidgetContainer.layoutChild() logic.
+ */
+ private fun applyScalingToWidget(widgetView: NavigableAppWidgetHostView) {
+ val launcherInstance = launcher ?: return
+ val profile = launcherInstance.deviceProfile
+ val widgetInfo = widgetView.tag as? com.android.launcher3.model.data.ItemInfo
+ if (widgetInfo != null) {
+ // Get the app widget scale from device profile
+ val appWidgetScale = profile.getAppWidgetScale(widgetInfo)
+ val scaleX = appWidgetScale.x
+ val scaleY = appWidgetScale.y
+
+ // Apply scale to fit (use minimum to maintain aspect ratio)
+ widgetView.setScaleToFit(Math.min(scaleX, scaleY))
+
+ // Apply translation for centering (similar to ShortcutAndWidgetContainer)
+ // Use measured dimensions if layout dimensions aren't available yet
+ val width = if (widgetView.width > 0) widgetView.width else widgetView.measuredWidth
+ val height = if (widgetView.height > 0) widgetView.height else widgetView.measuredHeight
+ if (width > 0 && height > 0) {
+ widgetView.getTranslateDelegate().setTranslation(
+ MultiTranslateDelegate.INDEX_WIDGET_CENTERING,
+ -(width - (width * scaleX)) / 2.0f,
+ -(height - (height * scaleY)) / 2.0f,
+ )
+ }
+ }
+ }
+
/**
* Refreshes widgets that were pending but are now ready
* This ensures widgets transition from "Loading..." to actual content
@@ -918,6 +1010,14 @@ class WidgetStackContentView @JvmOverloads constructor(
} else {
widgetViews.add(view)
}
+
+ // Apply scaling to newly loaded widget
+ if (view is NavigableAppWidgetHostView) {
+ view.post {
+ applyScalingToWidget(view)
+ }
+ }
+
needsRefresh = true
android.util.Log.d("WidgetStackContentView", "Loaded missing widget $widgetId at position $positionInStack for stack ${currentStackInfo.stackId}")
} else {
@@ -1007,6 +1107,13 @@ class WidgetStackContentView @JvmOverloads constructor(
realView?.isFocusable = false
if (realView != null) {
+ // Apply scaling after view is created
+ if (realView is NavigableAppWidgetHostView) {
+ realView.post {
+ applyScalingToWidget(realView)
+ }
+ }
+
// Replace pending view with real widget view
synchronized(widgetViews) {
val actualIndex = widgetViews.indexOfFirst { it.appWidgetId == widgetInfo.appWidgetId }
@@ -1081,6 +1188,13 @@ class WidgetStackContentView @JvmOverloads constructor(
realView?.isFocusable = false
if (realView != null) {
+ // Apply scaling after view is created
+ if (realView is NavigableAppWidgetHostView) {
+ realView.post {
+ applyScalingToWidget(realView)
+ }
+ }
+
synchronized(widgetViews) {
val actualIndex = widgetViews.indexOfFirst { it.appWidgetId == widgetInfo.appWidgetId }
if (actualIndex != -1 && actualIndex < widgetViews.size) {
@@ -1368,6 +1482,11 @@ class WidgetStackContentView @JvmOverloads constructor(
// Widgets must be attached to receive live updates from AppWidgetManager
container.addView(view)
+ // Apply scaling to widget after it's added to container
+ if (view is NavigableAppWidgetHostView) {
+ applyScalingToWidget(view)
+ }
+
// Ensure widget is properly set up for updates
if (view is LauncherAppWidgetHostView) {
val widgetId = view.appWidgetId
@@ -1377,6 +1496,11 @@ class WidgetStackContentView @JvmOverloads constructor(
// Widget is now attached and will receive updates automatically
android.util.Log.d("WidgetStackContentView", "Widget $widgetId attached at position $position - will receive live updates")
+ // Apply scaling again after layout (in case dimensions changed)
+ if (view is NavigableAppWidgetHostView) {
+ applyScalingToWidget(view)
+ }
+
// Request an immediate update to ensure widget is fresh
try {
val appWidgetManager = AppWidgetManager.getInstance(context)
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index be7756234d..ff6334e856 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -43,6 +43,7 @@ import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.PendingRequestArgs;
import com.android.launcher3.views.ArrowTipView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
@@ -57,6 +58,8 @@ import java.util.List;
import app.lawnchair.preferences2.PreferenceManager2;
import app.lawnchair.theme.color.tokens.ColorTokens;
import app.lawnchair.theme.drawable.DrawableTokens;
+import app.lawnchair.widget.WidgetStackInfo;
+import app.lawnchair.widget.WidgetStackView;
public class AppWidgetResizeFrame extends AbstractFloatingView implements View.OnKeyListener {
private static final int SNAP_DURATION_MS = 150;
@@ -85,6 +88,7 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
private final List mSystemGestureExclusionRects = new ArrayList<>(HANDLE_COUNT);
private LauncherAppWidgetHostView mWidgetView;
+ private WidgetStackView mWidgetStackView;
private CellLayout mCellLayout;
private DragLayer mDragLayer;
private ImageButton mReconfigureButton;
@@ -250,6 +254,32 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
frame.post(() -> frame.snapToWidget(false));
}
+ public static void showForWidgetStack(WidgetStackView widgetStack, CellLayout cellLayout) {
+ PreferenceManager2 pref2 = PreferenceManager2.getInstance(widgetStack.getContext());
+ boolean force = PreferenceExtensionsKt.firstBlocking(pref2.getForceWidgetResize());
+ boolean unlimited = PreferenceExtensionsKt.firstBlocking(pref2.getWidgetUnlimitedSize());
+
+ // If widget stack is not added to view hierarchy, we cannot show resize frame at
+ // correct location
+ if (widgetStack.getParent() == null) {
+ return;
+ }
+ Launcher launcher = Launcher.getLauncher(cellLayout.getContext());
+ AbstractFloatingView.closeAllOpenViews(launcher);
+
+ DragLayer dl = launcher.getDragLayer();
+ AppWidgetResizeFrame frame = (AppWidgetResizeFrame) launcher.getLayoutInflater()
+ .inflate(R.layout.app_widget_resize_frame, dl, false);
+ ImageView imageView = frame.findViewById(R.id.widget_resize_frame);
+ imageView.setImageDrawable(DrawableTokens.WidgetResizeFrame.resolve(launcher));
+ frame.setupForWidgetStack(widgetStack, cellLayout, dl, force, unlimited);
+ ((DragLayer.LayoutParams) frame.getLayoutParams()).customPosition = true;
+
+ dl.addView(frame);
+ frame.mIsOpen = true;
+ frame.post(() -> frame.snapToWidget(false));
+ }
+
private void setCornerRadiusFromWidget() {
if (mWidgetView != null && mWidgetView.hasEnforcedCornerRadius()) {
float enforcedCornerRadius = mWidgetView.getEnforcedCornerRadius();
@@ -375,6 +405,82 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
mWidgetView.addOnLayoutChangeListener(mWidgetViewLayoutListener);
}
+ private void setupForWidgetStack(WidgetStackView widgetStackView, CellLayout cellLayout,
+ DragLayer dragLayer, boolean force, boolean unlimited) {
+ mCellLayout = cellLayout;
+ mWidgetStackView = widgetStackView;
+ mWidgetView = null; // Clear widget view when using stack
+ mDragLayer = dragLayer;
+ InvariantDeviceProfile idp = LauncherAppState.getIDP(cellLayout.getContext());
+
+ app.lawnchair.widget.WidgetStackInfo stackInfo = widgetStackView.getStackInfo();
+ if (stackInfo == null) {
+ return;
+ }
+
+ // For widget stacks, we allow resizing in both directions by default
+ // Use the minimum and maximum spans from the device profile
+ int resizeMode = AppWidgetProviderInfo.RESIZE_BOTH;
+ if (unlimited) {
+ mMinHSpan = 1;
+ mMinVSpan = 1;
+ mMaxHSpan = idp.numColumns;
+ mMaxVSpan = idp.numRows;
+ } else {
+ // Use current stack size as base, allow resizing from 1x1 to full screen
+ mMinHSpan = 1;
+ mMinVSpan = 1;
+ mMaxHSpan = idp.numColumns;
+ mMaxVSpan = idp.numRows;
+ }
+
+ // Show all resize handles for widget stacks
+ mVerticalResizeActive = mMinVSpan < idp.numRows && mMaxVSpan > 1 && mMinVSpan < mMaxVSpan;
+ if (!mVerticalResizeActive) {
+ mDragHandles[INDEX_TOP].setVisibility(GONE);
+ mDragHandles[INDEX_BOTTOM].setVisibility(GONE);
+ }
+ mHorizontalResizeActive = mMinHSpan < idp.numColumns && mMaxHSpan > 1 && mMinHSpan < mMaxHSpan;
+ if (!mHorizontalResizeActive) {
+ mDragHandles[INDEX_LEFT].setVisibility(GONE);
+ mDragHandles[INDEX_RIGHT].setVisibility(GONE);
+ }
+
+ // Hide reconfigure button for widget stacks (not applicable)
+ mReconfigureButton = (ImageButton) findViewById(R.id.widget_reconfigure_button);
+ mReconfigureButton.setVisibility(GONE);
+
+ CellLayoutLayoutParams lp = (CellLayoutLayoutParams) mWidgetStackView.getLayoutParams();
+ ItemInfo widgetInfo = (ItemInfo) mWidgetStackView.getTag();
+ if (widgetInfo != null) {
+ CellPos presenterPos = mLauncher.getCellPosMapper().mapModelToPresenter(widgetInfo);
+ lp.setCellX(presenterPos.cellX);
+ lp.setTmpCellX(presenterPos.cellX);
+ lp.setCellY(presenterPos.cellY);
+ lp.setTmpCellY(presenterPos.cellY);
+ lp.cellHSpan = widgetInfo.spanX;
+ lp.cellVSpan = widgetInfo.spanY;
+ lp.isLockedToGrid = true;
+ }
+
+ // When we create the resize frame, we first mark all cells as unoccupied. The
+ // appropriate
+ // cells (same if not resized, or different) will be marked as occupied when the
+ // resize
+ // frame is dismissed.
+ mCellLayout.markCellsAsUnoccupiedForView(mWidgetStackView);
+
+ if (widgetInfo != null) {
+ mLauncher.getStatsLogManager()
+ .logger()
+ .withInstanceId(logInstanceId)
+ .withItemInfo(widgetInfo)
+ .log(LAUNCHER_WIDGET_RESIZE_STARTED);
+ }
+
+ setOnKeyListener(this);
+ }
+
public boolean beginResizeIfPointInRegion(int x, int y) {
mLeftBorderActive = x < mTouchTargetWidth;
mRightBorderActive = x > getWidth() - mTouchTargetWidth;
@@ -491,7 +597,12 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
* Based on the current deltas, we determine if and how to resize the widget.
*/
private void resizeWidgetIfNeeded(boolean onDismiss) {
- ViewGroup.LayoutParams wlp = mWidgetView.getLayoutParams();
+ View targetView = mWidgetView != null ? mWidgetView : (View) mWidgetStackView;
+ if (targetView == null) {
+ return;
+ }
+
+ ViewGroup.LayoutParams wlp = targetView.getLayoutParams();
if (!(wlp instanceof CellLayoutLayoutParams)) {
return;
}
@@ -550,30 +661,101 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
mLastDirectionVector[1] = mDirectionVector[1];
}
- // We don't want to evaluate resize if a widget was pending config activity and
- // was already
- // occupying a space on the screen. This otherwise will cause reorder algorithm
- // evaluate a
- // different location for the widget and cause a jump.
- if (!(mWidgetView instanceof PendingAppWidgetHostView) && mCellLayout.createAreaForResize(
- cellX, cellY, spanX, spanY, mWidgetView, mDirectionVector, onDismiss)) {
- if (mStateAnnouncer != null && (lp.cellHSpan != spanX || lp.cellVSpan != spanY)) {
- mStateAnnouncer.announce(
- mLauncher.getString(R.string.widget_resized, spanX, spanY));
+ // Handle widget stack resize
+ if (mWidgetStackView != null) {
+ if (mCellLayout.createAreaForResize(
+ cellX, cellY, spanX, spanY, mWidgetStackView, mDirectionVector, onDismiss)) {
+ if (mStateAnnouncer != null && (lp.cellHSpan != spanX || lp.cellVSpan != spanY)) {
+ mStateAnnouncer.announce(
+ mLauncher.getString(R.string.widget_resized, spanX, spanY));
+ }
+
+ lp.setTmpCellX(cellX);
+ lp.setTmpCellY(cellY);
+ lp.cellHSpan = spanX;
+ lp.cellVSpan = spanY;
+ mRunningVInc += vSpanDelta;
+ mRunningHInc += hSpanDelta;
+
+ // Update stack info with new size
+ WidgetStackInfo stackInfo = mWidgetStackView.getStackInfo();
+ if (stackInfo != null) {
+ ItemInfo itemInfo = (ItemInfo) mWidgetStackView.getTag();
+ if (itemInfo != null) {
+ int container = itemInfo.container;
+ int screenId = mLauncher.getCellPosMapper().mapModelToPresenter(itemInfo).screenId;
+
+ WidgetStackInfo updatedStackInfo = stackInfo.copy(
+ stackInfo.getStackId(),
+ stackInfo.getWidgetIds(),
+ stackInfo.getCurrentIndex(),
+ stackInfo.getAutoRotate(),
+ container,
+ screenId,
+ cellX,
+ cellY,
+ spanX,
+ spanY
+ );
+
+ // Update all widgets in the stack to the new size
+ final com.android.launcher3.model.BgDataModel bgDataModel = mLauncher.getModel().getBgDataModel();
+ synchronized (bgDataModel) {
+ for (Integer widgetIdObj : stackInfo.getWidgetIds()) {
+ int widgetId = widgetIdObj;
+ for (ItemInfo item : bgDataModel.itemsIdMap) {
+ if (item instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo wInfo = (LauncherAppWidgetInfo) item;
+ if (wInfo.appWidgetId == widgetId) {
+ mLauncher.getModelWriter().modifyItemInDatabase(
+ wInfo, container, screenId,
+ cellX, cellY, spanX, spanY
+ );
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Save updated stack info to database
+ mLauncher.getModelWriter().saveWidgetStack(updatedStackInfo);
+
+ // Update the view with new stack info
+ mWidgetStackView.setStackInfo(updatedStackInfo);
+
+ // Update item info
+ itemInfo.spanX = spanX;
+ itemInfo.spanY = spanY;
+ }
+ }
}
+ } else if (mWidgetView != null) {
+ // We don't want to evaluate resize if a widget was pending config activity and
+ // was already
+ // occupying a space on the screen. This otherwise will cause reorder algorithm
+ // evaluate a
+ // different location for the widget and cause a jump.
+ if (!(mWidgetView instanceof PendingAppWidgetHostView) && mCellLayout.createAreaForResize(
+ cellX, cellY, spanX, spanY, mWidgetView, mDirectionVector, onDismiss)) {
+ if (mStateAnnouncer != null && (lp.cellHSpan != spanX || lp.cellVSpan != spanY)) {
+ mStateAnnouncer.announce(
+ mLauncher.getString(R.string.widget_resized, spanX, spanY));
+ }
- lp.setTmpCellX(cellX);
- lp.setTmpCellY(cellY);
- lp.cellHSpan = spanX;
- lp.cellVSpan = spanY;
- mRunningVInc += vSpanDelta;
- mRunningHInc += hSpanDelta;
+ lp.setTmpCellX(cellX);
+ lp.setTmpCellY(cellY);
+ lp.cellHSpan = spanX;
+ lp.cellVSpan = spanY;
+ mRunningVInc += vSpanDelta;
+ mRunningHInc += hSpanDelta;
- if (!onDismiss) {
- WidgetSizes.updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
+ if (!onDismiss) {
+ WidgetSizes.updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
+ }
}
}
- mWidgetView.requestLayout();
+ targetView.requestLayout();
}
@Override
@@ -583,11 +765,17 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
// We are done with resizing the widget. Save the widget size & position to
// LauncherModel
resizeWidgetIfNeeded(true);
- mLauncher.getStatsLogManager()
- .logger()
- .withInstanceId(logInstanceId)
- .withItemInfo((ItemInfo) mWidgetView.getTag())
- .log(LAUNCHER_WIDGET_RESIZE_COMPLETED);
+ View targetView = mWidgetView != null ? mWidgetView : (View) mWidgetStackView;
+ if (targetView != null) {
+ ItemInfo itemInfo = (ItemInfo) targetView.getTag();
+ if (itemInfo != null) {
+ mLauncher.getStatsLogManager()
+ .logger()
+ .withInstanceId(logInstanceId)
+ .withItemInfo(itemInfo)
+ .log(LAUNCHER_WIDGET_RESIZE_COMPLETED);
+ }
+ }
}
private void onTouchUp() {
@@ -609,11 +797,17 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
* relative to the {@link DragLayer}.
*/
private void getSnappedRectRelativeToDragLayer(@NonNull Rect out) {
- float scale = mWidgetView.getScaleToFit();
- if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()) {
+ View targetView = mWidgetView != null ? mWidgetView : (View) mWidgetStackView;
+ if (targetView == null) {
+ out.setEmpty();
+ return;
+ }
+
+ float scale = mWidgetView != null ? mWidgetView.getScaleToFit() : 1.0f;
+ if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get() && mWidgetView != null) {
getViewRectRelativeToDragLayer(out);
} else {
- mDragLayer.getViewRectRelativeToSelf(mWidgetView, out);
+ mDragLayer.getViewRectRelativeToSelf(targetView, out);
}
int width = 2 * mBackgroundPadding + Math.round(scale * out.width());
@@ -658,8 +852,12 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
// The widget is guaranteed to be attached to the cell layout at this point,
// thus setting
// the transition here
+ View targetView = mWidgetView != null ? mWidgetView : (View) mWidgetStackView;
+ if (targetView == null) {
+ return;
+ }
if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()
- && mWidgetView.getLayoutTransition() == null) {
+ && mWidgetView != null && mWidgetView.getLayoutTransition() == null) {
final LayoutTransition transition = new LayoutTransition();
transition.setDuration(RESIZE_TRANSITION_DURATION_MS);
transition.enableTransitionType(LayoutTransition.CHANGING);
@@ -813,12 +1011,14 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
@Override
protected void handleClose(boolean animate) {
- if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()) {
- mWidgetView.clearCellChildViewPreLayoutListener();
- mWidgetView.setLayoutTransition(null);
+ if (mWidgetView != null) {
+ if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()) {
+ mWidgetView.clearCellChildViewPreLayoutListener();
+ mWidgetView.setLayoutTransition(null);
+ }
+ mWidgetView.removeOnLayoutChangeListener(mWidgetViewLayoutListener);
}
mDragLayer.removeView(this);
- mWidgetView.removeOnLayoutChangeListener(mWidgetViewLayoutListener);
}
private void updateInvalidResizeEffect(CellLayout cellLayout, CellLayout pairedCellLayout,
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index ae72bcda76..e28c4412fa 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -56,7 +56,6 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -2816,12 +2815,12 @@ public class Workspace extends PagedView
lp.isLockedToGrid = true;
if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
- cell instanceof LauncherAppWidgetHostView) {
+ (cell instanceof LauncherAppWidgetHostView || cell instanceof WidgetStackView)) {
// We post this call so that the widget has a chance to be placed
// in its final location
onCompleteRunnable = getWidgetResizeFrameRunnable(options,
- (LauncherAppWidgetHostView) cell, dropTargetLayout, forceWidgetResize);
+ cell, dropTargetLayout, forceWidgetResize);
}
// If this is a widget stack, update the stack info position
@@ -2906,7 +2905,7 @@ public class Workspace extends PagedView
if (pageIsVisible) {
onCompleteRunnable = getWidgetResizeFrameRunnable(options,
- (LauncherAppWidgetHostView) cell, cellLayout, forceWidgetResize);
+ cell, cellLayout, forceWidgetResize);
}
}
}
@@ -2971,15 +2970,28 @@ public class Workspace extends PagedView
@Nullable
private Runnable getWidgetResizeFrameRunnable(DragOptions options,
- LauncherAppWidgetHostView hostView, CellLayout cellLayout, boolean force) {
- AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
- boolean shouldResize = (pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) || force;
- if (pInfo != null && shouldResize && !options.isAccessibleDrag) {
- return () -> {
- if (!isPageInTransition()) {
- AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
- }
- };
+ View widgetView, CellLayout cellLayout, boolean force) {
+ if (widgetView instanceof LauncherAppWidgetHostView) {
+ LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) widgetView;
+ AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
+ boolean shouldResize = (pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) || force;
+ if (pInfo != null && shouldResize && !options.isAccessibleDrag) {
+ return () -> {
+ if (!isPageInTransition()) {
+ AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
+ }
+ };
+ }
+ } else if (widgetView instanceof WidgetStackView) {
+ WidgetStackView stackView = (WidgetStackView) widgetView;
+ // Widget stacks are always resizable
+ if (!options.isAccessibleDrag) {
+ return () -> {
+ if (!isPageInTransition()) {
+ AppWidgetResizeFrame.showForWidgetStack(stackView, cellLayout);
+ }
+ };
+ }
}
return null;
}