Merge "Fix drop target icons being truncated." into sc-dev
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 1bf3627..33dc6cf 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -422,8 +422,8 @@
@Override
public Stream<SystemShortcut.Factory> getSupportedShortcuts() {
- return Stream.concat(super.getSupportedShortcuts(),
- Stream.of(WellbeingModel.SHORTCUT_FACTORY));
+ return Stream.concat(Stream.of(WellbeingModel.SHORTCUT_FACTORY),
+ super.getSupportedShortcuts());
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index f0b02b3..ec9893c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -192,7 +192,7 @@
@Override
public Stream<SystemShortcut.Factory> getSupportedShortcuts() {
return Stream.concat(
- super.getSupportedShortcuts(), Stream.of(mHotseatPredictionController));
+ Stream.of(mHotseatPredictionController), super.getSupportedShortcuts());
}
/**
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index a9dacee..0ebaea2 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -45,8 +45,6 @@
import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
-import static com.android.quickstep.util.SwipePipToHomeAnimator.FRACTION_END;
-import static com.android.quickstep.util.SwipePipToHomeAnimator.FRACTION_START;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
@@ -248,7 +246,6 @@
private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch;
- private static final long SWIPE_PIP_TO_HOME_DURATION = 425;
private SwipePipToHomeAnimator mSwipePipToHomeAnimator;
protected boolean mIsSwipingPipToHome;
@@ -1134,17 +1131,14 @@
createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip,
runningTaskTarget);
mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome() && appCanEnterPip;
+ final RectFSpringAnim windowAnim;
if (mIsSwipingPipToHome) {
- mSwipePipToHomeAnimator = getSwipePipToHomeAnimator(
+ mSwipePipToHomeAnimator = createWindowAnimationToPip(
homeAnimFactory, runningTaskTarget, start);
- mSwipePipToHomeAnimator.setDuration(SWIPE_PIP_TO_HOME_DURATION);
- mSwipePipToHomeAnimator.setInterpolator(interpolator);
- mSwipePipToHomeAnimator.setFloatValues(FRACTION_START, FRACTION_END);
- mSwipePipToHomeAnimator.start();
- mRunningWindowAnim = RunningWindowAnim.wrap(mSwipePipToHomeAnimator);
+ windowAnim = mSwipePipToHomeAnimator;
} else {
mSwipePipToHomeAnimator = null;
- RectFSpringAnim windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
+ windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
windowAnim.addAnimatorListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
@@ -1158,9 +1152,9 @@
mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED);
}
});
- windowAnim.start(mContext, velocityPxPerMs);
- mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim);
}
+ windowAnim.start(mContext, velocityPxPerMs);
+ mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim);
homeAnimFactory.setSwipeVelocity(velocityPxPerMs.y);
homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y);
mLauncherTransitionController = null;
@@ -1216,7 +1210,7 @@
}
}
- private SwipePipToHomeAnimator getSwipePipToHomeAnimator(HomeAnimationFactory homeAnimFactory,
+ private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory,
RemoteAnimationTargetCompat runningTaskTarget, float startProgress) {
// Directly animate the app to PiP (picture-in-picture) mode
final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask();
@@ -1229,16 +1223,15 @@
runningTaskTarget.taskInfo.pictureInPictureParams,
homeRotation,
mDp.hotseatBarSizePx);
- final Rect startBounds = new Rect();
- updateProgressForStartRect(new Matrix(), startProgress).round(startBounds);
final SwipePipToHomeAnimator swipePipToHomeAnimator = new SwipePipToHomeAnimator(
+ mContext,
runningTaskTarget.taskId,
taskInfo.topActivity,
runningTaskTarget.leash.getSurfaceControl(),
TaskInfoCompat.getPipSourceRectHint(
runningTaskTarget.taskInfo.pictureInPictureParams),
TaskInfoCompat.getWindowConfigurationBounds(taskInfo),
- startBounds,
+ updateProgressForStartRect(new Matrix(), startProgress),
destinationBounds,
mRecentsView.getPipCornerRadius(),
mRecentsView);
@@ -1250,7 +1243,7 @@
}
AnimatorPlaybackController activityAnimationToHome =
homeAnimFactory.createActivityAnimationToHome();
- swipePipToHomeAnimator.addListener(new AnimatorListenerAdapter() {
+ swipePipToHomeAnimator.addAnimatorListener(new AnimatorListenerAdapter() {
private boolean mHasAnimationEnded;
@Override
public void onAnimationStart(Animator animation) {
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index 4c10822..7eca360 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -27,8 +27,11 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_SCREEN_SUGGESTIONS_ENABLED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DOT_DISABLED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DOT_ENABLED;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_THEMED_ICON_DISABLED;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_THEMED_ICON_ENABLED;
import static com.android.launcher3.model.QuickstepModelDelegate.LAST_PREDICTION_ENABLED_STATE;
import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
+import static com.android.launcher3.util.Themes.KEY_THEMED_ICONS;
import android.content.Context;
import android.content.SharedPreferences;
@@ -40,6 +43,7 @@
import com.android.launcher3.AutoInstallsLayout;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
@@ -170,6 +174,13 @@
if (gridSizeChangedEvent != null) {
logger.log(gridSizeChangedEvent);
}
+
+ if (FeatureFlags.ENABLE_THEMED_ICONS.get()) {
+ logger.log(prefs.getBoolean(KEY_THEMED_ICONS, false)
+ ? LAUNCHER_THEMED_ICON_ENABLED
+ : LAUNCHER_THEMED_ICON_DISABLED);
+ }
+
mLoggablePrefs.forEach((key, lp) -> logger.log(() ->
prefs.getBoolean(key, lp.defaultValue) ? lp.eventIdOn : lp.eventIdOff));
}
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index 61a2eaf..67a635b 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -20,8 +20,8 @@
import android.animation.Animator;
import android.animation.RectEvaluator;
-import android.animation.ValueAnimator;
import android.content.ComponentName;
+import android.content.Context;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
@@ -44,30 +44,24 @@
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
/**
- * An {@link Animator} that animates an Activity to PiP (picture-in-picture) window when
- * swiping up (in gesture navigation mode). Note that this class is derived from
- * {@link com.android.wm.shell.pip.PipAnimationController.PipTransitionAnimator}.
- *
- * TODO: consider sharing this class including the animator and leash operations between
- * Launcher and SysUI. Also, there should be one source of truth for the corner radius of the
- * PiP window, which would ideally be on SysUI side as well.
+ * Subclass of {@link RectFSpringAnim} that animates an Activity to PiP (picture-in-picture) window
+ * when swiping up (in gesture navigation mode).
*/
-public class SwipePipToHomeAnimator extends ValueAnimator {
+public class SwipePipToHomeAnimator extends RectFSpringAnim {
private static final String TAG = SwipePipToHomeAnimator.class.getSimpleName();
- public static final float FRACTION_START = 0f;
- public static final float FRACTION_END = 1f;
+ private static final float END_PROGRESS = 1.0f;
private final int mTaskId;
private final ComponentName mComponentName;
private final SurfaceControl mLeash;
private final Rect mAppBounds = new Rect();
private final Rect mStartBounds = new Rect();
+ private final Rect mCurrentBounds = new Rect();
private final Rect mDestinationBounds = new Rect();
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
- /** for calculating the transform in {@link #onAnimationUpdate(ValueAnimator)} */
- private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
+ /** for calculating transform in {@link #onAnimationUpdate(AppCloseConfig, RectF, float)} */
private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());
private final Rect mSourceHintRectInsets;
private final Rect mSourceInsets = new Rect();
@@ -90,6 +84,7 @@
private SurfaceControl mContentOverlay;
/**
+ * @param context {@link Context} provides Launcher resources
* @param taskId Task id associated with this animator, see also {@link #getTaskId()}
* @param componentName Component associated with this animator,
* see also {@link #getComponentName()}
@@ -102,20 +97,22 @@
* @param destinationBounds Bounds of the destination this animator ends to
* @param cornerRadius Corner radius in pixel value for PiP window
*/
- public SwipePipToHomeAnimator(int taskId,
+ public SwipePipToHomeAnimator(@NonNull Context context,
+ int taskId,
@NonNull ComponentName componentName,
@NonNull SurfaceControl leash,
@Nullable Rect sourceRectHint,
@NonNull Rect appBounds,
- @NonNull Rect startBounds,
+ @NonNull RectF startBounds,
@NonNull Rect destinationBounds,
int cornerRadius,
@NonNull View view) {
+ super(startBounds, new RectF(destinationBounds), context);
mTaskId = taskId;
mComponentName = componentName;
mLeash = leash;
mAppBounds.set(appBounds);
- mStartBounds.set(startBounds);
+ startBounds.round(mStartBounds);
mDestinationBounds.set(destinationBounds);
mDestinationBoundsTransformed.set(mDestinationBounds);
mDestinationBoundsAnimation.set(mDestinationBounds);
@@ -151,10 +148,10 @@
t.reparent(mContentOverlay, mLeash);
t.apply();
- addUpdateListener(valueAnimator -> {
- float alpha = valueAnimator.getAnimatedFraction() < 0.5f
+ addOnUpdateListener((values, currentRect, progress) -> {
+ float alpha = progress < 0.5f
? 0
- : Utilities.mapToRange(valueAnimator.getAnimatedFraction(), 0.5f, 1f,
+ : Utilities.mapToRange(Math.min(progress, 1f), 0.5f, 1f,
0f, 1f, Interpolators.FAST_OUT_SLOW_IN);
t.setAlpha(mContentOverlay, alpha);
t.apply();
@@ -166,7 +163,7 @@
appBounds.bottom - sourceRectHint.bottom);
}
- addListener(new AnimationSuccessListener() {
+ addAnimatorListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
InteractionJankMonitorWrapper.begin(view, CUJ_APP_CLOSE_TO_PIP);
@@ -191,7 +188,7 @@
mHasAnimationEnded = true;
}
});
- addUpdateListener(this::onAnimationUpdate);
+ addOnUpdateListener(this::onAnimationUpdate);
}
/** sets the from rotation if it's different from the target rotation. */
@@ -219,34 +216,34 @@
mAppBounds.top + mDestinationBounds.height());
}
- private void onAnimationUpdate(ValueAnimator animator) {
+ private void onAnimationUpdate(@Nullable AppCloseConfig values, RectF currentRect,
+ float progress) {
if (mHasAnimationEnded) return;
final SurfaceControl.Transaction tx =
PipSurfaceTransactionHelper.newSurfaceControlTransaction();
- onAnimationUpdate(tx, animator.getAnimatedFraction());
+ onAnimationUpdate(tx, currentRect, progress);
tx.apply();
}
private PictureInPictureSurfaceTransaction onAnimationUpdate(SurfaceControl.Transaction tx,
- float fraction) {
- final Rect bounds = mRectEvaluator.evaluate(fraction, mStartBounds,
- mDestinationBoundsAnimation);
+ RectF currentRect, float progress) {
+ currentRect.round(mCurrentBounds);
final PictureInPictureSurfaceTransaction op;
if (mSourceHintRectInsets == null) {
// no source rect hint been set, directly scale the window down
- op = onAnimationScale(fraction, tx, bounds);
+ op = onAnimationScale(progress, tx, mCurrentBounds);
} else {
// scale and crop according to the source rect hint
- op = onAnimationScaleAndCrop(fraction, tx, bounds);
+ op = onAnimationScaleAndCrop(progress, tx, mCurrentBounds);
}
return op;
}
/** scale the window directly with no source rect hint being set */
private PictureInPictureSurfaceTransaction onAnimationScale(
- float fraction, SurfaceControl.Transaction tx, Rect bounds) {
+ float progress, SurfaceControl.Transaction tx, Rect bounds) {
if (mFromRotation == Surface.ROTATION_90 || mFromRotation == Surface.ROTATION_270) {
- final RotatedPosition rotatedPosition = getRotatedPosition(fraction);
+ final RotatedPosition rotatedPosition = getRotatedPosition(progress);
return mSurfaceTransactionHelper.scale(tx, mLeash, mAppBounds, bounds,
rotatedPosition.degree, rotatedPosition.positionX, rotatedPosition.positionY);
} else {
@@ -256,12 +253,12 @@
/** scale and crop the window with source rect hint */
private PictureInPictureSurfaceTransaction onAnimationScaleAndCrop(
- float fraction, SurfaceControl.Transaction tx,
+ float progress, SurfaceControl.Transaction tx,
Rect bounds) {
- final Rect insets = mInsetsEvaluator.evaluate(fraction, mSourceInsets,
+ final Rect insets = mInsetsEvaluator.evaluate(progress, mSourceInsets,
mSourceHintRectInsets);
if (mFromRotation == Surface.ROTATION_90 || mFromRotation == Surface.ROTATION_270) {
- final RotatedPosition rotatedPosition = getRotatedPosition(fraction);
+ final RotatedPosition rotatedPosition = getRotatedPosition(progress);
return mSurfaceTransactionHelper.scaleAndRotate(tx, mLeash, mAppBounds, bounds, insets,
rotatedPosition.degree, rotatedPosition.positionX, rotatedPosition.positionY);
} else {
@@ -291,22 +288,22 @@
// get the final leash operations but do not apply to the leash.
final SurfaceControl.Transaction tx =
PipSurfaceTransactionHelper.newSurfaceControlTransaction();
- return onAnimationUpdate(tx, FRACTION_END);
+ return onAnimationUpdate(tx, new RectF(mDestinationBounds), END_PROGRESS);
}
- private RotatedPosition getRotatedPosition(float fraction) {
+ private RotatedPosition getRotatedPosition(float progress) {
final float degree, positionX, positionY;
if (mFromRotation == Surface.ROTATION_90) {
- degree = -90 * fraction;
- positionX = fraction * (mDestinationBoundsTransformed.left - mStartBounds.left)
+ degree = -90 * progress;
+ positionX = progress * (mDestinationBoundsTransformed.left - mStartBounds.left)
+ mStartBounds.left;
- positionY = fraction * (mDestinationBoundsTransformed.bottom - mStartBounds.top)
+ positionY = progress * (mDestinationBoundsTransformed.bottom - mStartBounds.top)
+ mStartBounds.top;
} else {
- degree = 90 * fraction;
- positionX = fraction * (mDestinationBoundsTransformed.right - mStartBounds.left)
+ degree = 90 * progress;
+ positionX = progress * (mDestinationBoundsTransformed.right - mStartBounds.left)
+ mStartBounds.left;
- positionY = fraction * (mDestinationBoundsTransformed.top - mStartBounds.top)
+ positionY = progress * (mDestinationBoundsTransformed.top - mStartBounds.top)
+ mStartBounds.top;
}
return new RotatedPosition(degree, positionX, positionY);
diff --git a/res/drawable/ic_drag_handle.xml b/res/drawable/ic_drag_handle.xml
index 0181ff1..9db75f4 100644
--- a/res/drawable/ic_drag_handle.xml
+++ b/res/drawable/ic_drag_handle.xml
@@ -19,7 +19,7 @@
android:height="@dimen/deep_shortcut_drag_handle_size"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
- android:tint="?android:attr/textColorHint" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:pathData="M20,9H4v2h16V9z M4,15h16v-2H4V15z"
diff --git a/res/layout/system_shortcut.xml b/res/layout/system_shortcut.xml
index 6337fae..2cdf1f4 100644
--- a/res/layout/system_shortcut.xml
+++ b/res/layout/system_shortcut.xml
@@ -45,6 +45,6 @@
android:layout_height="@dimen/system_shortcut_icon_size"
android:layout_marginStart="@dimen/system_shortcut_margin_start"
android:layout_gravity="start|center_vertical"
- android:backgroundTint="?android:attr/textColorTertiary"/>
+ android:backgroundTint="?android:attr/textColorPrimary"/>
</com.android.launcher3.shortcuts.DeepShortcutView>
diff --git a/res/layout/widget_shortcut_container.xml b/res/layout/widget_shortcut_container.xml
new file mode 100644
index 0000000..a4d8eb4
--- /dev/null
+++ b/res/layout/widget_shortcut_container.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/system_shortcut_full"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/system_shortcut_header_height"
+ android:orientation="horizontal"
+ android:gravity="end|center_vertical"
+ android:elevation="@dimen/deep_shortcuts_elevation"
+ android:tag="@string/popup_container_iterate_children"
+ android:clipToPadding="true">
+</LinearLayout>
diff --git a/res/layout/widgets_table_container.xml b/res/layout/widgets_table_container.xml
index c6b70aa..4f70a05 100644
--- a/res/layout/widgets_table_container.xml
+++ b/res/layout/widgets_table_container.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<TableLayout
+<com.android.launcher3.widget.picker.WidgetsListTableView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widgets_table"
android:layout_width="match_parent"
diff --git a/res/layout/work_apps_edu.xml b/res/layout/work_apps_edu.xml
index 2c58907..ffbf962 100644
--- a/res/layout/work_apps_edu.xml
+++ b/res/layout/work_apps_edu.xml
@@ -16,30 +16,38 @@
<com.android.launcher3.allapps.WorkEduCard xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="@dimen/work_edu_card_margin"
- android:orientation="vertical"
- android:background="@drawable/work_card"
android:gravity="center">
- <TextView
- style="@style/PrimaryHeadline"
- android:textColor="?android:attr/textColorPrimary"
- android:id="@+id/work_apps_paused_title"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp"
- android:text="@string/work_profile_edu_work_apps"
- android:textAlignment="center"
- android:textSize="20sp" />
+ android:orientation="vertical"
+ android:padding="@dimen/work_edu_card_margin"
+ android:background="@drawable/work_card"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center"
+ android:id="@+id/wrapper">
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/action_btn"
- android:textColor="?attr/workProfileOverlayTextColor"
- android:text="@string/work_profile_edu_accept"
- android:textAlignment="center"
- android:background="@drawable/work_card_btn"
- android:textSize="14sp" />
+ <TextView
+ style="@style/PrimaryHeadline"
+ android:textColor="?android:attr/textColorPrimary"
+ android:id="@+id/work_apps_paused_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:text="@string/work_profile_edu_work_apps"
+ android:textAlignment="center"
+ android:textSize="20sp" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/action_btn"
+ android:textColor="?attr/workProfileOverlayTextColor"
+ android:text="@string/work_profile_edu_accept"
+ android:textAlignment="center"
+ android:background="@drawable/work_card_btn"
+ android:textSize="14sp" />
+ </LinearLayout>
</com.android.launcher3.allapps.WorkEduCard>
\ No newline at end of file
diff --git a/res/layout/work_apps_paused.xml b/res/layout/work_apps_paused.xml
index 7f1107f..14dcb8c 100644
--- a/res/layout/work_apps_paused.xml
+++ b/res/layout/work_apps_paused.xml
@@ -12,11 +12,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.allapps.WorkPausedCard xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?attr/allAppsScrimColor"
- android:padding="48dp"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/work_edu_card_margin"
android:orientation="vertical"
android:gravity="center">
@@ -39,5 +38,16 @@
android:textColor="?attr/workProfileOverlayTextColor"
android:text="@string/work_apps_paused_body"
android:textAlignment="center"
+ android:layout_marginBottom="8dp"
android:textSize="16sp" />
-</LinearLayout>
\ No newline at end of file
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/enable_work_apps"
+ android:textColor="?attr/workProfileOverlayTextColor"
+ android:text="@string/work_apps_enable_btn_text"
+ android:textAlignment="center"
+ android:background="@drawable/work_card_btn"
+ android:textSize="14sp" />
+</com.android.launcher3.allapps.WorkPausedCard>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e8d3212..12f50e5 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -94,7 +94,7 @@
<dimen name="all_apps_background_canvas_height">475dp</dimen>
<dimen name="all_apps_header_pill_height">48dp</dimen>
<dimen name="all_apps_header_pill_corner_radius">18dp</dimen>
- <dimen name="all_apps_header_pills_width">320dp</dimen>
+ <dimen name="all_apps_header_pills_width">348dp</dimen>
<dimen name="all_apps_header_tab_height">48dp</dimen>
<dimen name="all_apps_tabs_indicator_height">2dp</dimen>
<dimen name="all_apps_header_top_padding">36dp</dimen>
@@ -140,7 +140,6 @@
<dimen name="widget_list_top_bottom_corner_radius">28dp</dimen>
<dimen name="widget_list_content_corner_radius">4dp</dimen>
- <dimen name="widget_list_content_joined_corner_radius">0dp</dimen>
<dimen name="widget_list_header_view_vertical_padding">20dp</dimen>
<dimen name="widget_list_entry_bottom_margin">2dp</dimen>
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
index 84a03d5..4e2a508 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
@@ -107,7 +107,10 @@
/* iconClickListener= */ view -> {},
/* iconLongClickListener= */ view -> false);
mViewHolderBinder = new WidgetsListHeaderViewHolderBinder(
- LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter);
+ LayoutInflater.from(mTestActivity),
+ mOnHeaderClickListener,
+ new WidgetsListDrawableFactory(mTestActivity),
+ widgetsListAdapter);
}
@After
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
index 075c58d..d6aea55 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
@@ -107,7 +107,10 @@
/* iconClickListener= */ view -> {},
/* iconLongClickListener= */ view -> false);
mViewHolderBinder = new WidgetsListSearchHeaderViewHolderBinder(
- LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter);
+ LayoutInflater.from(mTestActivity),
+ mOnHeaderClickListener,
+ new WidgetsListDrawableFactory(mTestActivity),
+ widgetsListAdapter);
}
@After
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 0c6e717..2f1326f 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -118,6 +118,7 @@
mOnIconClickListener,
mOnLongClickListener,
mWidgetPreviewLoader,
+ new WidgetsListDrawableFactory(mTestActivity),
widgetsListAdapter);
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index d749e02..7003df1 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -23,7 +23,6 @@
import android.animation.ValueAnimator;
import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -494,15 +493,6 @@
}
}
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- View overlay = mAH[AdapterHolder.WORK].getOverlayView();
- int v = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ? GONE : VISIBLE;
- overlay.findViewById(R.id.work_apps_paused_title).setVisibility(v);
- overlay.findViewById(R.id.work_apps_paused_content).setVisibility(v);
- }
-
private void replaceRVContainer(boolean showTabs) {
for (int i = 0; i < mAH.length; i++) {
if (mAH[i].recyclerView != null) {
@@ -544,9 +534,6 @@
&& mAllAppsStore.hasModelFlag(
FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION));
}
- if (mSearchUiManager != null && mSearchUiManager.getEditText() != null) {
- mSearchUiManager.getEditText().hideKeyboard();
- }
}
// Used by tests only
@@ -704,7 +691,9 @@
mHeaderPaint.setColor(mHeaderColor);
mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
- canvas.drawRect(0, 0, getWidth(), mSearchContainer.getTop() + getTranslationY(),
+ int bottom = mUsingTabs && mHeader.mHeaderCollapsed ? mHeader.getVisibleBottomBound()
+ : mSearchContainer.getBottom();
+ canvas.drawRect(0, 0, getWidth(), bottom + getTranslationY(),
mHeaderPaint);
}
}
@@ -781,13 +770,6 @@
mAH[AdapterHolder.MAIN].recyclerView.setVerticalFadingEdgeEnabled(!mUsingTabs
&& verticalFadingEdge);
}
-
- private View getOverlayView() {
- if (mOverlay == null) {
- mOverlay = mLauncher.getLayoutInflater().inflate(R.layout.work_apps_paused, null);
- }
- return mOverlay;
- }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 5bbd02b..4ad694b 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -447,4 +447,14 @@
public boolean hasOverlappingRendering() {
return false;
}
+
+ /**
+ * Returns distance between left and right app icons
+ */
+ public int getTabWidth() {
+ DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+ int totalWidth = (grid.availableWidthPx - getPaddingLeft() - getPaddingRight());
+ int iconPadding = totalWidth / grid.numShownAllAppsColumns - grid.allAppsIconSizePx;
+ return totalWidth - iconPadding;
+ }
}
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 450d2e2..f1381e9 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -72,8 +72,13 @@
}
int current = -mCurrentRV.getCurrentScrollY();
+ boolean headerCollapsed = mHeaderCollapsed;
moved(current);
applyVerticalMove();
+ if (headerCollapsed != mHeaderCollapsed) {
+ AllAppsContainerView parent = (AllAppsContainerView) getParent();
+ parent.invalidateHeader();
+ }
}
};
@@ -219,6 +224,8 @@
mTabsHidden = tabsHidden;
mTabLayout.setVisibility(tabsHidden ? View.GONE : View.VISIBLE);
+ mTabLayout.getLayoutParams().width =
+ mAH[AllAppsContainerView.AdapterHolder.MAIN].recyclerView.getTabWidth();
mMainRV = setupRV(mMainRV, mAH[AllAppsContainerView.AdapterHolder.MAIN].recyclerView);
mWorkRV = setupRV(mWorkRV, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView);
mParent = (ViewGroup) mMainRV.getParent();
@@ -429,6 +436,13 @@
}
return null;
}
+
+ /**
+ * Returns visible height of FloatingHeaderView contents
+ */
+ public int getVisibleBottomBound() {
+ return getBottom() + mTranslationY;
+ }
}
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index 29a42f8..9db7bf0 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -21,7 +21,7 @@
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-import android.widget.LinearLayout;
+import android.widget.FrameLayout;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
@@ -29,7 +29,7 @@
/**
* Work profile toggle switch shown at the bottom of AllApps work tab
*/
-public class WorkEduCard extends LinearLayout implements View.OnClickListener,
+public class WorkEduCard extends FrameLayout implements View.OnClickListener,
Animation.AnimationListener {
private final Launcher mLauncher;
@@ -52,11 +52,24 @@
mDismissAnim.setAnimationListener(this);
}
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mDismissAnim.reset();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mDismissAnim.cancel();
+ }
@Override
protected void onFinishInflate() {
super.onFinishInflate();
findViewById(R.id.action_btn).setOnClickListener(this);
+ MarginLayoutParams lp = ((MarginLayoutParams) findViewById(R.id.wrapper).getLayoutParams());
+ lp.width = mLauncher.getAppsView().getActiveRecyclerView().getTabWidth();
}
@Override
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index c22cd63..866694f 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -31,7 +31,6 @@
import androidx.annotation.RequiresApi;
import com.android.launcher3.Insettable;
-import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.pm.UserCache;
@@ -79,7 +78,9 @@
clearAnimation();
if (workTabVisible) {
setEnabled(true);
- setVisibility(VISIBLE);
+ if (mWorkEnabled) {
+ setVisibility(VISIBLE);
+ }
setAlpha(0);
animate().alpha(1).start();
} else {
@@ -91,7 +92,7 @@
public void onClick(View view) {
if (Utilities.ATLEAST_P) {
setEnabled(false);
- UI_HELPER_EXECUTOR.post(() -> setToState(!mWorkEnabled));
+ UI_HELPER_EXECUTOR.post(() -> setWorkProfileEnabled(getContext(), false));
}
}
@@ -101,20 +102,18 @@
public void updateCurrentState(boolean active) {
mWorkEnabled = active;
setEnabled(true);
- setCompoundDrawablesRelativeWithIntrinsicBounds(
- active ? R.drawable.ic_corp_off : R.drawable.ic_corp, 0, 0, 0);
- setText(active ? R.string.work_apps_pause_btn_text : R.string.work_apps_enable_btn_text);
+ setVisibility(active ? VISIBLE : GONE);
}
@RequiresApi(Build.VERSION_CODES.P)
- protected Boolean setToState(boolean toState) {
- UserManager userManager = getContext().getSystemService(UserManager.class);
+ public static Boolean setWorkProfileEnabled(Context context, boolean enabled) {
+ UserManager userManager = context.getSystemService(UserManager.class);
boolean showConfirm = false;
- for (UserHandle userProfile : UserCache.INSTANCE.get(getContext()).getUserProfiles()) {
+ for (UserHandle userProfile : UserCache.INSTANCE.get(context).getUserProfiles()) {
if (Process.myUserHandle().equals(userProfile)) {
continue;
}
- showConfirm |= !userManager.requestQuietModeEnabled(!toState, userProfile);
+ showConfirm |= !userManager.requestQuietModeEnabled(!enabled, userProfile);
}
return showConfirm;
}
diff --git a/src/com/android/launcher3/allapps/WorkPausedCard.java b/src/com/android/launcher3/allapps/WorkPausedCard.java
new file mode 100644
index 0000000..3955a9a
--- /dev/null
+++ b/src/com/android/launcher3/allapps/WorkPausedCard.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
+/**
+ * Work profile toggle switch shown at the bottom of AllApps work tab
+ */
+public class WorkPausedCard extends LinearLayout implements View.OnClickListener {
+
+ private final Launcher mLauncher;
+ private Button mBtn;
+
+ public WorkPausedCard(Context context) {
+ this(context, null, 0);
+ }
+
+ public WorkPausedCard(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WorkPausedCard(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mLauncher = Launcher.getLauncher(getContext());
+ }
+
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mBtn = findViewById(R.id.enable_work_apps);
+ mBtn.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (Utilities.ATLEAST_P) {
+ setEnabled(false);
+ UI_HELPER_EXECUTOR.post(() -> WorkModeSwitch.setWorkProfileEnabled(getContext(), true));
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ int orientation = getResources().getConfiguration().orientation;
+ getLayoutParams().height = orientation == Configuration.ORIENTATION_PORTRAIT
+ ? LayoutParams.MATCH_PARENT : LayoutParams.WRAP_CONTENT;
+ super.onLayout(changed, l, t, r, b);
+ }
+}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 418e46d..345a2ac 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -473,7 +473,13 @@
LAUNCHER_WIDGET_RESIZE_COMPLETED(824),
@UiEvent(doc = "User reconfigured a widget on their home screen.")
- LAUNCHER_WIDGET_RECONFIGURED(821)
+ LAUNCHER_WIDGET_RECONFIGURED(821),
+
+ @UiEvent(doc = "User enabled themed icons option in wallpaper & style settings.")
+ LAUNCHER_THEMED_ICON_ENABLED(836),
+
+ @UiEvent(doc = "User disabled themed icons option in wallpaper & style settings.")
+ LAUNCHER_THEMED_ICON_DISABLED(837)
;
// ADD MORE
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 3be2c3a..365cab1 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -130,8 +130,9 @@
packageName);
if (!packageInstaller.verifySessionInfo(sessionInfo)) {
- FileLog.d(LOG, "Item info failed session info verification: "
- + workspaceInfo);
+ FileLog.d(LOG, "Item info failed session info verification. "
+ + "Skipping : " + workspaceInfo);
+ continue;
}
List<LauncherActivityInfo> activities = launcherApps
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 5255490..2bd9ba0 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -217,7 +217,8 @@
void tryQueuePromiseAppIcon(PackageInstaller.SessionInfo sessionInfo) {
if (FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
&& SessionCommitReceiver.isEnabled(mAppContext)
- && verifySessionInfo(sessionInfo)) {
+ && verifySessionInfo(sessionInfo)
+ && !promiseIconAddedForId(sessionInfo.getSessionId())) {
FileLog.d(LOG, "Adding package name to install queue: "
+ sessionInfo.getAppPackageName());
@@ -234,25 +235,28 @@
&& sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER
&& sessionInfo.getAppIcon() != null
&& !TextUtils.isEmpty(sessionInfo.getAppLabel())
- && !promiseIconAddedForId(sessionInfo.getSessionId())
&& !new PackageManagerHelper(mAppContext).isAppInstalled(
sessionInfo.getAppPackageName(), getUserHandle(sessionInfo));
if (sessionInfo != null) {
Bitmap appIcon = sessionInfo.getAppIcon();
- FileLog.d(LOG, String.format(
- "Verifying session info. Valid: %b, Session verified: %b, Install reason valid:"
- + " %b, App icon: %s, App label: %s, Promise icon added: %b, "
- + "App installed: %b.",
- validSessionInfo,
- verify(sessionInfo) != null,
- sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER,
- appIcon == null ? "null" : IOUtils.toBase64String(appIcon),
- sessionInfo.getAppLabel(),
- promiseIconAddedForId(sessionInfo.getSessionId()),
- new PackageManagerHelper(mAppContext).isAppInstalled(
- sessionInfo.getAppPackageName(), getUserHandle(sessionInfo))));
+ if (Utilities.IS_DEBUG_DEVICE) {
+ FileLog.d(LOG, String.format(
+ "Verifying session info. Valid: %b,"
+ + " Session verified: %b,"
+ + " Install reason valid: %b,"
+ + " App icon: %s,"
+ + " App label: %s,"
+ + " App installed: %b.",
+ validSessionInfo,
+ verify(sessionInfo) != null,
+ sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER,
+ appIcon == null ? "null" : IOUtils.toBase64String(appIcon),
+ sessionInfo.getAppLabel(),
+ new PackageManagerHelper(mAppContext).isAppInstalled(
+ sessionInfo.getAppPackageName(), getUserHandle(sessionInfo))));
+ }
} else {
FileLog.d(LOG, "Verifying session info failed: session info null.");
}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 332390d..2ae12ac 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -96,6 +96,8 @@
private int mNumNotifications;
private ViewGroup mNotificationContainer;
+ private ViewGroup mWidgetContainer;
+
private ViewGroup mDeepShortcutContainer;
private ViewGroup mSystemShortcutContainer;
@@ -234,7 +236,7 @@
@Override
protected List<View> getChildrenForColorExtraction() {
- return Arrays.asList(mSystemShortcutContainer, mDeepShortcutContainer,
+ return Arrays.asList(mSystemShortcutContainer, mWidgetContainer, mDeepShortcutContainer,
mNotificationContainer);
}
@@ -298,10 +300,24 @@
updateHiddenShortcuts();
if (!systemShortcuts.isEmpty()) {
- mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons, this);
for (SystemShortcut shortcut : systemShortcuts) {
- initializeSystemShortcut(
- R.layout.system_shortcut_icon_only, mSystemShortcutContainer, shortcut);
+ if (shortcut instanceof SystemShortcut.Widgets) {
+ if (mWidgetContainer == null) {
+ mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container,
+ this);
+ }
+ initializeSystemShortcut(R.layout.system_shortcut, mWidgetContainer,
+ shortcut);
+ }
+ }
+ mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons, this);
+
+ for (SystemShortcut shortcut : systemShortcuts) {
+ if (!(shortcut instanceof SystemShortcut.Widgets)) {
+ initializeSystemShortcut(
+ R.layout.system_shortcut_icon_only, mSystemShortcutContainer,
+ shortcut);
+ }
}
}
} else {
@@ -524,25 +540,34 @@
mLauncher.getPopupDataProvider().setChangeListener(null);
}
+ private View getWidgetsView(ViewGroup container) {
+ for (int i = container.getChildCount() - 1; i >= 0; --i) {
+ View systemShortcutView = container.getChildAt(i);
+ if (systemShortcutView.getTag() instanceof SystemShortcut.Widgets) {
+ return systemShortcutView;
+ }
+ }
+ return null;
+ }
+
@Override
public void onWidgetsBound() {
ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag();
SystemShortcut widgetInfo = SystemShortcut.WIDGETS.getShortcut(mLauncher, itemInfo);
- View widgetsView = null;
- int count = mSystemShortcutContainer.getChildCount();
- for (int i = 0; i < count; i++) {
- View systemShortcutView = mSystemShortcutContainer.getChildAt(i);
- if (systemShortcutView.getTag() instanceof SystemShortcut.Widgets) {
- widgetsView = systemShortcutView;
- break;
- }
+ View widgetsView = getWidgetsView(PopupContainerWithArrow.this);
+ if (widgetsView == null && mWidgetContainer != null) {
+ widgetsView = getWidgetsView(mWidgetContainer);
}
if (widgetInfo != null && widgetsView == null) {
// We didn't have any widgets cached but now there are some, so enable the shortcut.
if (mSystemShortcutContainer != PopupContainerWithArrow.this) {
- initializeSystemShortcut(R.layout.system_shortcut_icon_only,
- mSystemShortcutContainer, widgetInfo);
+ if (mWidgetContainer == null) {
+ mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container,
+ PopupContainerWithArrow.this);
+ }
+ initializeSystemShortcut(R.layout.system_shortcut, mWidgetContainer,
+ widgetInfo);
} else {
// If using the expanded system shortcut (as opposed to just the icon), we need
// to reopen the container to ensure measurements etc. all work out. While this
@@ -554,8 +579,10 @@
}
} else if (widgetInfo == null && widgetsView != null) {
// No widgets exist, but we previously added the shortcut so remove it.
- if (mSystemShortcutContainer != PopupContainerWithArrow.this) {
- mSystemShortcutContainer.removeView(widgetsView);
+ if (mSystemShortcutContainer
+ != PopupContainerWithArrow.this
+ && mWidgetContainer != null) {
+ mWidgetContainer.removeView(widgetsView);
} else {
close(false);
PopupContainerWithArrow.showForIcon(mOriginalIcon);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index e89aea7..6863c60 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -103,18 +103,25 @@
OnClickListener iconClickListener, OnLongClickListener iconLongClickListener) {
mLauncher = Launcher.getLauncher(context);
mDiffReporter = new WidgetsDiffReporter(iconCache, this);
+ WidgetsListDrawableFactory listDrawableFactory = new WidgetsListDrawableFactory(context);
mWidgetsListTableViewHolderBinder = new WidgetsListTableViewHolderBinder(context,
layoutInflater, iconClickListener, iconLongClickListener,
- widgetPreviewLoader, /* listAdapter= */ this);
+ widgetPreviewLoader, listDrawableFactory, /* listAdapter= */ this);
mViewHolderBinders.put(VIEW_TYPE_WIDGETS_LIST, mWidgetsListTableViewHolderBinder);
mViewHolderBinders.put(
VIEW_TYPE_WIDGETS_HEADER,
new WidgetsListHeaderViewHolderBinder(
- layoutInflater, /* onHeaderClickListener= */this, /* listAdapter= */ this));
+ layoutInflater,
+ /* onHeaderClickListener= */ this,
+ listDrawableFactory,
+ /* listAdapter= */ this));
mViewHolderBinders.put(
VIEW_TYPE_WIDGETS_SEARCH_HEADER,
new WidgetsListSearchHeaderViewHolderBinder(
- layoutInflater, /*onHeaderClickListener=*/ this, /* listAdapter= */ this));
+ layoutInflater,
+ /* onHeaderClickListener= */ this,
+ listDrawableFactory,
+ /* listAdapter= */ this));
}
@Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java b/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java
new file mode 100644
index 0000000..c61e3a4
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.widget.picker;
+
+import static com.android.launcher3.widget.picker.WidgetsListDrawableState.FIRST;
+import static com.android.launcher3.widget.picker.WidgetsListDrawableState.FIRST_EXPANDED;
+import static com.android.launcher3.widget.picker.WidgetsListDrawableState.LAST;
+import static com.android.launcher3.widget.picker.WidgetsListDrawableState.MIDDLE;
+import static com.android.launcher3.widget.picker.WidgetsListDrawableState.MIDDLE_EXPANDED;
+import static com.android.launcher3.widget.picker.WidgetsListDrawableState.SINGLE;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.RippleDrawable;
+import android.graphics.drawable.StateListDrawable;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.Themes;
+
+/** Factory for creating drawables to use as background for list elements. */
+final class WidgetsListDrawableFactory {
+
+ private final float mTopBottomCornerRadius;
+ private final float mMiddleCornerRadius;
+ private final ColorStateList mSurfaceColor;
+ private final ColorStateList mRippleColor;
+
+ WidgetsListDrawableFactory(Context context) {
+ Resources res = context.getResources();
+ mTopBottomCornerRadius = res.getDimension(R.dimen.widget_list_top_bottom_corner_radius);
+ mMiddleCornerRadius = res.getDimension(R.dimen.widget_list_content_corner_radius);
+ mSurfaceColor = context.getColorStateList(R.color.surface);
+ mRippleColor = ColorStateList.valueOf(
+ Themes.getAttrColor(context, android.R.attr.colorControlHighlight));
+ }
+
+ /**
+ * Creates a drawable for widget header list items. This drawable supports all positions
+ * in {@link WidgetsListDrawableState}.
+ */
+ Drawable createHeaderBackgroundDrawable() {
+ StateListDrawable stateList = new StateListDrawable();
+ stateList.addState(
+ SINGLE.mStateSet,
+ createRoundedRectDrawable(mTopBottomCornerRadius, mTopBottomCornerRadius));
+ stateList.addState(
+ FIRST_EXPANDED.mStateSet,
+ createRoundedRectDrawable(mTopBottomCornerRadius, 0));
+ stateList.addState(
+ FIRST.mStateSet,
+ createRoundedRectDrawable(mTopBottomCornerRadius, mMiddleCornerRadius));
+ stateList.addState(
+ MIDDLE_EXPANDED.mStateSet,
+ createRoundedRectDrawable(mMiddleCornerRadius, 0));
+ stateList.addState(
+ MIDDLE.mStateSet,
+ createRoundedRectDrawable(mMiddleCornerRadius, mMiddleCornerRadius));
+ stateList.addState(
+ LAST.mStateSet,
+ createRoundedRectDrawable(mMiddleCornerRadius, mTopBottomCornerRadius));
+ return new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList);
+ }
+
+ /**
+ * Creates a drawable for widget content list items. This state list supports the middle and
+ * last states.
+ */
+ Drawable createContentBackgroundDrawable() {
+ StateListDrawable stateList = new StateListDrawable();
+ stateList.addState(
+ MIDDLE.mStateSet,
+ createRoundedRectDrawable(0, mMiddleCornerRadius));
+ stateList.addState(
+ LAST.mStateSet,
+ createRoundedRectDrawable(0, mTopBottomCornerRadius));
+ return new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList);
+ }
+
+ /** Creates a rounded-rect drawable with the specified radii. */
+ private Drawable createRoundedRectDrawable(float topRadius, float bottomRadius) {
+ GradientDrawable backgroundMask = new GradientDrawable();
+ backgroundMask.setColor(mSurfaceColor);
+ backgroundMask.setShape(GradientDrawable.RECTANGLE);
+ backgroundMask.setCornerRadii(
+ new float[]{
+ topRadius,
+ topRadius,
+ topRadius,
+ topRadius,
+ bottomRadius,
+ bottomRadius,
+ bottomRadius,
+ bottomRadius
+ });
+ return backgroundMask;
+ }
+}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListDrawableState.java b/src/com/android/launcher3/widget/picker/WidgetsListDrawableState.java
new file mode 100644
index 0000000..94f292b
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/WidgetsListDrawableState.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.widget.picker;
+
+/**
+ * Different possible list position states for an item in the widgets list to have. Note that only
+ * headers use the expanded state.
+ */
+enum WidgetsListDrawableState {
+ FIRST(new int[]{android.R.attr.state_first}),
+ FIRST_EXPANDED(new int[]{android.R.attr.state_first, android.R.attr.state_expanded}),
+ MIDDLE(new int[]{android.R.attr.state_middle}),
+ MIDDLE_EXPANDED(new int[]{android.R.attr.state_middle, android.R.attr.state_expanded}),
+ LAST(new int[]{android.R.attr.state_last}),
+ SINGLE(new int[]{android.R.attr.state_single});
+
+ final int[] mStateSet;
+
+ WidgetsListDrawableState(int[] stateSet) {
+ mStateSet = stateSet;
+ }
+
+ static WidgetsListDrawableState obtain(boolean isFirst, boolean isLast, boolean isExpanded) {
+ if (isFirst && isLast) return SINGLE;
+ if (isFirst && isExpanded) return FIRST_EXPANDED;
+ if (isFirst) return FIRST;
+ if (isLast) return LAST;
+ if (isExpanded) return MIDDLE_EXPANDED;
+ return MIDDLE;
+ }
+}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListDrawables.java b/src/com/android/launcher3/widget/picker/WidgetsListDrawables.java
deleted file mode 100644
index b3bb544..0000000
--- a/src/com/android/launcher3/widget/picker/WidgetsListDrawables.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.widget.picker;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.graphics.drawable.RippleDrawable;
-
-import com.android.launcher3.R;
-import com.android.launcher3.util.Themes;
-
-/** Helper class for creating drawables to use as background for list elements. */
-final class WidgetsListDrawables {
-
- private WidgetsListDrawables() {}
-
- /** Creates a list background drawable with the specified radii. */
- static Drawable createListBackgroundDrawable(
- Context context,
- float topRadius,
- float bottomRadius) {
- GradientDrawable backgroundMask = new GradientDrawable();
- backgroundMask.setColor(context.getColorStateList(R.color.surface));
- backgroundMask.setShape(GradientDrawable.RECTANGLE);
-
- backgroundMask.setCornerRadii(
- new float[]{
- topRadius,
- topRadius,
- topRadius,
- topRadius,
- bottomRadius,
- bottomRadius,
- bottomRadius,
- bottomRadius
- });
-
- return new RippleDrawable(
- /* color= */ ColorStateList.valueOf(
- Themes.getAttrColor(context, android.R.attr.colorControlHighlight)),
- /* content= */ backgroundMask,
- /* mask= */ backgroundMask);
- }
-
-}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
index fece359..cdab964 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
@@ -60,9 +60,6 @@
@Nullable private Drawable mIconDrawable;
private final int mIconSize;
private final int mBottomMarginSize;
- private final float mTopBottomCornerRadius;
- private final float mMiddleCornerRadius;
- private final float mJoinedCornerRadius;
private ImageView mAppIcon;
private TextView mTitle;
@@ -70,6 +67,7 @@
private CheckBox mExpandToggle;
private boolean mIsExpanded = false;
+ @Nullable private WidgetsListDrawableState mListDrawableState;
public WidgetsListHeader(Context context) {
this(context, /* attrs= */ null);
@@ -90,12 +88,6 @@
grid.iconSizePx);
mBottomMarginSize =
getResources().getDimensionPixelSize(R.dimen.widget_list_entry_bottom_margin);
- mTopBottomCornerRadius =
- getResources().getDimension(R.dimen.widget_list_top_bottom_corner_radius);
- mMiddleCornerRadius =
- getResources().getDimension(R.dimen.widget_list_content_corner_radius);
- mJoinedCornerRadius =
- getResources().getDimension(R.dimen.widget_list_content_joined_corner_radius);
}
@Override
@@ -163,6 +155,14 @@
}
}
+ /** Sets the {@link WidgetsListDrawableState} and refreshes the background drawable. */
+ @UiThread
+ public void setListDrawableState(WidgetsListDrawableState state) {
+ if (state == mListDrawableState) return;
+ this.mListDrawableState = state;
+ refreshDrawableState();
+ }
+
/** Apply app icon, labels and tag using a generic {@link WidgetsListHeaderEntry}. */
@UiThread
public void applyFromItemInfoWithIcon(WidgetsListHeaderEntry entry) {
@@ -263,20 +263,6 @@
verifyHighRes();
}
- /** Updates the list to have a background drawable with the appropriate corner radii. */
- @UiThread
- public void updateListBackground(boolean isFirst, boolean isLast, boolean isExpanded) {
- float topRadius = isFirst ? mTopBottomCornerRadius : mMiddleCornerRadius;
- float bottomRadius = isLast
- ? mTopBottomCornerRadius
- : isExpanded
- ? mJoinedCornerRadius
- : mMiddleCornerRadius;
- setBackground(
- WidgetsListDrawables.createListBackgroundDrawable(
- getContext(), topRadius, bottomRadius));
- }
-
private void setTitles(WidgetsListSearchHeaderEntry entry) {
mTitle.setText(entry.mPkgItem.title);
@@ -300,6 +286,17 @@
}
}
+ @Override
+ protected int[] onCreateDrawableState(int extraSpace) {
+ if (mListDrawableState == null) return super.onCreateDrawableState(extraSpace);
+ // Augment the state set from the super implementation with the custom states from
+ // mListDrawableState.
+ int[] drawableState =
+ super.onCreateDrawableState(extraSpace + mListDrawableState.mStateSet.length);
+ mergeDrawableStates(drawableState, mListDrawableState.mStateSet);
+ return drawableState;
+ }
+
/** Verifies that the current icon is high-res otherwise posts a request to load the icon. */
public void verifyHighRes() {
if (mIconLoadRequest != null) {
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinder.java
index 22d6d22..2f8f1ba 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinder.java
@@ -30,13 +30,16 @@
ViewHolderBinder<WidgetsListHeaderEntry, WidgetsListHeaderHolder> {
private final LayoutInflater mLayoutInflater;
private final OnHeaderClickListener mOnHeaderClickListener;
+ private final WidgetsListDrawableFactory mListDrawableFactory;
private final WidgetsListAdapter mWidgetsListAdapter;
public WidgetsListHeaderViewHolderBinder(LayoutInflater layoutInflater,
OnHeaderClickListener onHeaderClickListener,
+ WidgetsListDrawableFactory listDrawableFactory,
WidgetsListAdapter listAdapter) {
mLayoutInflater = layoutInflater;
mOnHeaderClickListener = onHeaderClickListener;
+ mListDrawableFactory = listDrawableFactory;
mWidgetsListAdapter = listAdapter;
}
@@ -44,7 +47,7 @@
public WidgetsListHeaderHolder newViewHolder(ViewGroup parent) {
WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
R.layout.widgets_list_row_header, parent, false);
-
+ header.setBackground(mListDrawableFactory.createHeaderBackgroundDrawable());
return new WidgetsListHeaderHolder(header);
}
@@ -52,12 +55,13 @@
public void bindViewHolder(WidgetsListHeaderHolder viewHolder, WidgetsListHeaderEntry data,
int position) {
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
- widgetsListHeader.updateListBackground(
- /* isFirst= */ position == 0,
- /* isLast= */ position == mWidgetsListAdapter.getItemCount() - 1,
- /* isExpanded= */ data.isWidgetListShown());
widgetsListHeader.applyFromItemInfoWithIcon(data);
widgetsListHeader.setExpanded(data.isWidgetListShown());
+ widgetsListHeader.setListDrawableState(
+ WidgetsListDrawableState.obtain(
+ /* isFirst= */ position == 0,
+ /* isLast= */ position == mWidgetsListAdapter.getItemCount() - 1,
+ /* isExpanded= */ data.isWidgetListShown()));
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
mOnHeaderClickListener.onHeaderClicked(
isExpanded,
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinder.java
index d5e03a4..31dd9ee 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinder.java
@@ -31,13 +31,16 @@
ViewHolderBinder<WidgetsListSearchHeaderEntry, WidgetsListSearchHeaderHolder> {
private final LayoutInflater mLayoutInflater;
private final OnHeaderClickListener mOnHeaderClickListener;
+ private final WidgetsListDrawableFactory mListDrawableFactory;
private final WidgetsListAdapter mWidgetsListAdapter;
public WidgetsListSearchHeaderViewHolderBinder(LayoutInflater layoutInflater,
OnHeaderClickListener onHeaderClickListener,
+ WidgetsListDrawableFactory listDrawableFactory,
WidgetsListAdapter listAdapter) {
mLayoutInflater = layoutInflater;
mOnHeaderClickListener = onHeaderClickListener;
+ mListDrawableFactory = listDrawableFactory;
mWidgetsListAdapter = listAdapter;
}
@@ -45,7 +48,7 @@
public WidgetsListSearchHeaderHolder newViewHolder(ViewGroup parent) {
WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
R.layout.widgets_list_row_header, parent, false);
-
+ header.setBackground(mListDrawableFactory.createHeaderBackgroundDrawable());
return new WidgetsListSearchHeaderHolder(header);
}
@@ -53,12 +56,13 @@
public void bindViewHolder(WidgetsListSearchHeaderHolder viewHolder,
WidgetsListSearchHeaderEntry data, int position) {
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
- widgetsListHeader.updateListBackground(
- /* isFirst= */ position == 0,
- /* isLast= */ position == mWidgetsListAdapter.getItemCount() - 1,
- /* isExpanded= */ data.isWidgetListShown());
widgetsListHeader.applyFromItemInfoWithIcon(data);
widgetsListHeader.setExpanded(data.isWidgetListShown());
+ widgetsListHeader.setListDrawableState(
+ WidgetsListDrawableState.obtain(
+ /* isFirst= */ position == 0,
+ /* isLast= */ position == mWidgetsListAdapter.getItemCount() - 1,
+ /* isExpanded= */ data.isWidgetListShown()));
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
mOnHeaderClickListener.onHeaderClicked(isExpanded,
new PackageUserKey(data.mPkgItem.packageName, data.mPkgItem.user)));
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListTableView.java b/src/com/android/launcher3/widget/picker/WidgetsListTableView.java
new file mode 100644
index 0000000..d30e7b6
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/WidgetsListTableView.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.widget.picker;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TableLayout;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+
+/**
+ * Extension of {@link TableLayout} to support the drawable states used by
+ * {@link WidgetsListDrawableState}.
+ */
+public class WidgetsListTableView extends TableLayout {
+
+ @Nullable private WidgetsListDrawableState mListDrawableState;
+
+ public WidgetsListTableView(Context context) {
+ super(context);
+ }
+
+ public WidgetsListTableView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ /** Sets the {@link WidgetsListDrawableState} and refreshes the background drawable. */
+ @UiThread
+ public void setListDrawableState(WidgetsListDrawableState state) {
+ if (state == mListDrawableState) return;
+ mListDrawableState = state;
+ refreshDrawableState();
+ }
+
+ @Override
+ protected int[] onCreateDrawableState(int extraSpace) {
+ if (mListDrawableState == null) return super.onCreateDrawableState(extraSpace);
+ // Augment the state set from the super implementation with the custom states from
+ // mListDrawableState.
+ int[] drawableState =
+ super.onCreateDrawableState(extraSpace + mListDrawableState.mStateSet.length);
+ mergeDrawableStates(drawableState, mListDrawableState.mStateSet);
+ return drawableState;
+ }
+}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
index 8e310c5..7e8c55b 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
@@ -15,8 +15,10 @@
*/
package com.android.launcher3.widget.picker;
+import static com.android.launcher3.widget.picker.WidgetsListDrawableState.LAST;
+import static com.android.launcher3.widget.picker.WidgetsListDrawableState.MIDDLE;
+
import android.content.Context;
-import android.content.res.Resources;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -51,10 +53,8 @@
private final OnClickListener mIconClickListener;
private final OnLongClickListener mIconLongClickListener;
private final WidgetPreviewLoader mWidgetPreviewLoader;
+ private final WidgetsListDrawableFactory mListDrawableFactory;
private final WidgetsListAdapter mWidgetsListAdapter;
- private final float mTopBottomCornerRadius;
- private final float mMiddleCornerRadius;
- private final float mJoinedCornerRadius;
private boolean mApplyBitmapDeferred = false;
public WidgetsListTableViewHolderBinder(
@@ -63,19 +63,14 @@
OnClickListener iconClickListener,
OnLongClickListener iconLongClickListener,
WidgetPreviewLoader widgetPreviewLoader,
+ WidgetsListDrawableFactory listDrawableFactory,
WidgetsListAdapter listAdapter) {
mLayoutInflater = layoutInflater;
mIconClickListener = iconClickListener;
mIconLongClickListener = iconLongClickListener;
mWidgetPreviewLoader = widgetPreviewLoader;
+ mListDrawableFactory = listDrawableFactory;
mWidgetsListAdapter = listAdapter;
- Resources resources = context.getResources();
- mTopBottomCornerRadius =
- resources.getDimension(R.dimen.widget_list_top_bottom_corner_radius);
- mMiddleCornerRadius =
- resources.getDimension(R.dimen.widget_list_content_corner_radius);
- mJoinedCornerRadius =
- resources.getDimension(R.dimen.widget_list_content_joined_corner_radius);
}
/**
@@ -97,28 +92,25 @@
Log.v(TAG, "\nonCreateViewHolder");
}
- ViewGroup container = (ViewGroup) mLayoutInflater.inflate(
- R.layout.widgets_table_container, parent, false);
- return new WidgetsRowViewHolder(container);
+ WidgetsRowViewHolder viewHolder =
+ new WidgetsRowViewHolder(mLayoutInflater.inflate(
+ R.layout.widgets_table_container, parent, false));
+ viewHolder.mTableContainer.setBackgroundDrawable(
+ mListDrawableFactory.createContentBackgroundDrawable());
+ return viewHolder;
}
@Override
public void bindViewHolder(WidgetsRowViewHolder holder, WidgetsListContentEntry entry,
int position) {
- TableLayout table = holder.mTableContainer;
+ WidgetsListTableView table = holder.mTableContainer;
if (DEBUG) {
Log.d(TAG, String.format("onBindViewHolder [widget#=%d, table.getChildCount=%d]",
entry.mWidgets.size(), table.getChildCount()));
}
- // The content is always joined to an expanded header above.
- float topRadius = mJoinedCornerRadius;
- float bottomRadius = position == mWidgetsListAdapter.getItemCount() - 1
- ? mTopBottomCornerRadius
- : mMiddleCornerRadius;
- table.setBackgroundDrawable(
- WidgetsListDrawables.createListBackgroundDrawable(
- holder.itemView.getContext(), topRadius, bottomRadius));
+ table.setListDrawableState(
+ position == mWidgetsListAdapter.getItemCount() - 1 ? LAST : MIDDLE);
List<ArrayList<WidgetItem>> widgetItemsTable =
WidgetsTableUtils.groupWidgetItemsIntoTable(entry.mWidgets, mMaxSpansPerRow);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRowViewHolder.java b/src/com/android/launcher3/widget/picker/WidgetsRowViewHolder.java
index aef1103..618e2cb 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRowViewHolder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRowViewHolder.java
@@ -15,8 +15,7 @@
*/
package com.android.launcher3.widget.picker;
-import android.view.ViewGroup;
-import android.widget.TableLayout;
+import android.view.View;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
@@ -25,9 +24,9 @@
/** A {@link ViewHolder} for showing widgets of an app in the full widget picker. */
public final class WidgetsRowViewHolder extends ViewHolder {
- public final TableLayout mTableContainer;
+ public final WidgetsListTableView mTableContainer;
- public WidgetsRowViewHolder(ViewGroup v) {
+ public WidgetsRowViewHolder(View v) {
super(v);
mTableContainer = v.findViewById(R.id.widgets_table);
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 6f47df0..06bc26a 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -293,7 +293,7 @@
try {
final AppIconMenu menu = allApps.
getAppIcon(APP_NAME).
- openMenu();
+ openDeepShortcutMenu();
executeOnLauncher(
launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu",
@@ -341,7 +341,7 @@
try {
final AppIconMenu menu = allApps
.getAppIcon(APP_NAME)
- .openMenu();
+ .openDeepShortcutMenu();
final AppIconMenuItem menuItem0 = menu.getMenuItem(0);
final AppIconMenuItem menuItem2 = menu.getMenuItem(2);
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index 56723b1..57fd08a 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -51,6 +51,16 @@
}
}
+ /**
+ * Long-clicks the icon to open its menu, and looks at the deep shortcuts container only.
+ */
+ public AppIconMenu openDeepShortcutMenu() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ return new AppIconMenu(mLauncher, mLauncher.clickAndGet(
+ mObject, "deep_shortcuts_container", LONG_CLICK_EVENT));
+ }
+ }
+
@Override
protected void addExpectedEventsForLongClick() {
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT);