From a8178f545412eefa732578b30860863fe628bc56 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Wed, 22 May 2019 13:01:01 +0800 Subject: [PATCH] HeadsUpAppearanceController: allow heads-up to draw beyond bounds On some devices with huge `rounded_corner_content_padding`, the icon of heads-up notifications will be clipped or even completely removed from view. This is caused by `HeadsUpStatusBarView` trying to align the heads-up icon with where the icon would be on a normal notification card, which would end up outside of the status bar contents view when `rounded_corner_content_padding` is set to beyond a certain value. This patch fixes the problem by allowing heads-up content to overflow the normal status bar content region when it is shown. As long as the rounded corner is not too huge, the aligning position of the icon should not be a problem of its own. Fixes: 131813566 Test: atest SystemUiTests Change-Id: I0fb8856c301a438ca87b06fcdbcf5323d9cda18c --- .../phone/HeadsUpAppearanceController.java | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java index 4baeeef1ffd00..66903fa531e08 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java @@ -23,6 +23,7 @@ import android.view.View; import android.view.WindowInsets; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.widget.ViewClippingUtil; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher; @@ -67,6 +68,13 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, private final View.OnLayoutChangeListener mStackScrollLayoutChangeListener = (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> updatePanelTranslation(); + private final ViewClippingUtil.ClippingParameters mParentClippingParams = + new ViewClippingUtil.ClippingParameters() { + @Override + public boolean shouldFinish(View view) { + return view.getId() == R.id.status_bar; + } + }; private boolean mAnimationsEnabled = true; Point mPoint; @@ -239,6 +247,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, if (mShown != isShown) { mShown = isShown; if (isShown) { + updateParentClipping(false /* shouldClip */); mHeadsUpStatusBarView.setVisibility(View.VISIBLE); show(mHeadsUpStatusBarView); hide(mClockView, View.INVISIBLE); @@ -256,25 +265,54 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, if (mOperatorNameView != null) { show(mOperatorNameView); } - hide(mHeadsUpStatusBarView, View.GONE); + hide(mHeadsUpStatusBarView, View.GONE, () -> { + updateParentClipping(true /* shouldClip */); + }); } } } + private void updateParentClipping(boolean shouldClip) { + ViewClippingUtil.setClippingDeactivated( + mHeadsUpStatusBarView, !shouldClip, mParentClippingParams); + } + /** * Hides the view and sets the state to endState when finished. * * @param view The view to hide. * @param endState One of {@link View#INVISIBLE} or {@link View#GONE}. + * @see HeadsUpAppearanceController#hide(View, int, Runnable) * @see View#setVisibility(int) * */ private void hide(View view, int endState) { + hide(view, endState, null); + } + + /** + * Hides the view and sets the state to endState when finished. + * + * @param view The view to hide. + * @param endState One of {@link View#INVISIBLE} or {@link View#GONE}. + * @param callback Runnable to be executed after the view has been hidden. + * @see View#setVisibility(int) + * + */ + private void hide(View view, int endState, Runnable callback) { if (mAnimationsEnabled) { CrossFadeHelper.fadeOut(view, CONTENT_FADE_DURATION /* duration */, - 0 /* delay */, () -> view.setVisibility(endState)); + 0 /* delay */, () -> { + view.setVisibility(endState); + if (callback != null) { + callback.run(); + } + }); } else { view.setVisibility(endState); + if (callback != null) { + callback.run(); + } } }