From ddb08885f9d51db577aedc386cc3a90d054132b2 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 10 Mar 2020 18:25:31 -0700 Subject: [PATCH] Try orienting popup the other way if offset pushes it out of bounds orientAboutObject() currently determines whether the popup should align its left side with the icon or the right side. However, after determining this, there is an offset to ensure the popup lines up with the icon as expected, which might push it out of bounds. In that case, we fallback to centering the popup. However, there might be plenty of room on the other side, so we should just align the other direction instead. Updated the logic to do that by first trying to align left (in LTR) or right (in RTL), then trying again with the other alignment if it doesn't fit after all x calculations are made. Bug: 150644839 Change-Id: I219dae331bf790e461d91394ffe025d40ec54c9b --- .../android/launcher3/popup/ArrowPopup.java | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java index 1c2acfd6fc..18bc55a5ab 100644 --- a/src/com/android/launcher3/popup/ArrowPopup.java +++ b/src/com/android/launcher3/popup/ArrowPopup.java @@ -240,6 +240,17 @@ public abstract class ArrowPopup extends Abstrac * and align above if there is enough vertical space. */ protected void orientAboutObject() { + orientAboutObject(true /* allowAlignLeft */, true /* allowAlignRight */); + } + + /** + * @see #orientAboutObject() + * + * @param allowAlignLeft Set to false if we already tried aligning left and didn't have room. + * @param allowAlignRight Set to false if we already tried aligning right and didn't have room. + * TODO: Can we test this with all permutations of widths/heights and icon locations + RTL? + */ + private void orientAboutObject(boolean allowAlignLeft, boolean allowAlignRight) { measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); int width = getMeasuredWidth(); int extraVerticalSpace = mArrow.getLayoutParams().height + mArrowOffset @@ -253,14 +264,8 @@ public abstract class ArrowPopup extends Abstrac // Align left (right in RTL) if there is room. int leftAlignedX = mTempRect.left; int rightAlignedX = mTempRect.right - width; - int x = leftAlignedX; - boolean canBeLeftAligned = leftAlignedX + width + insets.left - < dragLayer.getRight() - insets.right; - boolean canBeRightAligned = rightAlignedX > dragLayer.getLeft() + insets.left; - if (!canBeLeftAligned || (mIsRtl && canBeRightAligned)) { - x = rightAlignedX; - } - mIsLeftAligned = x == leftAlignedX; + mIsLeftAligned = !mIsRtl ? allowAlignLeft : !allowAlignRight; + int x = mIsLeftAligned ? leftAlignedX : rightAlignedX; // Offset x so that the arrow and shortcut icons are center-aligned with the original icon. int iconWidth = mTempRect.width(); @@ -282,6 +287,24 @@ public abstract class ArrowPopup extends Abstrac } x += mIsLeftAligned ? xOffset : -xOffset; + // Check whether we can still align as we originally wanted, now that we've calculated x. + if (!allowAlignLeft && !allowAlignRight) { + // We've already tried both ways and couldn't make it fit. onLayout() will set the + // gravity to CENTER_HORIZONTAL, but continue below to update y. + } else { + boolean canBeLeftAligned = x + width + insets.left + < dragLayer.getRight() - insets.right; + boolean canBeRightAligned = x > dragLayer.getLeft() + insets.left; + boolean alignmentStillValid = mIsLeftAligned && canBeLeftAligned + || !mIsLeftAligned && canBeRightAligned; + if (!alignmentStillValid) { + // Try again, but don't allow this alignment we already know won't work. + orientAboutObject(allowAlignLeft && !mIsLeftAligned /* allowAlignLeft */, + allowAlignRight && mIsLeftAligned /* allowAlignRight */); + return; + } + } + // Open above icon if there is room. int iconHeight = mTempRect.height(); int y = mTempRect.top - height;