Merge "Animating the qs / notification bounds now when dismissing media" into sc-dev am: 5b4a42f6db am: 3da27148ba

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15105255

Change-Id: I4f1b3eeead0add9396c2fca0fc4ef612a918b675
This commit is contained in:
Selim Cinek
2021-06-29 11:07:37 +00:00
committed by Automerger Merge Worker
10 changed files with 75 additions and 98 deletions

View File

@@ -23,6 +23,8 @@ import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
import com.android.systemui.plugins.qs.QS.HeightListener;
import java.util.function.Consumer;
/**
* Fragment that contains QS in the notification shade. Most of the interface is for
* handling the expand/collapsing of the view interaction.
@@ -33,7 +35,7 @@ public interface QS extends FragmentBase {
String ACTION = "com.android.systemui.action.PLUGIN_QS";
int VERSION = 9;
int VERSION = 10;
String TAG = "QS";
@@ -101,6 +103,11 @@ public interface QS extends FragmentBase {
return true;
}
/**
* Add a listener for when the collapsed media visibility changes.
*/
void setCollapsedMediaVisibilityChangedListener(Consumer<Boolean> listener);
@ProvidesInterface(version = HeightListener.VERSION)
interface HeightListener {
int VERSION = 1;

View File

@@ -28,12 +28,8 @@ import android.view.View;
import android.view.WindowInsets;
import android.widget.FrameLayout;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.systemui.R;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.wm.shell.animation.PhysicsAnimator;
/**
* Wrapper view with background which contains {@link QSPanel} and {@link QuickStatusBarHeader}
@@ -41,26 +37,10 @@ import com.android.wm.shell.animation.PhysicsAnimator;
public class QSContainerImpl extends FrameLayout {
private final Point mSizePoint = new Point();
private static final FloatPropertyCompat<QSContainerImpl> BACKGROUND_BOTTOM =
new FloatPropertyCompat<QSContainerImpl>("backgroundBottom") {
@Override
public float getValue(QSContainerImpl qsImpl) {
return qsImpl.getBackgroundBottom();
}
@Override
public void setValue(QSContainerImpl background, float value) {
background.setBackgroundBottom((int) value);
}
};
private static final PhysicsAnimator.SpringConfig BACKGROUND_SPRING
= new PhysicsAnimator.SpringConfig(SpringForce.STIFFNESS_MEDIUM,
SpringForce.DAMPING_RATIO_LOW_BOUNCY);
private int mFancyClippingTop;
private int mFancyClippingBottom;
private final float[] mFancyClippingRadii = new float[] {0, 0, 0, 0, 0, 0, 0, 0};
private final Path mFancyClippingPath = new Path();
private int mBackgroundBottom = 0;
private int mHeightOverride = -1;
private View mQSDetail;
private QuickStatusBarHeader mHeader;
@@ -71,7 +51,6 @@ public class QSContainerImpl extends FrameLayout {
private int mSideMargins;
private boolean mQsDisabled;
private int mContentPadding = -1;
private boolean mAnimateBottomOnNextLayout;
private int mNavBarInset = 0;
private boolean mClippingEnabled;
@@ -86,11 +65,6 @@ public class QSContainerImpl extends FrameLayout {
mQSDetail = findViewById(R.id.qs_detail);
mHeader = findViewById(R.id.header);
mQSCustomizer = findViewById(R.id.qs_customize);
mHeader.getHeaderQsPanel().setMediaVisibilityChangedListener((visible) -> {
if (mHeader.getHeaderQsPanel().isShown()) {
mAnimateBottomOnNextLayout = true;
}
});
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
}
@@ -99,20 +73,6 @@ public class QSContainerImpl extends FrameLayout {
return false;
}
void onMediaVisibilityChanged(boolean qsVisible) {
mAnimateBottomOnNextLayout = qsVisible;
}
private void setBackgroundBottom(int value) {
// We're saving the bottom separately since otherwise the bottom would be overridden in
// the layout and the animation wouldn't properly start at the old position.
mBackgroundBottom = value;
}
private float getBackgroundBottom() {
return mBackgroundBottom;
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -186,8 +146,7 @@ public class QSContainerImpl extends FrameLayout {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
updateExpansion(mAnimateBottomOnNextLayout /* animate */);
mAnimateBottomOnNextLayout = false;
updateExpansion();
updateClippingPath();
}
@@ -230,31 +189,12 @@ public class QSContainerImpl extends FrameLayout {
}
public void updateExpansion() {
updateExpansion(false /* animate */);
}
public void updateExpansion(boolean animate) {
int height = calculateContainerHeight();
int scrollBottom = calculateContainerBottom();
setBottom(getTop() + height);
mQSDetail.setBottom(getTop() + scrollBottom);
int qsDetailBottomMargin = ((MarginLayoutParams) mQSDetail.getLayoutParams()).bottomMargin;
mQSDetail.setBottom(getTop() + scrollBottom - qsDetailBottomMargin);
updateBackgroundBottom(scrollBottom, animate);
}
private void updateBackgroundBottom(int height, boolean animated) {
PhysicsAnimator<QSContainerImpl> physicsAnimator = PhysicsAnimator.getInstance(this);
if (physicsAnimator.isPropertyAnimating(BACKGROUND_BOTTOM) || animated) {
// An animation is running or we want to animate
// Let's make sure to set the currentValue again, since the call below might only
// start in the next frame and otherwise we'd flicker
BACKGROUND_BOTTOM.setValue(this, BACKGROUND_BOTTOM.getValue(this));
physicsAnimator.spring(BACKGROUND_BOTTOM, height, BACKGROUND_SPRING).start();
} else {
BACKGROUND_BOTTOM.setValue(this, height);
}
}
protected int calculateContainerHeight() {

View File

@@ -61,12 +61,6 @@ public class QSContainerImplController extends ViewController<QSContainerImpl> {
@Override
protected void onViewAttached() {
mView.updateResources(mQsPanelController, mQuickStatusBarHeaderController);
mQsPanelController.setMediaVisibilityChangedListener((visible) -> {
if (mQsPanelController.isShown()) {
mView.onMediaVisibilityChanged(true);
}
});
mConfigurationController.addCallback(mConfigurationListener);
}

View File

@@ -53,6 +53,8 @@ import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.LifecycleFragment;
import com.android.systemui.util.Utils;
import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Named;
@@ -281,6 +283,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
return mLastQSExpansion == 0.0f || mLastQSExpansion == -1;
}
@Override
public void setCollapsedMediaVisibilityChangedListener(Consumer<Boolean> listener) {
mQuickQSPanelController.setMediaVisibilityChangedListener(listener);
}
private void setEditLocation(View view) {
View edit = view.findViewById(android.R.id.edit);
int[] loc = edit.getLocationOnScreen();

View File

@@ -46,7 +46,6 @@ import com.android.systemui.util.animation.UniqueObjectHostView;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/** View that represents the quick settings tile panel (when expanded/pulled down). **/
public class QSPanel extends LinearLayout implements Tunable {
@@ -105,7 +104,6 @@ public class QSPanel extends LinearLayout implements Tunable {
protected QSTileLayout mTileLayout;
private int mLastOrientation = -1;
private int mMediaTotalBottomMargin;
private Consumer<Boolean> mMediaVisibilityChangedListener;
public QSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -148,12 +146,6 @@ public class QSPanel extends LinearLayout implements Tunable {
}
}
protected void onMediaVisibilityChanged(Boolean visible) {
if (mMediaVisibilityChangedListener != null) {
mMediaVisibilityChangedListener.accept(visible);
}
}
/**
* Add brightness view above the tile layout.
*
@@ -667,10 +659,6 @@ public class QSPanel extends LinearLayout implements Tunable {
mHeaderContainer = headerContainer;
}
public void setMediaVisibilityChangedListener(Consumer<Boolean> visibilityChangedListener) {
mMediaVisibilityChangedListener = visibilityChangedListener;
}
public boolean isListening() {
return mListening;
}

View File

@@ -45,8 +45,6 @@ import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Named;
@@ -289,11 +287,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mView.setPageListener(listener);
}
/** */
public void setMediaVisibilityChangedListener(Consumer<Boolean> visibilityChangedListener) {
mView.setMediaVisibilityChangedListener(visibilityChangedListener);
}
public boolean isShown() {
return mView.isShown();
}

View File

@@ -19,6 +19,8 @@ package com.android.systemui.qs;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.res.Configuration;
import android.metrics.LogMaker;
@@ -42,6 +44,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.inject.Named;
@@ -68,6 +71,8 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
private boolean mShouldUseSplitNotificationShade;
@Nullable
private Consumer<Boolean> mMediaVisibilityChangedListener;
private int mLastOrientation;
private String mCachedSpecs = "";
private QSTileRevealController mQsTileRevealController;
@@ -89,7 +94,9 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
};
private final Function1<Boolean, Unit> mMediaHostVisibilityListener = (visible) -> {
mView.onMediaVisibilityChanged(visible);
if (mMediaVisibilityChangedListener != null) {
mMediaVisibilityChangedListener.accept(visible);
}
switchTileLayout(false);
return null;
};
@@ -136,7 +143,6 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
}
mMediaHost.addVisibilityChangeListener(mMediaHostVisibilityListener);
mView.onMediaVisibilityChanged(mMediaHost.getVisible());
mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
mHost.addCallback(mQSHostCallback);
setTiles();
@@ -381,6 +387,13 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
return mView.getTileLayout();
}
/**
* Add a listener for when the media visibility changes.
*/
public void setMediaVisibilityChangedListener(@NonNull Consumer<Boolean> listener) {
mMediaVisibilityChangedListener = listener;
}
/** */
public static final class TileRecord extends QSPanel.Record {
public QSTile tile;

View File

@@ -77,7 +77,6 @@ import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.CommandQueue;
@@ -201,6 +200,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private int mPaddingBetweenElements;
private int mMaxTopPadding;
private int mTopPadding;
private boolean mAnimateNextTopPaddingChange;
private int mBottomMargin;
private int mBottomInset = 0;
private float mQsExpansionFraction;
@@ -1212,16 +1212,18 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
private void setTopPadding(int topPadding, boolean animate) {
if (mTopPadding != topPadding) {
boolean shouldAnimate = animate || mAnimateNextTopPaddingChange;
mTopPadding = topPadding;
updateAlgorithmHeightAndPadding();
updateContentHeight();
if (animate && mAnimationsEnabled && mIsExpanded) {
if (shouldAnimate && mAnimationsEnabled && mIsExpanded) {
mTopPaddingNeedsAnimation = true;
mNeedsAnimation = true;
}
updateStackPosition();
requestChildrenUpdate();
notifyHeightChangeListener(null, animate);
notifyHeightChangeListener(null, shouldAnimate);
mAnimateNextTopPaddingChange = false;
}
}
@@ -5551,6 +5553,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
return mIsExpanded ? mQsScrollBoundaryPosition : 0;
}
/**
* Request an animation whenever the toppadding changes next
*/
public void animateNextTopPaddingChange() {
mAnimateNextTopPaddingChange = true;
}
/**
* A listener that is notified when the empty space below the notifications is clicked on
*/

View File

@@ -1463,6 +1463,13 @@ public class NotificationStackScrollLayoutController {
mView.setRoundedClippingBounds(left, top, right, bottom, topRadius, bottomRadius);
}
/**
* Request an animation whenever the toppadding changes next
*/
public void animateNextTopPaddingChange() {
mView.animateNextTopPaddingChange();
}
/**
* Enum for UiEvent logged from this class
*/

View File

@@ -558,6 +558,11 @@ public class NotificationPanelViewController extends PanelViewController {
*/
private long mNotificationBoundsAnimationDelay;
/**
* The duration of the notification bounds animation
*/
private long mNotificationBoundsAnimationDuration;
/**
* Is this a collapse that started on the panel where we should allow the panel to intercept
*/
@@ -2227,7 +2232,8 @@ public class NotificationPanelViewController extends PanelViewController {
private void onStackYChanged(boolean shouldAnimate) {
if (mQs != null) {
if (shouldAnimate) {
mAnimateNextNotificationBounds = true;
animateNextNotificationBounds(StackStateAnimator.ANIMATION_DURATION_STANDARD,
0 /* delay */);
mNotificationBoundsAnimationDelay = 0;
}
setQSClippingBounds();
@@ -2307,8 +2313,7 @@ public class NotificationPanelViewController extends PanelViewController {
final int startBottom = mKeyguardStatusAreaClipBounds.bottom;
mQsClippingAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
mQsClippingAnimation.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mQsClippingAnimation.setDuration(
StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
mQsClippingAnimation.setDuration(mNotificationBoundsAnimationDuration);
mQsClippingAnimation.setStartDelay(mNotificationBoundsAnimationDelay);
mQsClippingAnimation.addUpdateListener(animation -> {
float fraction = animation.getAnimatedFraction();
@@ -2484,8 +2489,10 @@ public class NotificationPanelViewController extends PanelViewController {
* shade. 0.0f means we're not transitioning yet.
*/
public void setTransitionToFullShadeAmount(float pxAmount, boolean animate, long delay) {
mAnimateNextNotificationBounds = animate && !mShouldUseSplitNotificationShade;
mNotificationBoundsAnimationDelay = delay;
if (animate && !mShouldUseSplitNotificationShade) {
animateNextNotificationBounds(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE,
delay);
}
float endPosition = 0;
if (pxAmount > 0.0f) {
@@ -3484,7 +3491,6 @@ public class NotificationPanelViewController extends PanelViewController {
mQs.setPanelView(mHeightListener);
mQs.setExpandClickListener(mOnClickListener);
mQs.setHeaderClickable(mQsExpansionEnabled);
mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade);
updateQSPulseExpansion();
mQs.setOverscrolling(mStackScrollerOverscrolling);
mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade);
@@ -3498,6 +3504,13 @@ public class NotificationPanelViewController extends PanelViewController {
mHeightListener.onQsHeightChanged();
}
});
mQs.setCollapsedMediaVisibilityChangedListener((visible) -> {
if (mQs.getHeader().isShown()) {
animateNextNotificationBounds(StackStateAnimator.ANIMATION_DURATION_STANDARD,
0 /* delay */);
mNotificationStackScrollLayoutController.animateNextTopPaddingChange();
}
});
mLockscreenShadeTransitionController.setQS(mQs);
mNotificationStackScrollLayoutController.setQsContainer((ViewGroup) mQs.getView());
updateQsExpansion();
@@ -3514,6 +3527,12 @@ public class NotificationPanelViewController extends PanelViewController {
}
};
private void animateNextNotificationBounds(long duration, long delay) {
mAnimateNextNotificationBounds = true;
mNotificationBoundsAnimationDuration = duration;
mNotificationBoundsAnimationDelay = delay;
}
@Override
public void setTouchAndAnimationDisabled(boolean disabled) {
super.setTouchAndAnimationDisabled(disabled);