Merge "Implement responsive grid for foldables 4x4 grid" into udc-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 6818db6..012a362 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -277,6 +277,7 @@
private void applyViewChanges(BubbleBarViewUpdate update) {
final boolean isCollapsed = (update.expandedChanged && !update.expanded)
|| (!update.expandedChanged && !mBubbleBarViewController.isExpanded());
+ BubbleBarItem previouslySelectedBubble = mSelectedBubble;
BubbleBarBubble bubbleToSelect = null;
if (!update.removedBubbles.isEmpty()) {
for (int i = 0; i < update.removedBubbles.size(); i++) {
@@ -321,6 +322,11 @@
mBubbleBarViewController.setHiddenForBubbles(mBubbles.isEmpty());
mBubbleStashedHandleViewController.setHiddenForBubbles(mBubbles.isEmpty());
+ if (mBubbles.isEmpty()) {
+ // all bubbles were removed. clear the selected bubble
+ mSelectedBubble = null;
+ }
+
if (update.updatedBubble != null) {
// Updates mean the dot state may have changed; any other changes were updated in
// the populateBubble step.
@@ -357,6 +363,11 @@
if (bubbleToSelect != null) {
setSelectedBubble(bubbleToSelect);
}
+
+ if (previouslySelectedBubble == null) {
+ mBubbleStashController.animateToInitialState(update.expanded);
+ }
+
if (update.expandedChanged) {
if (update.expanded != mBubbleBarViewController.isExpanded()) {
mBubbleBarViewController.setExpandedFromSysui(update.expanded);
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 8e7fda8..f5e2ddc 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -206,10 +206,12 @@
// TODO: (b/273592694) animate it
private void updateVisibilityForStateChange() {
- if (!mHiddenForSysui && !mBubbleStashController.isStashed() && !mHiddenForNoBubbles) {
+ if (!mHiddenForSysui && !mHiddenForNoBubbles) {
mBarView.setVisibility(VISIBLE);
} else {
mBarView.setVisibility(INVISIBLE);
+ mBarView.setAlpha(0);
+ mBarView.setExpanded(false);
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index 8af4ff9..a267211 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -71,6 +71,7 @@
private int mUnstashedHeight;
private boolean mBubblesShowingOnHome;
private boolean mBubblesShowingOnOverview;
+ private boolean mIsSysuiLocked;
@Nullable
private AnimatorSet mAnimator;
@@ -95,14 +96,6 @@
mStashedHeight = mHandleViewController.getStashedHeight();
mUnstashedHeight = mHandleViewController.getUnstashedHeight();
-
- bubbleControllers.runAfterInit(() -> {
- if (mTaskbarStashController.isStashed()) {
- stashBubbleBar();
- } else {
- showBubbleBar(false /* expandBubbles */);
- }
- });
}
/**
@@ -120,6 +113,40 @@
}
/**
+ * Animates the bubble bar and handle to their initial state, transitioning from the state where
+ * both views are invisible. Called when the first bubble is added or when the device is
+ * unlocked.
+ *
+ * <p>Normally either the bubble bar or the handle is visible,
+ * and {@link #showBubbleBar(boolean)} and {@link #stashBubbleBar()} are used to transition
+ * between these two states. But the transition from the state where both the bar and handle
+ * are invisible is slightly different.
+ *
+ * <p>The initial state will depend on the current state of the device, i.e. overview, home etc
+ * and whether bubbles are requested to be expanded.
+ */
+ public void animateToInitialState(boolean expanding) {
+ AnimatorSet animatorSet = new AnimatorSet();
+ if (expanding || mBubblesShowingOnHome || mBubblesShowingOnOverview) {
+ mIsStashed = false;
+ animatorSet.playTogether(mIconScaleForStash.animateToValue(1),
+ mIconTranslationYForStash.animateToValue(getBubbleBarTranslationY()),
+ mIconAlphaForStash.animateToValue(1));
+ } else {
+ mIsStashed = true;
+ animatorSet.playTogether(mBubbleStashedHandleAlpha.animateToValue(1));
+ }
+
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ onIsStashedChanged();
+ }
+ });
+ animatorSet.setDuration(BAR_STASH_DURATION).start();
+ }
+
+ /**
* Called when launcher enters or exits the home page. Bubbles are unstashed on home.
*/
public void setBubblesShowingOnHome(boolean onHome) {
@@ -172,12 +199,11 @@
/** Called when sysui locked state changes, when locked, bubble bar is stashed. */
public void onSysuiLockedStateChange(boolean isSysuiLocked) {
- if (isSysuiLocked) {
- // TODO: should the normal path flip mBubblesOnHome / check if this is needed
- // If we're locked, we're no longer showing on home.
- mBubblesShowingOnHome = false;
- mBubblesShowingOnOverview = false;
- stashBubbleBar();
+ if (isSysuiLocked != mIsSysuiLocked) {
+ mIsSysuiLocked = isSysuiLocked;
+ if (!mIsSysuiLocked) {
+ animateToInitialState(false /* expanding */);
+ }
}
}
@@ -256,11 +282,7 @@
firstHalfDurationScale = 0.5f;
secondHalfDurationScale = 0.75f;
- // If we're on home, adjust the translation so the bubble bar aligns with hotseat.
- // Otherwise we're either showing in an app or in overview. In either case adjust it so
- // the bubble bar aligns with the taskbar.
- final float translationY = mBubblesShowingOnHome ? getBubbleBarTranslationYForHotseat()
- : getBubbleBarTranslationYForTaskbar();
+ final float translationY = getBubbleBarTranslationY();
fullLengthAnimatorSet.playTogether(
mIconScaleForStash.animateToValue(1),
@@ -317,6 +339,9 @@
}
float getBubbleBarTranslationY() {
+ // If we're on home, adjust the translation so the bubble bar aligns with hotseat.
+ // Otherwise we're either showing in an app or in overview. In either case adjust it so
+ // the bubble bar aligns with the taskbar.
return mBubblesShowingOnHome ? getBubbleBarTranslationYForHotseat()
: getBubbleBarTranslationYForTaskbar();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index 26756d4..4c197f6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -52,6 +52,7 @@
private BubbleStashController mBubbleStashController;
private RegionSamplingHelper mRegionSamplingHelper;
private int mBarSize;
+ private int mStashedTaskbarHeight;
private int mStashedHandleWidth;
private int mStashedHandleHeight;
@@ -92,7 +93,7 @@
mTaskbarStashedHandleAlpha.get(0).setValue(0);
- final int stashedTaskbarHeight = resources.getDimensionPixelSize(
+ mStashedTaskbarHeight = resources.getDimensionPixelSize(
R.dimen.bubblebar_stashed_size);
mStashedHandleView.setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -115,22 +116,25 @@
}
}, Executors.UI_HELPER_EXECUTOR);
- mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> {
- // As more bubbles get added, the icon bounds become larger. To ensure a consistent
- // handle bar position, we pin it to the edge of the screen.
- Rect bubblebarRect = mBarViewController.getBubbleBarBounds();
- final int stashedCenterY = view.getHeight() - stashedTaskbarHeight / 2;
+ mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
+ updateBounds());
+ }
- mStashedHandleBounds.set(
- bubblebarRect.right - mStashedHandleWidth,
- stashedCenterY - mStashedHandleHeight / 2,
- bubblebarRect.right,
- stashedCenterY + mStashedHandleHeight / 2);
- mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
+ private void updateBounds() {
+ // As more bubbles get added, the icon bounds become larger. To ensure a consistent
+ // handle bar position, we pin it to the edge of the screen.
+ Rect bubblebarRect = mBarViewController.getBubbleBarBounds();
+ final int stashedCenterY = mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2;
- view.setPivotX(view.getWidth());
- view.setPivotY(view.getHeight() - stashedTaskbarHeight / 2f);
- });
+ mStashedHandleBounds.set(
+ bubblebarRect.right - mStashedHandleWidth,
+ stashedCenterY - mStashedHandleHeight / 2,
+ bubblebarRect.right,
+ stashedCenterY + mStashedHandleHeight / 2);
+ mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
+
+ mStashedHandleView.setPivotX(mStashedHandleView.getWidth());
+ mStashedHandleView.setPivotY(mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2f);
}
public void onDestroy() {
@@ -188,6 +192,7 @@
mStashedHandleView.setVisibility(VISIBLE);
} else {
mStashedHandleView.setVisibility(INVISIBLE);
+ mStashedHandleView.setAlpha(0);
}
updateRegionSampling();
}
@@ -235,6 +240,9 @@
*/
public Animator createRevealAnimToIsStashed(boolean isStashed) {
Rect bubbleBarBounds = new Rect(mBarViewController.getBubbleBarBounds());
+ // the bubble bar may have been invisible when the bounds were previously calculated,
+ // update them again to ensure they're correct.
+ updateBounds();
// Account for the full visual height of the bubble bar
int heightDiff = (mBarSize - bubbleBarBounds.height()) / 2;
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index a67d787..bc90db0 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -116,8 +116,7 @@
Utilities.enableRunningInTestHarnessForTests();
}
- final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
- RecentsActivity.ACTIVITY_TRACKER::getCreatedActivity);
+ final ViewCaptureRule viewCaptureRule = new ViewCaptureRule();
mOrderSensitiveRules = RuleChain
.outerRule(new SamplerRule())
.around(new NavigationModeSwitchRule(mLauncher))
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index d22a353..f061fab 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -201,8 +201,7 @@
}
protected TestRule getRulesInsideActivityMonitor() {
- final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
- Launcher.ACTIVITY_TRACKER::getCreatedActivity);
+ final ViewCaptureRule viewCaptureRule = new ViewCaptureRule();
final RuleChain inner = RuleChain
.outerRule(new PortraitLandscapeRunner(this))
.around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
diff --git a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
index b2a2f7f..1ca4434 100644
--- a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
+++ b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
@@ -25,7 +25,6 @@
import com.android.app.viewcapture.data.ExportedData
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter
import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer
-import java.util.function.Supplier
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
@@ -36,7 +35,7 @@
*
* This rule will not work in OOP tests that don't have access to the activity under test.
*/
-class ViewCaptureRule(var alreadyOpenActivitySupplier: Supplier<Activity?>) : TestRule {
+class ViewCaptureRule : TestRule {
private val viewCapture = SimpleViewCapture("test-view-capture")
var viewCaptureData: ExportedData? = null
private set
@@ -47,20 +46,13 @@
viewCaptureData = null
val windowListenerCloseables = mutableListOf<SafeCloseable>()
- val alreadyOpenActivity = alreadyOpenActivitySupplier.get()
- if (alreadyOpenActivity != null) {
- startCapture(windowListenerCloseables, alreadyOpenActivity)
- }
-
val lifecycleCallbacks =
object : ActivityLifecycleCallbacksAdapter {
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
- super.onActivityCreated(activity, bundle)
startCapture(windowListenerCloseables, activity)
}
override fun onActivityDestroyed(activity: Activity) {
- super.onActivityDestroyed(activity)
viewCapture.stopCapture(activity.window.decorView)
}
}