diff options
3 files changed, 103 insertions, 33 deletions
| diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index e8b346ed97ab..49beae6872fd 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -94,6 +94,9 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList      private boolean mActivityViewReady = false;      private PendingIntent mBubbleIntent; +    private boolean mKeyboardVisible; +    private boolean mNeedsNewHeight; +      private int mMinHeight;      private int mHeaderHeight;      private int mBubbleHeight; @@ -227,21 +230,15 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList                  true /* singleTaskInstance */);          addView(mActivityView); -        mActivityView.setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> { -            ActivityView activityView = (ActivityView) view; -            // Here we assume that the position of the ActivityView on the screen -            // remains regardless of IME status. When we move ActivityView, the -            // forwardedInsets should be computed not against the current location -            // and size, but against the post-moved location and size. -            Point displaySize = new Point(); -            view.getContext().getDisplay().getSize(displaySize); -            int[] windowLocation = view.getLocationOnScreen(); -            final int windowBottom = windowLocation[1] + view.getHeight(); +        setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> { +            // Keep track of IME displaying because we should not make any adjustments that might +            // cause a config change while the IME is displayed otherwise it'll loose focus.              final int keyboardHeight = insets.getSystemWindowInsetBottom()                      - insets.getStableInsetBottom(); -            final int insetsBottom = Math.max(0, -                    windowBottom + keyboardHeight - displaySize.y); -            activityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom)); +            mKeyboardVisible = keyboardHeight != 0; +            if (!mKeyboardVisible && mNeedsNewHeight) { +                updateHeight(); +            }              return view.onApplyWindowInsets(insets);          }); @@ -258,6 +255,34 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList          }      } +    @Override +    protected void onDetachedFromWindow() { +        super.onDetachedFromWindow(); +        mKeyboardVisible = false; +        mNeedsNewHeight = false; +        if (mActivityView != null) { +            mActivityView.setForwardedInsets(Insets.of(0, 0, 0, 0)); +        } +    } + +    /** +     * Called by {@link BubbleStackView} when the insets for the expanded state should be updated. +     * This should be done post-move and post-animation. +     */ +    void updateInsets(WindowInsets insets) { +        if (usingActivityView()) { +            Point displaySize = new Point(); +            mActivityView.getContext().getDisplay().getSize(displaySize); +            int[] windowLocation = mActivityView.getLocationOnScreen(); +            final int windowBottom = windowLocation[1] + mActivityView.getHeight(); +            final int keyboardHeight = insets.getSystemWindowInsetBottom() +                    - insets.getStableInsetBottom(); +            final int insetsBottom = Math.max(0, +                    windowBottom + keyboardHeight - displaySize.y); +            mActivityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom)); +        } +    } +      /**       * Creates a background with corners rounded based on how the view is configured to display       */ @@ -448,9 +473,15 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList              int height = Math.min(desiredHeight, max);              height = Math.max(height, mMinHeight);              LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams(); -            lp.height = height; -            mBubbleHeight = height; -            mActivityView.setLayoutParams(lp); +            mNeedsNewHeight =  lp.height != height; +            if (!mKeyboardVisible) { +                // If the keyboard is visible... don't adjust the height because that will cause +                // a configuration change and the keyboard will be lost. +                lp.height = height; +                mBubbleHeight = height; +                mActivityView.setLayoutParams(lp); +                mNeedsNewHeight = false; +            }          } else {              mBubbleHeight = mNotifRow != null ? mNotifRow.getIntrinsicHeight() : mMinHeight;          } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 461e79c671c4..580acb82ebc1 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -128,6 +128,7 @@ public class BubbleStackView extends FrameLayout {      private Bubble mExpandedBubble;      private boolean mIsExpanded; +    private boolean mImeVisible;      private BubbleTouchHandler mTouchHandler;      private BubbleController.BubbleExpandListener mExpandListener; @@ -236,6 +237,28 @@ public class BubbleStackView extends FrameLayout {          setClipChildren(false);          setFocusable(true);          mBubbleContainer.bringToFront(); + +        setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> { +            final int keyboardHeight = insets.getSystemWindowInsetBottom() +                    - insets.getStableInsetBottom(); +            if (!mIsExpanded) { +                return view.onApplyWindowInsets(insets); +            } +            mImeVisible = keyboardHeight != 0; + +            float newY = getYPositionForExpandedView(); +            if (newY < 0) { +                // TODO: This means our expanded content is too big to fit on screen. Right now +                // we'll let it translate off but we should be clipping it & pushing the header +                // down so that it always remains visible. +            } +            mExpandedViewYAnim.animateToFinalPosition(newY); +            mExpandedAnimationController.updateYPosition( +                    // Update the insets after we're done translating otherwise position +                    // calculation for them won't be correct. +                    () -> mExpandedBubble.expandedView.updateInsets(insets)); +            return view.onApplyWindowInsets(insets); +        });      }      /** @@ -646,15 +669,6 @@ public class BubbleStackView extends FrameLayout {          }      } -    /** -     * The width of the collapsed stack of bubbles. -     */ -    public int getStackWidth() { -        return mBubblePadding * (mBubbleContainer.getChildCount() - 1) -                + mBubbleSize + mBubbleContainer.getPaddingEnd() -                + mBubbleContainer.getPaddingStart(); -    } -      private void notifyExpansionChanged(NotificationEntry entry, boolean expanded) {          if (mExpandListener != null) {              mExpandListener.onBubbleExpandChanged(expanded, entry != null ? entry.key : null); @@ -843,8 +857,13 @@ public class BubbleStackView extends FrameLayout {              // calculation is correct)              mExpandedBubble.expandedView.updateView();              final float y = getYPositionForExpandedView(); -            mExpandedViewContainer.setTranslationY(y); -            // Then update the view so that ActivityView knows we translated +            if (!mExpandedViewYAnim.isRunning()) { +                // We're not animating so set the value +                mExpandedViewContainer.setTranslationY(y); +            } else { +                // We are animating so update the value +                mExpandedViewYAnim.animateToFinalPosition(y); +            }              mExpandedBubble.expandedView.updateView();          } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java index 1f29883b180a..40e08bed8352 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java @@ -198,6 +198,19 @@ public class ExpandedAnimationController      }      /** +     * Animates the bubbles to {@link #getExpandedY()} position. Used in response to IME showing. +     */ +    public void updateYPosition(Runnable after) { +        if (mLayout == null) return; + +        for (int i = 0; i < mLayout.getChildCount(); i++) { +            boolean isLast = i == mLayout.getChildCount() - 1; +            mLayout.animateValueForChildAtIndex(DynamicAnimation.TRANSLATION_Y, i, +                    getExpandedY(), isLast ? after : null); +        } +    } + +    /**       * Animates the bubbles, starting at the given index, to the left or right by the given number       * of bubble widths. Passing zero for numBubbleWidths will animate the bubbles to their normal       * positions. @@ -213,18 +226,25 @@ public class ExpandedAnimationController      /** The Y value of the row of expanded bubbles. */      public float getExpandedY() { -        boolean showOnTop = mLayout != null -                && BubbleController.showBubblesAtTop(mLayout.getContext()); -        final WindowInsets insets = mLayout != null ? mLayout.getRootWindowInsets() : null; -        if (showOnTop && insets != null) { +        if (mLayout == null || mLayout.getRootWindowInsets() == null) { +            return 0; +        } +        final boolean showOnTop = BubbleController.showBubblesAtTop(mLayout.getContext()); +        final WindowInsets insets = mLayout.getRootWindowInsets(); +        if (showOnTop) {              return mBubblePaddingPx + Math.max(                      mStatusBarHeight,                      insets.getDisplayCutout() != null                              ? insets.getDisplayCutout().getSafeInsetTop()                              : 0);          } else { -            int bottomInset = insets != null ? insets.getSystemWindowInsetBottom() : 0; -            return mDisplaySize.y - mBubbleSizePx - (mPipDismissHeight - bottomInset); +            int keyboardHeight = insets.getSystemWindowInsetBottom() +                    - insets.getStableInsetBottom(); +            float bottomInset = keyboardHeight > 0 +                    ? keyboardHeight +                    : (mPipDismissHeight - insets.getStableInsetBottom()); +            // Stable insets are excluded from display size, so we must subtract it +            return mDisplaySize.y - mBubbleSizePx - mBubblePaddingPx - bottomInset;          }      } |