Merge "Rebind recycler views if launcher activity restarted" into sc-dev
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
index cc5e1cb..f8448da 100644
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -24,6 +24,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
+import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
@@ -81,4 +82,9 @@
ComponentName providerName) {
return null;
}
+
+ /** Returns {@link PackageItemInfo} of a pending widget. */
+ public static PackageItemInfo newPendingItemInfo(ComponentName provider) {
+ return new PackageItemInfo(provider.getPackageName());
+ }
}
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index ae7e477..310e178 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -982,10 +982,13 @@
depthController.setSurface(dimLayer);
backgroundRadiusAnim.addListener(new AnimatorListenerAdapter() {
@Override
+ public void onAnimationStart(Animator animation) {
+ depthController.setIsInLaunchTransition(true);
+ }
+
+ @Override
public void onAnimationEnd(Animator animation) {
- // Reset depth at the end of the launch animation, so the wallpaper won't be
- // zoomed out if an app crashes.
- DEPTH.setValue(depthController, 0f);
+ depthController.setIsInLaunchTransition(false);
depthController.setSurface(null);
if (dimLayer != null) {
new SurfaceControl.Transaction()
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 4503e30..bb8b62d 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -24,6 +24,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.os.IBinder;
+import android.os.SystemProperties;
import android.util.FloatProperty;
import android.view.CrossWindowBlurListeners;
import android.view.SurfaceControl;
@@ -117,6 +118,10 @@
* @see android.service.wallpaper.WallpaperService.Engine#onZoomChanged(float)
*/
private float mDepth;
+ /**
+ * If we're launching and app and should not be blurring the screen for performance reasons.
+ */
+ private boolean mBlurDisabledForAppLaunch;
// Workaround for animating the depth when multiwindow mode changes.
private boolean mIgnoreStateChangesDuringMultiWindowAnimation = false;
@@ -211,6 +216,19 @@
}
}
+ /**
+ * If we're launching an app from the home screen.
+ */
+ public void setIsInLaunchTransition(boolean inLaunchTransition) {
+ boolean blurEnabled = SystemProperties.getBoolean("ro.launcher.blur.appLaunch", true);
+ mBlurDisabledForAppLaunch = inLaunchTransition && !blurEnabled;
+ if (!inLaunchTransition) {
+ // Reset depth at the end of the launch animation, so the wallpaper won't be
+ // zoomed out if an app crashes.
+ setDepth(0f);
+ }
+ }
+
private void setDepth(float depth) {
depth = Utilities.boundToRange(depth, 0, 1);
// Round out the depth to dedupe frequent, non-perceptable updates
@@ -238,7 +256,7 @@
boolean opaque = mLauncher.getScrimView().isFullyOpaque() && !isOverview;
int blur = opaque || isOverview || !mCrossWindowBlursEnabled
- ? 0 : (int) (mDepth * mMaxBlurRadius);
+ || mBlurDisabledForAppLaunch ? 0 : (int) (mDepth * mMaxBlurRadius);
new SurfaceControl.Transaction()
.setBackgroundBlurRadius(mSurface, blur)
.setOpaque(mSurface, opaque)
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 01c9e76..fe5a347 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.graphics.Color;
-import android.os.SystemProperties;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -85,8 +84,7 @@
@Override
protected float getDepthUnchecked(Context context) {
- //TODO revert when b/178661709 is fixed
- return SystemProperties.getBoolean("ro.launcher.depth.appLaunch", true) ? 1 : 0;
+ return 1;
}
@Override
diff --git a/res/drawable/full_rounded_transparent_ripple.xml b/res/drawable/full_rounded_transparent_ripple.xml
new file mode 100644
index 0000000..a1e7943
--- /dev/null
+++ b/res/drawable/full_rounded_transparent_ripple.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <shape android:shape="oval">
+ <size android:height="24dp" android:width="24dp"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+</ripple>
\ No newline at end of file
diff --git a/res/layout/widgets_search_bar.xml b/res/layout/widgets_search_bar.xml
index 0b354e8..cb27f4f 100644
--- a/res/layout/widgets_search_bar.xml
+++ b/res/layout/widgets_search_bar.xml
@@ -31,11 +31,9 @@
android:id="@+id/widgets_search_cancel_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:paddingVertical="12dp"
- android:paddingStart="8dp"
- android:paddingEnd="12dp"
+ android:padding="12dp"
android:src="@drawable/ic_gm_close_24"
- android:background="?android:selectableItemBackground"
+ android:background="@drawable/full_rounded_transparent_ripple"
android:layout_gravity="center"
android:contentDescription="@string/widgets_full_sheet_cancel_button_description"
android:visibility="gone"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4f4a389..ddd838d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -55,6 +55,9 @@
<string name="widget_dims_format">%1$d \u00d7 %2$d</string>
<!-- Accessibility spoken message format for the dimensions of a widget in the drawer -->
<string name="widget_accessible_dims_format">%1$d wide by %2$d high</string>
+ <!-- Spoken text for a screen reader. The placeholder text is the widget name.
+ [CHAR_LIMIT=none]-->
+ <string name="widget_preview_context_description"><xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget</string>
<!-- Message to tell the user to press and hold a widget/icon to add it to the home screen.
[CHAR LIMIT=NONE] -->
<string name="add_item_request_drag_hint">Touch & hold the widget to move it around the Home screen</string>
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 1c99dfc..256999c 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -116,6 +116,14 @@
launcher:canBeDefault="true" />
<display-option
+ launcher:name="Large Phone Split Display"
+ launcher:minWidthDps="406"
+ launcher:minHeightDps="694"
+ launcher:iconImageSize="56"
+ launcher:iconTextSize="14.4"
+ launcher:canBeDefault="split_display" />
+
+ <display-option
launcher:name="Shorter Stubby"
launcher:minWidthDps="255"
launcher:minHeightDps="400"
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 9e21e1a..ee71146 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -108,7 +108,8 @@
private boolean mTopBorderActive;
private boolean mBottomBorderActive;
- private int mResizeMode;
+ private boolean mHorizontalResizeActive;
+ private boolean mVerticalResizeActive;
private int mRunningHInc;
private int mRunningVInc;
@@ -207,7 +208,6 @@
mWidgetView.addOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo)
widgetView.getAppWidgetInfo();
- mResizeMode = info.resizeMode;
mDragLayer = dragLayer;
mMinHSpan = info.minSpanX;
@@ -218,10 +218,17 @@
mWidgetPadding = getDefaultPaddingForWidget(getContext(),
widgetView.getAppWidgetInfo().provider, null);
- if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
+ // Only show resize handles for the directions in which resizing is possible.
+ InvariantDeviceProfile idp = LauncherAppState.getIDP(cellLayout.getContext());
+ mVerticalResizeActive = (info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0
+ && mMinVSpan < idp.numRows && mMaxVSpan > 1;
+ if (!mVerticalResizeActive) {
mDragHandles[INDEX_TOP].setVisibility(GONE);
mDragHandles[INDEX_BOTTOM].setVisibility(GONE);
- } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
+ }
+ mHorizontalResizeActive = (info.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0
+ && mMinHSpan < idp.numColumns && mMaxHSpan > 1;
+ if (!mHorizontalResizeActive) {
mDragHandles[INDEX_LEFT].setVisibility(GONE);
mDragHandles[INDEX_RIGHT].setVisibility(GONE);
}
@@ -255,6 +262,14 @@
}
}
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams();
+ ItemInfo widgetInfo = (ItemInfo) mWidgetView.getTag();
+ lp.cellX = lp.tmpCellX = widgetInfo.cellX;
+ lp.cellY = lp.tmpCellY = widgetInfo.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.
@@ -263,21 +278,19 @@
mLauncher.getStatsLogManager()
.logger()
.withInstanceId(logInstanceId)
- .withItemInfo((ItemInfo) mWidgetView.getTag())
+ .withItemInfo(widgetInfo)
.log(LAUNCHER_WIDGET_RESIZE_STARTED);
setOnKeyListener(this);
}
public boolean beginResizeIfPointInRegion(int x, int y) {
- boolean horizontalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0;
- boolean verticalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0;
-
- mLeftBorderActive = (x < mTouchTargetWidth) && horizontalActive;
- mRightBorderActive = (x > getWidth() - mTouchTargetWidth) && horizontalActive;
- mTopBorderActive = (y < mTouchTargetWidth + mTopTouchRegionAdjustment) && verticalActive;
+ mLeftBorderActive = (x < mTouchTargetWidth) && mHorizontalResizeActive;
+ mRightBorderActive = (x > getWidth() - mTouchTargetWidth) && mHorizontalResizeActive;
+ mTopBorderActive = (y < mTouchTargetWidth + mTopTouchRegionAdjustment)
+ && mVerticalResizeActive;
mBottomBorderActive = (y > getHeight() - mTouchTargetWidth + mBottomTouchRegionAdjustment)
- && verticalActive;
+ && mVerticalResizeActive;
boolean anyBordersActive = mLeftBorderActive || mRightBorderActive
|| mTopBorderActive || mBottomBorderActive;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1cfe7e0..0da16b7 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1347,6 +1347,40 @@
prepareAppWidget(hostView, launcherInfo);
mWorkspace.addInScreen(hostView, launcherInfo);
announceForAccessibility(R.string.item_added_to_workspace);
+
+ // Show the widget resize frame.
+ if (hostView instanceof LauncherAppWidgetHostView) {
+ final LauncherAppWidgetHostView launcherHostView = (LauncherAppWidgetHostView) hostView;
+ CellLayout cellLayout = getCellLayout(launcherInfo.container, launcherInfo.screenId);
+ if (mStateManager.getState() == NORMAL) {
+ // Show resize frame once the widget layout is drawn.
+ View.OnLayoutChangeListener onLayoutChangeListener =
+ new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View view, int left, int top, int right,
+ int bottom, int oldLeft, int oldTop, int oldRight,
+ int oldBottom) {
+ AppWidgetResizeFrame.showForWidget(launcherHostView, cellLayout);
+ launcherHostView.removeOnLayoutChangeListener(this);
+ }
+ };
+ launcherHostView.addOnLayoutChangeListener(onLayoutChangeListener);
+ // There is a small chance that the layout was already drawn before the layout
+ // change listener was registered, which means that the resize frame wouldn't be
+ // shown. Directly call requestLayout to force a layout change.
+ launcherHostView.requestLayout();
+ } else {
+ mStateManager.addStateListener(new StateManager.StateListener<LauncherState>() {
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {
+ if (mPrevLauncherState == SPRING_LOADED && finalState == NORMAL) {
+ AppWidgetResizeFrame.showForWidget(launcherHostView, cellLayout);
+ mStateManager.removeStateListener(this);
+ }
+ }
+ });
+ }
+ }
}
private void prepareAppWidget(AppWidgetHostView hostView, LauncherAppWidgetInfo item) {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 318496a..ad2d7c2 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -75,7 +75,6 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.PackageInstallInfo;
@@ -791,8 +790,8 @@
if (appWidgetInfo.restoreStatus !=
LauncherAppWidgetInfo.RESTORE_COMPLETED) {
- String pkg = appWidgetInfo.providerName.getPackageName();
- appWidgetInfo.pendingItemInfo = new PackageItemInfo(pkg);
+ appWidgetInfo.pendingItemInfo = WidgetsModel.newPendingItemInfo(
+ appWidgetInfo.providerName);
appWidgetInfo.pendingItemInfo.user = appWidgetInfo.user;
mIconCache.getTitleAndIconForApp(
appWidgetInfo.pendingItemInfo, false);
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index b7fe348..a534ee3 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -511,8 +511,8 @@
mArrowOffsetHorizontal, -mArrowOffsetVertical,
!mIsAboveIcon, mIsLeftAligned,
mArrowColor));
- // TODO: Remove elevation when arrow is above as it casts a shadow on the container
- mArrow.setElevation(mIsAboveIcon ? mElevation : 0);
+ setElevation(mElevation);
+ mArrow.setElevation(mElevation);
}
}
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java
index c395d6c..40bc9c3 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.java
+++ b/src/com/android/launcher3/util/OnboardingPrefs.java
@@ -36,7 +36,7 @@
public static final String HOME_BOUNCE_COUNT = "launcher.home_bounce_count";
public static final String HOTSEAT_DISCOVERY_TIP_COUNT = "launcher.hotseat_discovery_tip_count";
public static final String HOTSEAT_LONGPRESS_TIP_SEEN = "launcher.hotseat_longpress_tip_seen";
- public static final String SEARCH_EDU_SEEN = "launcher.search_edu";
+ public static final String SEARCH_EDU_SEEN = "launcher.search_edu_seen";
public static final String SEARCH_SNACKBAR_COUNT = "launcher.keyboard_snackbar_count";
/**
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index fb1485b..1eb79ad 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -97,8 +97,10 @@
private void updateSysUiColors() {
// Use a light system UI (dark icons) if all apps is behind at least half of the
// status bar.
- boolean forceChange =
- getVisibility() == VISIBLE && getAlpha() > STATUS_BAR_COLOR_FORCE_UPDATE_THRESHOLD;
+ final float threshold = STATUS_BAR_COLOR_FORCE_UPDATE_THRESHOLD;
+ boolean forceChange = getVisibility() == VISIBLE
+ && getAlpha() > threshold
+ && (Color.alpha(mBackgroundColor) / 255f) > threshold;
if (forceChange) {
getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, !isScrimDark());
} else {
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 3bf993e..9f0b9d9 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -24,11 +24,14 @@
import android.view.View.OnLongClickListener;
import android.widget.Toast;
+import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
+import com.android.launcher3.DeviceProfile;
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.R;
import com.android.launcher3.Utilities;
@@ -47,10 +50,11 @@
*/
public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
implements OnClickListener, OnLongClickListener, DragSource,
- PopupDataProvider.PopupDataChangeListener {
+ PopupDataProvider.PopupDataChangeListener, Insettable {
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;
@@ -105,6 +109,35 @@
return true;
}
+ @Override
+ public void setInsets(Rect insets) {
+ mInsets.set(insets);
+ }
+
+
+ /**
+ * Measures the dimension of this view and its children by taking system insets, navigation bar,
+ * status bar, into account.
+ */
+ @GuardedBy("MainThread")
+ protected void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
+ int widthUsed;
+ if (mInsets.bottom > 0) {
+ widthUsed = mInsets.left + mInsets.right;
+ } else {
+ Rect padding = deviceProfile.workspacePadding;
+ widthUsed = Math.max(padding.left + padding.right,
+ 2 * (mInsets.left + mInsets.right));
+ }
+
+ int heightUsed = mInsets.top + deviceProfile.edgeMarginPx;
+ measureChildWithMargins(mContent, widthMeasureSpec,
+ widthUsed, heightMeasureSpec, heightUsed);
+ setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
+ MeasureSpec.getSize(heightMeasureSpec));
+ }
+
private boolean beginDraggingWidget(WidgetCell v) {
// Get the widget preview as the drag representation
WidgetImageView image = v.getWidgetView();
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 47a8914..47f30be 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -17,6 +17,7 @@
package com.android.launcher3.widget;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
+import static com.android.launcher3.model.data.PackageItemInfo.CONVERSATIONS;
import android.content.Context;
import android.graphics.Canvas;
@@ -35,6 +36,8 @@
import android.view.View.OnClickListener;
import android.widget.RemoteViews;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.icons.FastBitmapDrawable;
@@ -146,21 +149,32 @@
mCenterDrawable = null;
}
if (info.bitmap.icon != null) {
+ Drawable widgetCategoryIcon = getWidgetCategoryIcon();
// The view displays three modes,
// 1) App icon in the center
// 2) Preload icon in the center
// 3) App icon in the center with a setup icon on the top left corner.
if (mDisabledForSafeMode) {
- FastBitmapDrawable disabledIcon = info.newIcon(getContext());
- disabledIcon.setIsDisabled(true);
- mCenterDrawable = disabledIcon;
+ if (widgetCategoryIcon == null) {
+ FastBitmapDrawable disabledIcon = info.newIcon(getContext());
+ disabledIcon.setIsDisabled(true);
+ mCenterDrawable = disabledIcon;
+ } else {
+ widgetCategoryIcon.setColorFilter(
+ FastBitmapDrawable.getDisabledFColorFilter(/* disabledAlpha= */ 1f));
+ mCenterDrawable = widgetCategoryIcon;
+ }
mSettingIconDrawable = null;
} else if (isReadyForClickSetup()) {
- mCenterDrawable = info.newIcon(getContext());
+ mCenterDrawable = widgetCategoryIcon == null
+ ? info.newIcon(getContext())
+ : widgetCategoryIcon;
mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate();
updateSettingColor(info.bitmap.color);
} else {
- mCenterDrawable = newPendingIcon(getContext(), info);
+ mCenterDrawable = widgetCategoryIcon == null
+ ? newPendingIcon(getContext(), info)
+ : widgetCategoryIcon;
mSettingIconDrawable = null;
applyState();
}
@@ -316,4 +330,19 @@
}
}
+
+ /**
+ * Returns the widget category icon for {@link #mInfo}.
+ *
+ * <p>If {@link #mInfo}'s category is {@code PackageItemInfo#NO_CATEGORY} or unknown, returns
+ * {@code null}.
+ */
+ @Nullable
+ private Drawable getWidgetCategoryIcon() {
+ switch (mInfo.pendingItemInfo.category) {
+ case CONVERSATIONS:
+ return getContext().getDrawable(R.drawable.ic_conversations_widget_category);
+ }
+ return null;
+ }
}
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 91529be..a52adf6 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -180,14 +180,17 @@
public void applyFromCellItem(WidgetItem item, WidgetPreviewLoader loader) {
applyPreviewOnAppWidgetHostView(item);
+ Context context = getContext();
mItem = item;
mWidgetName.setText(mItem.label);
- mWidgetDims.setText(getContext().getString(R.string.widget_dims_format,
+ mWidgetName.setContentDescription(
+ context.getString(R.string.widget_preview_context_description, mItem.label));
+ mWidgetDims.setText(context.getString(R.string.widget_dims_format,
mItem.spanX, mItem.spanY));
- mWidgetDims.setContentDescription(getContext().getString(
+ mWidgetDims.setContentDescription(context.getString(
R.string.widget_accessible_dims_format, mItem.spanX, mItem.spanY));
if (ATLEAST_S && mItem.widgetInfo != null) {
- CharSequence description = mItem.widgetInfo.loadDescription(getContext());
+ CharSequence description = mItem.widgetInfo.loadDescription(context);
if (description != null && description.length() > 0) {
mWidgetDescription.setText(description);
mWidgetDescription.setVisibility(VISIBLE);
@@ -238,6 +241,7 @@
NavigableAppWidgetHostView appWidgetHostViewPreview,
LauncherAppWidgetProviderInfo providerInfo,
@Nullable RemoteViews remoteViews) {
+ appWidgetHostViewPreview.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
appWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1, providerInfo);
Rect padding;
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 37b950d..d7928c7 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -23,7 +23,6 @@
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.IntProperty;
-import android.util.Log;
import android.util.Pair;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -36,10 +35,7 @@
import android.widget.TableRow;
import android.widget.TextView;
-import androidx.annotation.GuardedBy;
-
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Insettable;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
@@ -53,7 +49,7 @@
/**
* Bottom sheet for the "Widgets" system shortcut in the long-press popup.
*/
-public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
+public class WidgetsBottomSheet extends BaseWidgetSheet {
private static final String TAG = "WidgetsBottomSheet";
private static final IntProperty<View> PADDING_BOTTOM =
@@ -74,7 +70,6 @@
private static final long EDUCATION_TIP_DELAY_MS = 300;
private ItemInfo mOriginalItemInfo;
- private final Rect mInsets;
private final int mMaxTableHeight;
private int mMaxHorizontalSpan = 4;
@@ -114,7 +109,6 @@
public WidgetsBottomSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
- mInsets = new Rect();
DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
// Set the max table height to 2 / 3 of the grid height so that the bottom picker won't
// take over the entire view vertically.
@@ -132,53 +126,20 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (doMeasure(widthMeasureSpec, heightMeasureSpec)) {
- boolean hasUpdated = doMeasure(widthMeasureSpec, heightMeasureSpec);
- if (hasUpdated) {
- Log.w(TAG, "WidgetsBottomSheet dimension has been updated after a 2nd"
- + " measurement.");
- }
+ doMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (updateMaxSpansPerRow()) {
+ doMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
- /**
- * Measures the dimension of this view and its children.
- *
- * <p>This function takes account of the following during measurement:
- * <ol>
- * <li>status bar and system navigation bar insets</li>
- * <li>
- * number of spans that can fit in a row. This affects the number of widgets that can
- * fit in a row.
- * </li>
- * </ol>
- *
- * @return {@code true} if the width or height of this view or its children have changed after
- * the measurement. Otherwise, returns {@code false}.
- */
- @GuardedBy("MainThread")
- private boolean doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
- int widthUsed;
- if (mInsets.bottom > 0) {
- widthUsed = mInsets.left + mInsets.right;
- } else {
- Rect padding = deviceProfile.workspacePadding;
- widthUsed = Math.max(padding.left + padding.right,
- 2 * (mInsets.left + mInsets.right));
- }
-
- int heightUsed = mInsets.top + deviceProfile.edgeMarginPx;
- measureChildWithMargins(mContent, widthMeasureSpec,
- widthUsed, heightMeasureSpec, heightUsed);
- setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
- MeasureSpec.getSize(heightMeasureSpec));
+ /** Returns {@code true} if the max spans have been updated. */
+ private boolean updateMaxSpansPerRow() {
+ if (getMeasuredWidth() == 0) return false;
int paddingPx = 2 * getResources().getDimensionPixelOffset(
R.dimen.widget_cell_horizontal_padding);
int maxHorizontalSpan = findViewById(R.id.widgets_table).getMeasuredWidth()
/ (mActivityContext.getDeviceProfile().cellWidthPx + paddingPx);
-
if (mMaxHorizontalSpan != maxHorizontalSpan) {
// Ensure the table layout is showing widgets in the right column after measure.
mMaxHorizontalSpan = maxHorizontalSpan;
@@ -297,7 +258,8 @@
@Override
public void setInsets(Rect insets) {
- mInsets.set(insets);
+ super.setInsets(insets);
+
mContent.setPadding(mContent.getPaddingStart(),
mContent.getPaddingTop(), mContent.getPaddingEnd(), insets.bottom);
if (insets.bottom > 0) {
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 0106ef5..6c2cca6 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -45,8 +45,6 @@
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
@@ -76,7 +74,7 @@
* Popup for showing the full list of available widgets
*/
public class WidgetsFullSheet extends BaseWidgetSheet
- implements Insettable, ProviderChangedListener, OnActivePageChangedListener,
+ implements ProviderChangedListener, OnActivePageChangedListener,
WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener {
private static final String TAG = WidgetsFullSheet.class.getSimpleName();
@@ -131,6 +129,22 @@
}
};
+ private final OnAttachStateChangeListener mBindScrollbarInSearchMode =
+ new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View view) {
+ WidgetsRecyclerView searchRecyclerView =
+ mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView;
+ if (mIsInSearchMode && searchRecyclerView != null) {
+ searchRecyclerView.bindFastScrollbar();
+ }
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View view) {
+ }
+ };
+
private final int mTabsHeight;
private final int mViewPagerTopPadding;
private final int mSearchAndRecommendationContainerBottomMargin;
@@ -305,11 +319,17 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mActivityContext.getAppWidgetHost().removeProviderChangeListener(this);
+ mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView
+ .removeOnAttachStateChangeListener(mBindScrollbarInSearchMode);
+ if (mHasWorkProfile) {
+ mAdapters.get(AdapterHolder.WORK).mWidgetsRecyclerView
+ .removeOnAttachStateChangeListener(mBindScrollbarInSearchMode);
+ }
}
@Override
public void setInsets(Rect insets) {
- mInsets.set(insets);
+ super.setInsets(insets);
setBottomPadding(mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView, insets.bottom);
setBottomPadding(mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView, insets.bottom);
@@ -351,24 +371,6 @@
}
}
- private void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
- int widthUsed;
- if (mInsets.bottom > 0) {
- widthUsed = mInsets.left + mInsets.right;
- } else {
- Rect padding = deviceProfile.workspacePadding;
- widthUsed = Math.max(padding.left + padding.right,
- 2 * (mInsets.left + mInsets.right));
- }
-
- int heightUsed = mInsets.top + deviceProfile.edgeMarginPx;
- measureChildWithMargins(mContent, widthMeasureSpec,
- widthUsed, heightMeasureSpec, heightUsed);
- setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
- MeasureSpec.getSize(heightMeasureSpec));
- }
-
/** Returns {@code true} if the max spans have been updated. */
private boolean updateMaxSpansPerRow() {
if (getMeasuredWidth() == 0) return false;
@@ -772,6 +774,12 @@
mWidgetsRecyclerView.setHeaderViewDimensionsProvider(WidgetsFullSheet.this);
mWidgetsRecyclerView.setEdgeEffectFactory(
((TopRoundedCornerView) mContent).createEdgeEffectFactory());
+ // Recycler view binds to fast scroller when it is attached to screen. Make sure
+ // search recycler view is bound to fast scroller if user is in search mode at the time
+ // of attachment.
+ if (mAdapterType == PRIMARY || mAdapterType == WORK) {
+ mWidgetsRecyclerView.addOnAttachStateChangeListener(mBindScrollbarInSearchMode);
+ }
mWidgetsListAdapter.setApplyBitmapDeferred(false, mWidgetsRecyclerView);
mWidgetsListAdapter.setMaxHorizontalSpansPerRow(mMaxSpansPerRow);
}
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index a66b031..631067b 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -225,6 +225,14 @@
return null;
}
+ /** Returns {@link PackageItemInfo} of a pending widget. */
+ public static PackageItemInfo newPendingItemInfo(ComponentName provider) {
+ if (CONVERSATION_WIDGET.equals(provider)) {
+ return new PackageItemInfo(provider.getPackageName(), PackageItemInfo.CONVERSATIONS);
+ }
+ return new PackageItemInfo(provider.getPackageName());
+ }
+
private WidgetPackageOrCategoryKey getWidgetPackageOrCategoryKey(WidgetItem item) {
if (CONVERSATION_WIDGET.equals(item.componentName)) {
return new WidgetPackageOrCategoryKey(PackageItemInfo.CONVERSATIONS, item.user);
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index b421b0e..0c9c463 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -102,6 +102,8 @@
setResult(acceptConfig);
if (acceptConfig) {
+ // Dismiss widget resize frame.
+ mDevice.pressHome();
Wait.atMost("", new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
} else {
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 714b11b..dad4f2b 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -58,6 +58,8 @@
openAllWidgets().
getWidget(widgetInfo.getLabel(mTargetContext.getPackageManager())).
dragToWorkspace(false, false);
+ // Dismiss widget resize frame.
+ mDevice.pressHome();
assertTrue(mActivityMonitor.itemExists(
(info, view) -> info instanceof LauncherAppWidgetInfo &&