summaryrefslogtreecommitdiff
path: root/src/com/android/launcher3/widget
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/widget')
-rw-r--r--src/com/android/launcher3/widget/BaseWidgetSheet.java176
-rw-r--r--src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java2
-rw-r--r--src/com/android/launcher3/widget/LauncherAppWidgetHostView.java76
-rw-r--r--src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java2
-rw-r--r--src/com/android/launcher3/widget/WidgetManagerHelper.java11
-rw-r--r--src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java19
-rw-r--r--src/com/android/launcher3/widget/custom/CustomWidgetManager.java115
-rw-r--r--src/com/android/launcher3/widget/picker/WidgetsFullSheet.java129
-rw-r--r--src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java30
9 files changed, 286 insertions, 274 deletions
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index dcc86a15e9..5171fa218a 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -16,12 +16,12 @@
package com.android.launcher3.widget;
import static com.android.app.animation.Interpolators.EMPHASIZED;
-import static com.android.launcher3.config.FeatureFlags.LARGE_SCREEN_WIDGET_PICKER;
+import static com.android.launcher3.Flags.enableUnfoldedTwoPanePicker;
+import static com.android.launcher3.LauncherPrefs.WIDGETS_EDUCATION_TIP_SEEN;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
-import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
@@ -29,54 +29,47 @@ import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.WindowInsets;
import android.view.animation.Interpolator;
-import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.core.view.ViewCompat;
+import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
-import com.android.launcher3.DragSource;
-import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.launcher3.views.AbstractSlideInView;
-import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.ArrowTipView;
/**
* Base class for various widgets popup
*/
-public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
- implements OnClickListener, OnLongClickListener, DragSource,
+public abstract class BaseWidgetSheet extends AbstractSlideInView<BaseActivity>
+ implements OnClickListener, OnLongClickListener,
PopupDataProvider.PopupDataChangeListener, Insettable, OnDeviceProfileChangeListener {
/** The default number of cells that can fit horizontally in a widget sheet. */
public static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
- protected static final String KEY_WIDGETS_EDUCATION_TIP_SEEN =
- "launcher.widgets_education_tip_seen";
protected final Rect mInsets = new Rect();
- /* Touch handling related member variables. */
- private Toast mWidgetInstructionToast;
-
@Px protected int mContentHorizontalMargin;
@Px protected int mWidgetCellHorizontalPadding;
protected int mNavBarScrimHeight;
private final Paint mNavBarScrimPaint;
+ private boolean mDisableNavBarScrim = false;
+
public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContentHorizontalMargin = getResources().getDimensionPixelSize(
@@ -115,36 +108,35 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
mNavBarScrimPaint.setColor(navBarScrimColor);
invalidate();
}
+ setupNavBarColor();
}
@Override
public final void onClick(View v) {
- Object tag = null;
if (v instanceof WidgetCell) {
- tag = v.getTag();
- } else if (v.getParent() instanceof WidgetCell) {
- tag = ((WidgetCell) v.getParent()).getTag();
+ mActivityContext.getItemOnClickListener().onClick(v);
+ } else if (v.getParent() instanceof WidgetCell wc) {
+ mActivityContext.getItemOnClickListener().onClick(wc);
}
- if (tag instanceof PendingAddShortcutInfo) {
- mWidgetInstructionToast = showShortcutToast(getContext(), mWidgetInstructionToast);
- } else {
- mWidgetInstructionToast = showWidgetToast(getContext(), mWidgetInstructionToast);
- }
-
}
@Override
public boolean onLongClick(View v) {
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Widgets.onLongClick");
v.cancelLongPress();
- if (!ItemLongClickListener.canStartDrag(mActivityContext)) return false;
+ boolean result;
if (v instanceof WidgetCell) {
- return beginDraggingWidget((WidgetCell) v);
- } else if (v.getParent() instanceof WidgetCell) {
- return beginDraggingWidget((WidgetCell) v.getParent());
+ result = mActivityContext.getAllAppsItemLongClickListener().onLongClick(v);
+ } else if (v.getParent() instanceof WidgetCell wc) {
+ result = mActivityContext.getAllAppsItemLongClickListener().onLongClick(wc);
+ } else {
+ return true;
+ }
+ if (result) {
+ close(true);
}
- return true;
+ return result;
}
@Override
@@ -158,8 +150,15 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
}
}
+ /** Enables or disables the sheet's nav bar scrim. */
+ public void disableNavBarScrim(boolean disable) {
+ mDisableNavBarScrim = disable;
+ }
+
private int getNavBarScrimHeight(WindowInsets insets) {
- if (Utilities.ATLEAST_Q) {
+ if (mDisableNavBarScrim) {
+ return 0;
+ } else if (Utilities.ATLEAST_Q) {
return insets.getTappableElementInsets().bottom;
} else {
return insets.getStableInsetBottom();
@@ -193,14 +192,8 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
int widthUsed;
if (deviceProfile.isTablet) {
- int margin = deviceProfile.allAppsLeftRightMargin;
- if (deviceProfile.isLandscape
- && LARGE_SCREEN_WIDGET_PICKER.get()
- && !deviceProfile.isTwoPanels) {
- margin = getResources().getDimensionPixelSize(
- R.dimen.widget_picker_landscape_tablet_left_right_margin);
- }
- widthUsed = Math.max(2 * margin, 2 * (mInsets.left + mInsets.right));
+ widthUsed = Math.max(2 * getTabletMargin(deviceProfile),
+ 2 * (mInsets.left + mInsets.right));
} else if (mInsets.bottom > 0) {
widthUsed = mInsets.left + mInsets.right;
} else {
@@ -215,39 +208,16 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
MeasureSpec.getSize(heightMeasureSpec));
}
- private boolean beginDraggingWidget(WidgetCell v) {
- // Get the widget preview as the drag representation
- WidgetImageView image = v.getWidgetView();
-
- // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
- // we abort the drag.
- if (image.getDrawable() == null && v.getAppWidgetHostViewPreview() == null) {
- return false;
+ private int getTabletMargin(DeviceProfile deviceProfile) {
+ if (deviceProfile.isLandscape && !deviceProfile.isTwoPanels) {
+ return getResources().getDimensionPixelSize(
+ R.dimen.widget_picker_landscape_tablet_left_right_margin);
}
-
- PendingItemDragHelper dragHelper = new PendingItemDragHelper(v);
- // RemoteViews are being rendered in AppWidgetHostView in WidgetCell. And thus, the scale of
- // RemoteViews is equivalent to the AppWidgetHostView scale.
- dragHelper.setRemoteViewsPreview(v.getRemoteViewsPreview(), v.getAppWidgetHostViewScale());
- dragHelper.setAppWidgetHostViewPreview(v.getAppWidgetHostViewPreview());
-
- if (image.getDrawable() != null) {
- int[] loc = new int[2];
- getPopupContainer().getLocationInDragLayer(image, loc);
-
- dragHelper.startDrag(image.getBitmapBounds(), image.getDrawable().getIntrinsicWidth(),
- image.getWidth(), new Point(loc[0], loc[1]), this, new DragOptions());
- } else {
- NavigableAppWidgetHostView preview = v.getAppWidgetHostViewPreview();
- int[] loc = new int[2];
- getPopupContainer().getLocationInDragLayer(preview, loc);
- Rect r = new Rect();
- preview.getWorkspaceVisualDragBounds(r);
- dragHelper.startDrag(r, preview.getMeasuredWidth(), preview.getMeasuredWidth(),
- new Point(loc[0], loc[1]), this, new DragOptions());
+ if (deviceProfile.isTwoPanels && enableUnfoldedTwoPanePicker()) {
+ return getResources().getDimensionPixelSize(
+ R.dimen.widget_picker_two_panels_left_right_margin);
}
- close(true);
- return true;
+ return deviceProfile.allAppsLeftRightMargin;
}
@Override
@@ -256,14 +226,6 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
? EMPHASIZED : super.getIdleInterpolator();
}
- //
- // Drag related handling methods that implement {@link DragSource} interface.
- //
-
- @Override
- public void onDropCompleted(View target, DragObject d, boolean success) { }
-
-
protected void onCloseComplete() {
super.onCloseComplete();
clearNavBarColor();
@@ -275,48 +237,22 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
}
protected void setupNavBarColor() {
- boolean isSheetDark = Themes.getAttrBoolean(getContext(), R.attr.isMainColorDark);
- getSystemUiController().updateUiState(
- SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET,
- isSheetDark ? SystemUiController.FLAG_DARK_NAV : SystemUiController.FLAG_LIGHT_NAV);
- }
+ boolean isNavBarDark = Themes.getAttrBoolean(getContext(), R.attr.isMainColorDark);
- protected SystemUiController getSystemUiController() {
- return mActivityContext.getSystemUiController();
- }
-
- /**
- * Show Widget tap toast prompting user to drag instead
- */
- public static Toast showWidgetToast(Context context, Toast toast) {
- // Let the user know that they have to long press to add a widget
- if (toast != null) {
- toast.cancel();
+ // In light mode, landscape reverses navbar background color.
+ boolean isPhoneLandscape =
+ !mActivityContext.getDeviceProfile().isTablet && mInsets.bottom == 0;
+ if (!isNavBarDark && isPhoneLandscape) {
+ isNavBarDark = true;
}
- CharSequence msg = Utilities.wrapForTts(
- context.getText(R.string.long_press_widget_to_add),
- context.getString(R.string.long_accessible_way_to_add));
- toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
- toast.show();
- return toast;
+ getSystemUiController().updateUiState(SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET,
+ isNavBarDark ? SystemUiController.FLAG_DARK_NAV
+ : SystemUiController.FLAG_LIGHT_NAV);
}
- /**
- * Show shortcut tap toast prompting user to drag instead.
- */
- private static Toast showShortcutToast(Context context, Toast toast) {
- // Let the user know that they have to long press to add a widget
- if (toast != null) {
- toast.cancel();
- }
-
- CharSequence msg = Utilities.wrapForTts(
- context.getText(R.string.long_press_shortcut_to_add),
- context.getString(R.string.long_accessible_way_to_add_shortcut));
- toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
- toast.show();
- return toast;
+ protected SystemUiController getSystemUiController() {
+ return mActivityContext.getSystemUiController();
}
/** Shows education tip on top center of {@code view} if view is laid out. */
@@ -333,22 +269,22 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
/* arrowXCoord= */coords[0] + view.getWidth() / 2,
/* yCoord= */coords[1]);
if (arrowTipView != null) {
- mActivityContext.getSharedPrefs().edit()
- .putBoolean(KEY_WIDGETS_EDUCATION_TIP_SEEN, true).apply();
+ LauncherPrefs.get(getContext()).put(WIDGETS_EDUCATION_TIP_SEEN, true);
}
return arrowTipView;
}
/** Returns {@code true} if tip has previously been shown on any of {@link BaseWidgetSheet}. */
protected boolean hasSeenEducationTip() {
- return mActivityContext.getSharedPrefs().getBoolean(KEY_WIDGETS_EDUCATION_TIP_SEEN, false)
+ return LauncherPrefs.get(getContext()).get(WIDGETS_EDUCATION_TIP_SEEN)
|| Utilities.isRunningInTestHarness();
}
@Override
protected void setTranslationShift(float translationShift) {
super.setTranslationShift(translationShift);
- Launcher launcher = ActivityContext.lookupContext(getContext());
- launcher.onWidgetsTransition(1 - translationShift);
+ if (mActivityContext instanceof Launcher ls) {
+ ls.onWidgetsTransition(1 - translationShift);
+ }
}
}
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index 6f74fd965a..99485bec2e 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -257,8 +257,6 @@ public class DatabaseWidgetPreviewLoader {
throw new RuntimeException("Max size is too small for preview");
}
return BitmapRenderer.createHardwareBitmap(size, size, c -> {
- drawBoxWithShadow(c, size, size);
-
LauncherIcons li = LauncherIcons.obtain(mContext);
Drawable icon = li.createBadgedIconBitmap(
mutateOnMainThread(info.getFullResIcon(
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 340a61e1c5..5d069ed264 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -19,24 +19,25 @@ package com.android.launcher3.widget;
import android.annotation.TargetApi;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
+import android.os.Parcelable;
import android.os.SystemClock;
import android.os.Trace;
import android.util.Log;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.AdapterView;
import android.widget.Advanceable;
import android.widget.RemoteViews;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.CheckLongPressHelper;
@@ -63,6 +64,8 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
private static final long ADVANCE_INTERVAL = 20000;
private static final long ADVANCE_STAGGER = 250;
+ private @Nullable CellChildViewPreLayoutListener mCellChildViewPreLayoutListener;
+
// Maintains a list of widget ids which are supposed to be auto advanced.
private static final SparseBooleanArray sAutoAdvanceWidgetIds = new SparseBooleanArray();
// Maximum duration for which updates can be deferred.
@@ -74,9 +77,6 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
private final CheckLongPressHelper mLongPressHelper;
protected final Launcher mLauncher;
- @ViewDebug.ExportedProperty(category = "launcher")
- private boolean mReinflateOnConfigChange;
-
// Maintain the color manager.
private final LocalColorExtractor mColorExtractor;
@@ -171,17 +171,6 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
// The provider info or the views might have changed.
checkIfAutoAdvance();
-
- // It is possible that widgets can receive updates while launcher is not in the foreground.
- // Consequently, the widgets will be inflated for the orientation of the foreground activity
- // (framework issue). On resuming, we ensure that any widgets are inflated for the current
- // orientation.
- mReinflateOnConfigChange = !isSameOrientation();
- }
-
- private boolean isSameOrientation() {
- return mLauncher.getResources().getConfiguration().orientation ==
- mLauncher.getOrientation();
}
private boolean checkScrollableRecursively(ViewGroup viewGroup) {
@@ -335,6 +324,26 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
requestLayout();
}
+ /**
+ * Set the pre-layout listener
+ * @param listener The listener to be notified when {@code CellLayout} is to layout this view
+ */
+ public void setCellChildViewPreLayoutListener(
+ @NonNull CellChildViewPreLayoutListener listener) {
+ mCellChildViewPreLayoutListener = listener;
+ }
+
+ /** @return The current cell layout listener */
+ @Nullable
+ public CellChildViewPreLayoutListener getCellChildViewPreLayoutListener() {
+ return mCellChildViewPreLayoutListener;
+ }
+
+ /** Clear the listener for the pre-layout in CellLayout */
+ public void clearCellChildViewPreLayoutListener() {
+ mCellChildViewPreLayoutListener = null;
+ }
+
@Override
public void onColorsChanged(SparseIntArray colors) {
if (isDeferringUpdates()) {
@@ -425,17 +434,6 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
scheduleNextAdvance();
}
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- // Only reinflate when the final configuration is same as the required configuration
- if (mReinflateOnConfigChange && isSameOrientation()) {
- mReinflateOnConfigChange = false;
- reInflate();
- }
- }
-
public void reInflate() {
if (!isAttachedToWindow()) {
return;
@@ -460,4 +458,28 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
}
return false;
}
+
+ /**
+ * Listener interface to be called when {@code CellLayout} is about to layout this child view
+ */
+ public interface CellChildViewPreLayoutListener {
+ /**
+ * Notify the bound changes to this view on pre-layout
+ * @param v The view which the listener is set for
+ * @param left The new left coordinate of this view
+ * @param top The new top coordinate of this view
+ * @param right The new right coordinate of this view
+ * @param bottom The new bottom coordinate of this view
+ */
+ void notifyBoundChangeOnPreLayout(View v, int left, int top, int right, int bottom);
+ }
+
+ @Override
+ protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+ try {
+ super.dispatchRestoreInstanceState(container);
+ } catch (Exception e) {
+ Log.i(TAG, "Exception: " + e);
+ }
+ }
}
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index 10aef9ac66..ef51d152c7 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -67,7 +67,7 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo
*/
public int maxSpanY;
- private boolean mIsMinSizeFulfilled;
+ protected boolean mIsMinSizeFulfilled;
public static LauncherAppWidgetProviderInfo fromProviderInfo(Context context,
AppWidgetProviderInfo info) {
diff --git a/src/com/android/launcher3/widget/WidgetManagerHelper.java b/src/com/android/launcher3/widget/WidgetManagerHelper.java
index 737cdbd61f..0860e72420 100644
--- a/src/com/android/launcher3/widget/WidgetManagerHelper.java
+++ b/src/com/android/launcher3/widget/WidgetManagerHelper.java
@@ -57,10 +57,15 @@ public class WidgetManagerHelper {
/**
* @see AppWidgetManager#getAppWidgetInfo(int)
*/
- public LauncherAppWidgetProviderInfo getLauncherAppWidgetInfo(int appWidgetId) {
- if (appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
- return CustomWidgetManager.INSTANCE.get(mContext).getWidgetProvider(appWidgetId);
+ public LauncherAppWidgetProviderInfo getLauncherAppWidgetInfo(
+ int appWidgetId, ComponentName componentName) {
+
+ // For custom widgets.
+ if (appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID && !CustomWidgetManager
+ .INSTANCE.get(mContext).getWidgetIdForCustomProvider(componentName).equals("")) {
+ return CustomWidgetManager.INSTANCE.get(mContext).getWidgetProvider(componentName);
}
+
AppWidgetProviderInfo info = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
return info == null ? null : LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
}
diff --git a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
index 8b3bbce1c5..44571a6c4a 100644
--- a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
@@ -33,14 +33,15 @@ import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
public class CustomAppWidgetProviderInfo extends LauncherAppWidgetProviderInfo
implements Parcelable {
- public final int providerId;
+ public final String providerId;
- protected CustomAppWidgetProviderInfo(Parcel parcel, boolean readSelf, int providerId) {
+ protected CustomAppWidgetProviderInfo(Parcel parcel, boolean readSelf, String providerId) {
super(parcel);
if (readSelf) {
- this.providerId = parcel.readInt();
+ this.providerId = parcel.readString();
- provider = new ComponentName(parcel.readString(), CLS_CUSTOM_WIDGET_PREFIX + providerId);
+ provider = new ComponentName(parcel.readString(),
+ CLS_CUSTOM_WIDGET_PREFIX + parcel.readString());
label = parcel.readString();
initialLayout = parcel.readInt();
@@ -58,7 +59,10 @@ public class CustomAppWidgetProviderInfo extends LauncherAppWidgetProviderInfo
}
@Override
- public void initSpans(Context context, InvariantDeviceProfile idp) { }
+ public void initSpans(Context context, InvariantDeviceProfile idp) {
+ mIsMinSizeFulfilled = Math.min(spanX, minSpanX) <= idp.numColumns
+ && Math.min(spanY, minSpanY) <= idp.numRows;
+ }
@Override
public String getLabel(PackageManager packageManager) {
@@ -73,8 +77,9 @@ public class CustomAppWidgetProviderInfo extends LauncherAppWidgetProviderInfo
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
- out.writeInt(providerId);
+ out.writeString(providerId);
out.writeString(provider.getPackageName());
+ out.writeString(provider.getClassName());
out.writeString(label);
out.writeInt(initialLayout);
@@ -93,7 +98,7 @@ public class CustomAppWidgetProviderInfo extends LauncherAppWidgetProviderInfo
@Override
public CustomAppWidgetProviderInfo createFromParcel(Parcel parcel) {
- return new CustomAppWidgetProviderInfo(parcel, true, 0);
+ return new CustomAppWidgetProviderInfo(parcel, true, "");
}
@Override
diff --git a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
index 2e2a968a44..7cf022175b 100644
--- a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
+++ b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
@@ -16,7 +16,8 @@
package com.android.launcher3.widget.custom;
-import static com.android.launcher3.widget.LauncherAppWidgetProviderInfo.CLS_CUSTOM_WIDGET_PREFIX;
+import static com.android.launcher3.config.FeatureFlags.SMARTSPACE_AS_A_WIDGET;
+import static com.android.launcher3.model.data.LauncherAppWidgetInfo.CUSTOM_WIDGET_ID;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
@@ -24,12 +25,12 @@ import android.content.ComponentName;
import android.content.Context;
import android.os.Parcel;
import android.os.Process;
-import android.util.SparseArray;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.R;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.PackageUserKey;
@@ -39,8 +40,11 @@ import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.systemui.plugins.CustomWidgetPlugin;
import com.android.systemui.plugins.PluginListener;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
@@ -52,24 +56,37 @@ public class CustomWidgetManager implements PluginListener<CustomWidgetPlugin>,
public static final MainThreadInitializedObject<CustomWidgetManager> INSTANCE =
new MainThreadInitializedObject<>(CustomWidgetManager::new);
+ private static final String TAG = "CustomWidgetManager";
private final Context mContext;
- /**
- * auto provider Id is an ever-increasing number that serves as the providerId whenever a new
- * custom widget has been connected.
- */
- private int mAutoProviderId = 0;
- private final SparseArray<CustomWidgetPlugin> mPlugins;
+ private final HashMap<String, CustomWidgetPlugin> mPlugins;
private final List<CustomAppWidgetProviderInfo> mCustomWidgets;
- private final SparseArray<ComponentName> mWidgetsIdMap;
+ private final HashMap<ComponentName, String> mWidgetsIdMap;
private Consumer<PackageUserKey> mWidgetRefreshCallback;
private CustomWidgetManager(Context context) {
mContext = context;
- mPlugins = new SparseArray<>();
+ mPlugins = new HashMap<>();
mCustomWidgets = new ArrayList<>();
- mWidgetsIdMap = new SparseArray<>();
+ mWidgetsIdMap = new HashMap<>();
PluginManagerWrapper.INSTANCE.get(context)
.addPluginListener(this, CustomWidgetPlugin.class, true);
+
+ if (SMARTSPACE_AS_A_WIDGET.get()) {
+ for (String s: context.getResources()
+ .getStringArray(R.array.custom_widget_providers)) {
+ try {
+ Class<?> cls = Class.forName(s);
+ CustomWidgetPlugin plugin = (CustomWidgetPlugin)
+ cls.getDeclaredConstructor(Context.class).newInstance(context);
+ mPlugins.put(plugin.getId(), plugin);
+ onPluginConnected(mPlugins.get(plugin.getId()), context);
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+ | ClassCastException | NoSuchMethodException
+ | InvocationTargetException e) {
+ Log.e(TAG, "Exception found when trying to add custom widgets: " + e);
+ }
+ }
+ }
}
@Override
@@ -79,28 +96,41 @@ public class CustomWidgetManager implements PluginListener<CustomWidgetPlugin>,
@Override
public void onPluginConnected(CustomWidgetPlugin plugin, Context context) {
- mPlugins.put(mAutoProviderId, plugin);
List<AppWidgetProviderInfo> providers = AppWidgetManager.getInstance(context)
.getInstalledProvidersForProfile(Process.myUserHandle());
if (providers.isEmpty()) return;
Parcel parcel = Parcel.obtain();
providers.get(0).writeToParcel(parcel, 0);
parcel.setDataPosition(0);
- CustomAppWidgetProviderInfo info = newInfo(mAutoProviderId, plugin, parcel, context);
+ CustomAppWidgetProviderInfo info = newInfo(plugin.getId(), plugin, parcel, context);
parcel.recycle();
mCustomWidgets.add(info);
- mWidgetsIdMap.put(mAutoProviderId, info.provider);
- mWidgetRefreshCallback.accept(null);
- mAutoProviderId++;
+ mWidgetsIdMap.put(info.provider, plugin.getId());
}
@Override
public void onPluginDisconnected(CustomWidgetPlugin plugin) {
- int providerId = findProviderId(plugin);
- if (providerId == -1) return;
- mPlugins.remove(providerId);
- mCustomWidgets.remove(getWidgetProvider(providerId));
- mWidgetsIdMap.remove(providerId);
+ String providerId = plugin.getId();
+ if (mPlugins.containsKey(providerId)) {
+ mPlugins.remove(providerId);
+ }
+
+ ComponentName cn = null;
+ for (Map.Entry entry: mWidgetsIdMap.entrySet()) {
+ if (entry.getValue().equals(providerId)) {
+ cn = (ComponentName) entry.getKey();
+ }
+ }
+
+ if (cn != null) {
+ mWidgetsIdMap.remove(cn);
+ for (int i = 0; i < mCustomWidgets.size(); i++) {
+ if (mCustomWidgets.get(i).getComponent().equals(cn)) {
+ mCustomWidgets.remove(i);
+ return;
+ }
+ }
+ }
}
/**
@@ -131,12 +161,11 @@ public class CustomWidgetManager implements PluginListener<CustomWidgetPlugin>,
/**
* Returns the widget id for a specific provider.
*/
- public int getWidgetIdForCustomProvider(@NonNull ComponentName provider) {
- int index = mWidgetsIdMap.indexOfValue(provider);
- if (index >= 0) {
- return LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - mWidgetsIdMap.keyAt(index);
+ public String getWidgetIdForCustomProvider(@NonNull ComponentName provider) {
+ if (mWidgetsIdMap.containsKey(provider)) {
+ return mWidgetsIdMap.get(provider);
} else {
- return AppWidgetManager.INVALID_APPWIDGET_ID;
+ return "";
}
}
@@ -144,38 +173,26 @@ public class CustomWidgetManager implements PluginListener<CustomWidgetPlugin>,
* Returns the widget provider in respect to given widget id.
*/
@Nullable
- public LauncherAppWidgetProviderInfo getWidgetProvider(int widgetId) {
- ComponentName cn = mWidgetsIdMap.get(LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - widgetId);
+ public LauncherAppWidgetProviderInfo getWidgetProvider(ComponentName componentName) {
for (LauncherAppWidgetProviderInfo info : mCustomWidgets) {
- if (info.provider.equals(cn)) return info;
+ if (info.provider.equals(componentName)) return info;
}
return null;
}
- private static CustomAppWidgetProviderInfo newInfo(int providerId, CustomWidgetPlugin plugin,
+ private static CustomAppWidgetProviderInfo newInfo(String providerId, CustomWidgetPlugin plugin,
Parcel parcel, Context context) {
CustomAppWidgetProviderInfo info = new CustomAppWidgetProviderInfo(
parcel, false, providerId);
- info.provider = new ComponentName(
- context.getPackageName(), CLS_CUSTOM_WIDGET_PREFIX + providerId);
-
- info.label = plugin.getLabel();
- info.resizeMode = plugin.getResizeMode();
-
- info.spanX = plugin.getSpanX();
- info.spanY = plugin.getSpanY();
- info.minSpanX = plugin.getMinSpanX();
- info.minSpanY = plugin.getMinSpanY();
+ plugin.updateWidgetInfo(info, context);
return info;
}
- private int findProviderId(CustomWidgetPlugin plugin) {
- for (int i = 0; i < mPlugins.size(); i++) {
- int providerId = mPlugins.keyAt(i);
- if (mPlugins.get(providerId) == plugin) {
- return providerId;
- }
- }
- return -1;
+ /**
+ * Returns an id to set as the appWidgetId for a custom widget.
+ */
+ public int allocateCustomAppWidgetId(ComponentName componentName) {
+ return CUSTOM_WIDGET_ID - mCustomWidgets.indexOf(getWidgetProvider(componentName));
}
+
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index a4b605cccd..e9a590b814 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -17,14 +17,14 @@ package com.android.launcher3.widget.picker;
import static android.view.View.MeasureSpec.makeMeasureSpec;
+import static com.android.launcher3.Flags.enableUnfoldedTwoPanePicker;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
-import static com.android.launcher3.config.FeatureFlags.LARGE_SCREEN_WIDGET_PICKER;
+import static com.android.launcher3.LauncherPrefs.WIDGETS_EDUCATION_DIALOG_SEEN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
import android.animation.Animator;
import android.content.Context;
-import android.content.pm.LauncherApps;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -40,6 +40,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.Button;
@@ -54,8 +55,10 @@ import androidx.annotation.VisibleForTesting;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
+import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
@@ -69,7 +72,6 @@ import com.android.launcher3.views.SpringRelativeLayout;
import com.android.launcher3.views.StickyHeaderLayout;
import com.android.launcher3.views.WidgetsEduView;
import com.android.launcher3.widget.BaseWidgetSheet;
-import com.android.launcher3.widget.LauncherWidgetHolder.ProviderChangedListener;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.picker.search.SearchModeListener;
import com.android.launcher3.widget.picker.search.WidgetsSearchBar;
@@ -86,27 +88,24 @@ import java.util.stream.IntStream;
* Popup for showing the full list of available widgets
*/
public class WidgetsFullSheet extends BaseWidgetSheet
- implements ProviderChangedListener, OnActivePageChangedListener,
+ implements OnActivePageChangedListener,
WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener {
private static final long FADE_IN_DURATION = 150;
private static final long EDUCATION_TIP_DELAY_MS = 200;
private static final long EDUCATION_DIALOG_DELAY_MS = 500;
- private static final float VERTICAL_START_POSITION = 0.3f;
+
// The widget recommendation table can easily take over the entire screen on devices with small
// resolution or landscape on phone. This ratio defines the max percentage of content area that
// the table can display.
private static final float RECOMMENDATION_TABLE_HEIGHT_RATIO = 0.75f;
- private static final String KEY_WIDGETS_EDUCATION_DIALOG_SEEN =
- "launcher.widgets_education_dialog_seen";
+ private final UserCache mUserCache;
private final UserManagerState mUserManagerState = new UserManagerState();
private final UserHandle mCurrentUser = Process.myUserHandle();
private final Predicate<WidgetsListBaseEntry> mPrimaryWidgetsFilter =
entry -> mCurrentUser.equals(entry.mPkgItem.user);
- private final Predicate<WidgetsListBaseEntry> mWorkWidgetsFilter =
- entry -> !mCurrentUser.equals(entry.mPkgItem.user)
- && !mUserManagerState.isUserQuiet(entry.mPkgItem.user);
+ private final Predicate<WidgetsListBaseEntry> mWorkWidgetsFilter;
protected final boolean mHasWorkProfile;
protected boolean mHasRecommendedWidgets;
protected final SparseArray<AdapterHolder> mAdapters = new SparseArray();
@@ -164,9 +163,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet
private boolean mIsInSearchMode;
private boolean mIsNoWidgetsViewNeeded;
@Px private int mMaxSpanPerRow;
- private DeviceProfile mDeviceProfile;
-
- private int mOrientation;
+ protected DeviceProfile mDeviceProfile;
protected TextView mNoWidgetsView;
protected StickyHeaderLayout mSearchScrollView;
@@ -179,20 +176,23 @@ public class WidgetsFullSheet extends BaseWidgetSheet
public WidgetsFullSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mDeviceProfile = Launcher.getLauncher(context).getDeviceProfile();
- mHasWorkProfile = context.getSystemService(LauncherApps.class).getProfiles().size() > 1;
- mOrientation = context.getResources().getConfiguration().orientation;
+ mDeviceProfile = mActivityContext.getDeviceProfile();
+ mUserCache = UserCache.INSTANCE.get(context);
+ mHasWorkProfile = mUserCache.getUserProfiles()
+ .stream()
+ .anyMatch(user -> mUserCache.getUserInfo(user).isWork());
+ mWorkWidgetsFilter = entry -> mHasWorkProfile
+ && mUserCache.getUserInfo(entry.mPkgItem.user).isWork();
mAdapters.put(AdapterHolder.PRIMARY, new AdapterHolder(AdapterHolder.PRIMARY));
mAdapters.put(AdapterHolder.WORK, new AdapterHolder(AdapterHolder.WORK));
mAdapters.put(AdapterHolder.SEARCH, new AdapterHolder(AdapterHolder.SEARCH));
Resources resources = getResources();
+ mUserManagerState.init(UserCache.INSTANCE.get(context),
+ context.getSystemService(UserManager.class));
mTabsHeight = mHasWorkProfile
? resources.getDimensionPixelSize(R.dimen.all_apps_header_pill_height)
: 0;
-
- mUserManagerState.init(UserCache.INSTANCE.get(context),
- context.getSystemService(UserManager.class));
}
public WidgetsFullSheet(Context context, AttributeSet attrs) {
@@ -310,7 +310,9 @@ public class WidgetsFullSheet extends BaseWidgetSheet
if (adapterHolder.mAdapterType == AdapterHolder.SEARCH) {
mNoWidgetsView.setText(R.string.no_search_results);
} else if (adapterHolder.mAdapterType == AdapterHolder.WORK
- && mUserManagerState.isAnyProfileQuietModeEnabled()
+ && mUserCache.getUserProfiles().stream()
+ .filter(userHandle -> mUserCache.getUserInfo(userHandle).isWork())
+ .anyMatch(mUserManagerState::isUserQuiet)
&& mActivityContext.getStringCache() != null) {
mNoWidgetsView.setText(mActivityContext.getStringCache().workProfilePausedTitle);
} else {
@@ -348,15 +350,14 @@ public class WidgetsFullSheet extends BaseWidgetSheet
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mActivityContext.getAppWidgetHolder().addProviderChangeListener(this);
- notifyWidgetProvidersChanged();
+ LauncherAppState.getInstance(mActivityContext).getModel()
+ .refreshAndBindWidgetsAndShortcuts(null);
onRecommendedWidgetsBound();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mActivityContext.getAppWidgetHolder().removeProviderChangeListener(this);
mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView
.removeOnAttachStateChangeListener(mBindScrollbarInSearchMode);
if (mHasWorkProfile) {
@@ -477,11 +478,6 @@ public class WidgetsFullSheet extends BaseWidgetSheet
}
@Override
- public void notifyWidgetProvidersChanged() {
- mActivityContext.refreshAndBindWidgetsForPackageUser(null);
- }
-
- @Override
public void onWidgetsBound() {
if (mIsInSearchMode) {
return;
@@ -623,7 +619,6 @@ public class WidgetsFullSheet extends BaseWidgetSheet
if (animate) {
if (getPopupContainer().getInsets().bottom > 0) {
mContent.setAlpha(0);
- setTranslationShift(VERTICAL_START_POSITION);
}
setUpOpenAnimation(mActivityContext.getDeviceProfile().bottomSheetOpenDuration);
Animator animator = mOpenCloseAnimation.getAnimationPlayer();
@@ -677,31 +672,27 @@ public class WidgetsFullSheet extends BaseWidgetSheet
}
/** Shows the {@link WidgetsFullSheet} on the launcher. */
- public static WidgetsFullSheet show(Launcher launcher, boolean animate) {
- boolean isTwoPane = LARGE_SCREEN_WIDGET_PICKER.get()
- && launcher.getDeviceProfile().isTablet
- && launcher.getDeviceProfile().isLandscape
- && !launcher.getDeviceProfile().isTwoPanels;
-
- WidgetsFullSheet sheet;
- if (isTwoPane) {
- sheet = (WidgetsTwoPaneSheet) launcher.getLayoutInflater().inflate(
- R.layout.widgets_two_pane_sheet,
- launcher.getDragLayer(),
- false);
- } else {
- sheet = (WidgetsFullSheet) launcher.getLayoutInflater().inflate(
- R.layout.widgets_full_sheet,
- launcher.getDragLayer(),
- false);
- }
-
+ public static WidgetsFullSheet show(BaseActivity activity, boolean animate) {
+ WidgetsFullSheet sheet = (WidgetsFullSheet) activity.getLayoutInflater().inflate(
+ getWidgetSheetId(activity),
+ activity.getDragLayer(),
+ false);
sheet.attachToContainer();
sheet.mIsOpen = true;
sheet.open(animate);
return sheet;
}
+ private static int getWidgetSheetId(BaseActivity activity) {
+ boolean isTwoPane = (activity.getDeviceProfile().isTablet
+ && activity.getDeviceProfile().isLandscape
+ && !activity.getDeviceProfile().isTwoPanels)
+ // Enables two pane picker for unfolded foldables if the flag is on.
+ || (activity.getDeviceProfile().isTwoPanels && enableUnfoldedTwoPanePicker());
+
+ return isTwoPane ? R.layout.widgets_two_pane_sheet : R.layout.widgets_full_sheet;
+ }
+
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return isTouchOnScrollbar(ev) || super.onInterceptTouchEvent(ev);
@@ -749,7 +740,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet
/** Gets the {@link WidgetsRecyclerView} which shows all widgets in {@link WidgetsFullSheet}. */
@VisibleForTesting
- public static WidgetsRecyclerView getWidgetsView(Launcher launcher) {
+ public static WidgetsRecyclerView getWidgetsView(BaseActivity launcher) {
return launcher.findViewById(R.id.primary_widgets_list_view);
}
@@ -792,18 +783,25 @@ public class WidgetsFullSheet extends BaseWidgetSheet
if (mIsInSearchMode) {
mSearchBar.reset();
}
+ }
- // Checks the orientation of the screen
- if (mOrientation != newConfig.orientation) {
- mOrientation = newConfig.orientation;
- if (LARGE_SCREEN_WIDGET_PICKER.get()
- && mDeviceProfile.isTablet && !mDeviceProfile.isTwoPanels) {
- handleClose(false);
- show(Launcher.getLauncher(getContext()), false);
- } else {
- reset();
- }
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ if (mDeviceProfile.isLandscape != dp.isLandscape && dp.isTablet && !dp.isTwoPanels) {
+ handleClose(false);
+ show(BaseActivity.fromContext(getContext()), false);
+ } else {
+ reset();
+ }
+
+ // When folding/unfolding the foldables, we need to switch between the regular widget picker
+ // and the two pane picker, so we rebuild the picker with the correct layout.
+ if (mDeviceProfile.isTwoPanels != dp.isTwoPanels && enableUnfoldedTwoPanePicker()) {
+ handleClose(false);
+ show(BaseActivity.fromContext(getContext()), false);
}
+
+ mDeviceProfile = dp;
}
@Override
@@ -819,7 +817,10 @@ public class WidgetsFullSheet extends BaseWidgetSheet
@Override
public void onDragStart(boolean start, float startDisplacement) {
super.onDragStart(start, startDisplacement);
- getWindowInsetsController().hide(WindowInsets.Type.ime());
+ WindowInsetsController insetsController = getWindowInsetsController();
+ if (insetsController != null) {
+ insetsController.hide(WindowInsets.Type.ime());
+ }
}
@Nullable private View getViewToShowEducationTip() {
@@ -850,15 +851,13 @@ public class WidgetsFullSheet extends BaseWidgetSheet
/** Shows education dialog for widgets. */
private WidgetsEduView showEducationDialog() {
- mActivityContext.getSharedPrefs().edit()
- .putBoolean(KEY_WIDGETS_EDUCATION_DIALOG_SEEN, true).apply();
+ LauncherPrefs.get(getContext()).put(WIDGETS_EDUCATION_DIALOG_SEEN, true);
return WidgetsEduView.showEducationDialog(mActivityContext);
}
/** Returns {@code true} if education dialog has previously been shown. */
protected boolean hasSeenEducationDialog() {
- return mActivityContext.getSharedPrefs()
- .getBoolean(KEY_WIDGETS_EDUCATION_DIALOG_SEEN, false)
+ return LauncherPrefs.get(getContext()).get(WIDGETS_EDUCATION_DIALOG_SEEN)
|| Utilities.isRunningInTestHarness();
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
index d85737b28f..c3ab08c153 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget.picker;
+import static com.android.launcher3.Flags.enableUnfoldedTwoPanePicker;
+
import android.content.Context;
import android.graphics.Outline;
import android.os.Process;
@@ -23,12 +25,15 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewOutlineProvider;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import androidx.annotation.NonNull;
+import androidx.annotation.Px;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.recyclerview.ViewHolderBinder;
import com.android.launcher3.util.PackageUserKey;
@@ -46,6 +51,8 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
private static final int PERSONAL_TAB = 0;
private static final int WORK_TAB = 1;
+ private static final int MINIMUM_WIDTH_LEFT_PANE_FOLDABLE_DP = 268;
+ private static final int MAXIMUM_WIDTH_LEFT_PANE_FOLDABLE_DP = 395;
private static final String SUGGESTIONS_PACKAGE_NAME = "widgets_list_suggestions_entry";
private LinearLayout mSuggestedWidgetsContainer;
@@ -117,6 +124,29 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
}
@Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (changed && mDeviceProfile.isTwoPanels && enableUnfoldedTwoPanePicker()) {
+ LinearLayout layout = mContent.findViewById(R.id.linear_layout_container);
+ FrameLayout leftPane = layout.findViewById(R.id.recycler_view_container);
+ LinearLayout.LayoutParams layoutParams = (LayoutParams) leftPane.getLayoutParams();
+ // Width is 1/3 of the sheet unless it's less than min width or max width
+ int leftPaneWidth = layout.getMeasuredWidth() / 3;
+ @Px int minLeftPaneWidthPx = Utilities.dpToPx(MINIMUM_WIDTH_LEFT_PANE_FOLDABLE_DP);
+ @Px int maxLeftPaneWidthPx = Utilities.dpToPx(MAXIMUM_WIDTH_LEFT_PANE_FOLDABLE_DP);
+ if (leftPaneWidth < minLeftPaneWidthPx) {
+ layoutParams.width = minLeftPaneWidthPx;
+ } else if (leftPaneWidth > maxLeftPaneWidthPx) {
+ layoutParams.width = maxLeftPaneWidthPx;
+ } else {
+ layoutParams.width = 0;
+ }
+ layoutParams.weight = layoutParams.width == 0 ? 0.33F : 0;
+ leftPane.setLayoutParams(layoutParams);
+ }
+ }
+
+ @Override
public void onRecommendedWidgetsBound() {
super.onRecommendedWidgetsBound();