Made sure that the media section has no background

The background is unnecessary and UX wise doesn't look
good when scrolling. We therefore remove it from
the media header.
Because the screen animation still depends on having the
bounds calculated correctly, we now make all of the
background views ExpandableViews instead of
ActivatableNotificationRows.

Bug: 154137987
Test: add media notification, observe no background, normal screen on / off animation
Change-Id: Ie18af9d61d8d128c7a9397660910403e87c6fd51
This commit is contained in:
Selim Cinek
2020-05-26 15:54:24 -07:00
parent 7f657604e5
commit 4b9710e3c5
10 changed files with 123 additions and 124 deletions

View File

@@ -24,25 +24,4 @@
android:paddingEnd="0dp"
android:focusable="true"
android:clickable="true"
>
<!-- Background views required by ActivatableNotificationView. -->
<com.android.systemui.statusbar.notification.row.NotificationBackgroundView
android:id="@+id/backgroundNormal"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.android.systemui.statusbar.notification.row.NotificationBackgroundView
android:id="@+id/backgroundDimmed"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.android.systemui.statusbar.notification.FakeShadowView
android:id="@+id/fake_shadow"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</com.android.systemui.statusbar.notification.stack.MediaHeaderView>
/>

View File

@@ -123,8 +123,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private float mAppearAnimationFraction = -1.0f;
private float mAppearAnimationTranslation;
private int mNormalColor;
private boolean mLastInSection;
private boolean mFirstInSection;
private boolean mIsBelowSpeedBump;
private float mNormalBackgroundVisibilityAmount;
@@ -430,27 +428,21 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundDimmed.setDistanceToTopRoundness(distanceToTopRoundness);
}
public boolean isLastInSection() {
return mLastInSection;
}
public boolean isFirstInSection() {
return mFirstInSection;
}
/** Sets whether this view is the last notification in a section. */
@Override
public void setLastInSection(boolean lastInSection) {
if (lastInSection != mLastInSection) {
mLastInSection = lastInSection;
super.setLastInSection(lastInSection);
mBackgroundNormal.setLastInSection(lastInSection);
mBackgroundDimmed.setLastInSection(lastInSection);
}
}
/** Sets whether this view is the first notification in a section. */
@Override
public void setFirstInSection(boolean firstInSection) {
if (firstInSection != mFirstInSection) {
mFirstInSection = firstInSection;
super.setFirstInSection(firstInSection);
mBackgroundNormal.setFirstInSection(firstInSection);
mBackgroundDimmed.setFirstInSection(firstInSection);
}
@@ -963,6 +955,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
return false;
}
@Override
public int getHeadsUpHeightWithoutHeader() {
return getHeight();
}

View File

@@ -262,10 +262,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
setClipToOutline(mAlwaysRoundBothCorners);
}
/**
* Set the topRoundness of this view.
* @return Whether the roundness was changed.
*/
@Override
public boolean setTopRoundness(float topRoundness, boolean animate) {
if (mTopRoundness != topRoundness) {
mTopRoundness = topRoundness;
@@ -302,10 +299,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
return mCurrentBottomRoundness * mOutlineRadius;
}
/**
* Set the bottom roundness of this view.
* @return Whether the roundness was changed.
*/
@Override
public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
if (mBottomRoundness != bottomRoundness) {
mBottomRoundness = bottomRoundness;

View File

@@ -67,6 +67,8 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
protected int mContentShift;
private final ExpandableViewState mViewState;
private float mContentTranslation;
protected boolean mLastInSection;
protected boolean mFirstInSection;
public ExpandableView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -771,6 +773,44 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
return true;
}
/** Sets whether this view is the first notification in a section. */
public void setFirstInSection(boolean firstInSection) {
mFirstInSection = firstInSection;
}
/** Sets whether this view is the last notification in a section. */
public void setLastInSection(boolean lastInSection) {
mLastInSection = lastInSection;
}
public boolean isLastInSection() {
return mLastInSection;
}
public boolean isFirstInSection() {
return mFirstInSection;
}
/**
* Set the topRoundness of this view.
* @return Whether the roundness was changed.
*/
public boolean setTopRoundness(float topRoundness, boolean animate) {
return false;
}
/**
* Set the bottom roundness of this view.
* @return Whether the roundness was changed.
*/
public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
return false;
}
public int getHeadsUpHeightWithoutHeader() {
return getHeight();
}
/**
* A listener notifying when {@link #getActualHeight} changes.
*/

View File

@@ -64,7 +64,7 @@ public class AmbientState {
private int mZDistanceBetweenElements;
private int mBaseZHeight;
private int mMaxLayoutHeight;
private ActivatableNotificationView mLastVisibleBackgroundChild;
private ExpandableView mLastVisibleBackgroundChild;
private float mCurrentScrollVelocity;
private int mStatusBarState;
private float mExpandingVelocity;
@@ -346,11 +346,11 @@ public class AmbientState {
* view in the shade, without the clear all button.
*/
public void setLastVisibleBackgroundChild(
ActivatableNotificationView lastVisibleBackgroundChild) {
ExpandableView lastVisibleBackgroundChild) {
mLastVisibleBackgroundChild = lastVisibleBackgroundChild;
}
public ActivatableNotificationView getLastVisibleBackgroundChild() {
public ExpandableView getLastVisibleBackgroundChild() {
return mLastVisibleBackgroundChild;
}

View File

@@ -16,45 +16,35 @@
package com.android.systemui.statusbar.notification.stack;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableView;
/**
* Root view to insert Lock screen media controls into the notification stack.
*/
public class MediaHeaderView extends ActivatableNotificationView {
private View mContentView;
public class MediaHeaderView extends ExpandableView {
public MediaHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
public long performRemoveAnimation(long duration, long delay, float translationDirection,
boolean isHeadsUpAnimation, float endLocation, Runnable onFinishedRunnable,
AnimatorListenerAdapter animationListener) {
return 0;
}
@Override
protected View getContentView() {
return mContentView;
}
/**
* Sets the background color, to be used when album art changes.
* @param color background
*/
public void setBackgroundColor(int color) {
setTintColor(color);
public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
// No animation, it doesn't need it, this would be local
}
public void setContentView(ViewGroup contentView) {
mContentView = contentView;
addView(contentView);
ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;

View File

@@ -20,7 +20,6 @@ import android.util.MathUtils;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -37,10 +36,10 @@ import javax.inject.Singleton;
@Singleton
public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
private final ActivatableNotificationView[] mFirstInSectionViews;
private final ActivatableNotificationView[] mLastInSectionViews;
private final ActivatableNotificationView[] mTmpFirstInSectionViews;
private final ActivatableNotificationView[] mTmpLastInSectionViews;
private final ExpandableView[] mFirstInSectionViews;
private final ExpandableView[] mLastInSectionViews;
private final ExpandableView[] mTmpFirstInSectionViews;
private final ExpandableView[] mTmpLastInSectionViews;
private final KeyguardBypassController mBypassController;
private boolean mExpanded;
private HashSet<ExpandableView> mAnimatedChildren;
@@ -53,10 +52,10 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
KeyguardBypassController keyguardBypassController,
NotificationSectionsFeatureManager sectionsFeatureManager) {
int numberOfSections = sectionsFeatureManager.getNumberOfBuckets();
mFirstInSectionViews = new ActivatableNotificationView[numberOfSections];
mLastInSectionViews = new ActivatableNotificationView[numberOfSections];
mTmpFirstInSectionViews = new ActivatableNotificationView[numberOfSections];
mTmpLastInSectionViews = new ActivatableNotificationView[numberOfSections];
mFirstInSectionViews = new ExpandableView[numberOfSections];
mLastInSectionViews = new ExpandableView[numberOfSections];
mTmpFirstInSectionViews = new ExpandableView[numberOfSections];
mTmpLastInSectionViews = new ExpandableView[numberOfSections];
mBypassController = keyguardBypassController;
}
@@ -80,14 +79,14 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
updateView(entry.getRow(), false /* animate */);
}
private void updateView(ActivatableNotificationView view, boolean animate) {
private void updateView(ExpandableView view, boolean animate) {
boolean changed = updateViewWithoutCallback(view, animate);
if (changed) {
mRoundingChangedCallback.run();
}
}
private boolean updateViewWithoutCallback(ActivatableNotificationView view,
private boolean updateViewWithoutCallback(ExpandableView view,
boolean animate) {
float topRoundness = getRoundness(view, true /* top */);
float bottomRoundness = getRoundness(view, false /* top */);
@@ -100,8 +99,7 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
return (firstInSection || lastInSection) && (topChanged || bottomChanged);
}
private boolean isFirstInSection(ActivatableNotificationView view,
boolean includeFirstSection) {
private boolean isFirstInSection(ExpandableView view, boolean includeFirstSection) {
int numNonEmptySections = 0;
for (int i = 0; i < mFirstInSectionViews.length; i++) {
if (view == mFirstInSectionViews[i]) {
@@ -114,7 +112,7 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
return false;
}
private boolean isLastInSection(ActivatableNotificationView view, boolean includeLastSection) {
private boolean isLastInSection(ExpandableView view, boolean includeLastSection) {
int numNonEmptySections = 0;
for (int i = mLastInSectionViews.length - 1; i >= 0; i--) {
if (view == mLastInSectionViews[i]) {
@@ -127,7 +125,7 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
return false;
}
private float getRoundness(ActivatableNotificationView view, boolean top) {
private float getRoundness(ExpandableView view, boolean top) {
if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) {
return 1.0f;
}
@@ -174,14 +172,14 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
}
private boolean handleRemovedOldViews(NotificationSection[] sections,
ActivatableNotificationView[] oldViews, boolean first) {
ExpandableView[] oldViews, boolean first) {
boolean anyChanged = false;
for (ActivatableNotificationView oldView : oldViews) {
for (ExpandableView oldView : oldViews) {
if (oldView != null) {
boolean isStillPresent = false;
boolean adjacentSectionChanged = false;
for (NotificationSection section : sections) {
ActivatableNotificationView newView =
ExpandableView newView =
(first ? section.getFirstVisibleChild()
: section.getLastVisibleChild());
if (newView == oldView) {
@@ -207,14 +205,14 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
}
private boolean handleAddedNewViews(NotificationSection[] sections,
ActivatableNotificationView[] oldViews, boolean first) {
ExpandableView[] oldViews, boolean first) {
boolean anyChanged = false;
for (NotificationSection section : sections) {
ActivatableNotificationView newView =
ExpandableView newView =
(first ? section.getFirstVisibleChild() : section.getLastVisibleChild());
if (newView != null) {
boolean wasAlreadyPresent = false;
for (ActivatableNotificationView oldView : oldViews) {
for (ExpandableView oldView : oldViews) {
if (oldView == newView) {
wasAlreadyPresent = true;
break;

View File

@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.stack;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -26,7 +28,7 @@ import android.view.animation.Interpolator;
import com.android.systemui.Interpolators;
import com.android.systemui.statusbar.notification.ShadeViewRefactor;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableView;
/**
* Represents the bounds of a section of the notification shade and handles animation when the
@@ -41,8 +43,8 @@ public class NotificationSection {
private Rect mEndAnimationRect = new Rect();
private ObjectAnimator mTopAnimator = null;
private ObjectAnimator mBottomAnimator = null;
private ActivatableNotificationView mFirstVisibleChild;
private ActivatableNotificationView mLastVisibleChild;
private ExpandableView mFirstVisibleChild;
private ExpandableView mLastVisibleChild;
NotificationSection(View owningView, @PriorityBucket int bucket) {
mOwningView = owningView;
@@ -198,21 +200,21 @@ public class NotificationSection {
mOwningView.invalidate();
}
public ActivatableNotificationView getFirstVisibleChild() {
public ExpandableView getFirstVisibleChild() {
return mFirstVisibleChild;
}
public ActivatableNotificationView getLastVisibleChild() {
public ExpandableView getLastVisibleChild() {
return mLastVisibleChild;
}
public boolean setFirstVisibleChild(ActivatableNotificationView child) {
public boolean setFirstVisibleChild(ExpandableView child) {
boolean changed = mFirstVisibleChild != child;
mFirstVisibleChild = child;
return changed;
}
public boolean setLastVisibleChild(ActivatableNotificationView child) {
public boolean setLastVisibleChild(ExpandableView child) {
boolean changed = mLastVisibleChild != child;
mLastVisibleChild = child;
return changed;
@@ -251,7 +253,7 @@ public class NotificationSection {
boolean shiftBackgroundWithFirst) {
int top = minTopPosition;
int bottom = minTopPosition;
ActivatableNotificationView firstView = getFirstVisibleChild();
ExpandableView firstView = getFirstVisibleChild();
if (firstView != null) {
// Round Y up to avoid seeing the background during animation
int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView));
@@ -276,7 +278,7 @@ public class NotificationSection {
}
}
top = Math.max(minTopPosition, top);
ActivatableNotificationView lastView = getLastVisibleChild();
ExpandableView lastView = getLastVisibleChild();
if (lastView != null) {
float finalTranslationY = ViewState.getFinalTranslationY(lastView);
int finalHeight = ExpandableViewState.getFinalActualHeight(lastView);
@@ -302,4 +304,8 @@ public class NotificationSection {
mBounds.bottom = bottom;
return bottom;
}
public boolean needsBackground() {
return mFirstVisibleChild != null && mBucket != BUCKET_MEDIA_CONTROLS;
}
}

View File

@@ -35,7 +35,6 @@ import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter
import com.android.systemui.statusbar.notification.people.PeopleHubViewBoundary
import com.android.systemui.statusbar.notification.people.PersonViewModel
import com.android.systemui.statusbar.notification.people.Subscription
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView
@@ -456,14 +455,14 @@ class NotificationSectionsManager @Inject internal constructor(
private sealed class SectionBounds {
data class Many(
val first: ActivatableNotificationView,
val last: ActivatableNotificationView
val first: ExpandableView,
val last: ExpandableView
) : SectionBounds()
data class One(val lone: ActivatableNotificationView) : SectionBounds()
data class One(val lone: ExpandableView) : SectionBounds()
object None : SectionBounds()
fun addNotif(notif: ActivatableNotificationView): SectionBounds = when (this) {
fun addNotif(notif: ExpandableView): SectionBounds = when (this) {
is None -> One(notif)
is One -> Many(lone, notif)
is Many -> copy(last = notif)
@@ -476,8 +475,8 @@ class NotificationSectionsManager @Inject internal constructor(
}
private fun NotificationSection.setFirstAndLastVisibleChildren(
first: ActivatableNotificationView?,
last: ActivatableNotificationView?
first: ExpandableView?,
last: ExpandableView?
): Boolean {
val firstChanged = setFirstVisibleChild(first)
val lastChanged = setLastVisibleChild(last)
@@ -492,7 +491,7 @@ class NotificationSectionsManager @Inject internal constructor(
*/
fun updateFirstAndLastViewsForAllSections(
sections: Array<NotificationSection>,
children: List<ActivatableNotificationView>
children: List<ExpandableView>
): Boolean {
// Create mapping of bucket to section
val sectionBounds = children.asSequence()

View File

@@ -701,7 +701,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
* @return the height at which we will wake up when pulsing
*/
public float getWakeUpHeight() {
ActivatableNotificationView firstChild = getFirstChildWithBackground();
ExpandableView firstChild = getFirstChildWithBackground();
if (firstChild != null) {
if (mKeyguardBypassController.getBypassEnabled()) {
return firstChild.getHeadsUpHeightWithoutHeader();
@@ -907,7 +907,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
// TODO(kprevas): this may not be necessary any more since we don't display the shelf in AOD
boolean anySectionHasVisibleChild = false;
for (NotificationSection section : mSections) {
if (section.getFirstVisibleChild() != null) {
if (section.needsBackground()) {
anySectionHasVisibleChild = true;
break;
}
@@ -950,7 +950,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
int currentRight = right;
boolean first = true;
for (NotificationSection section : mSections) {
if (section.getFirstVisibleChild() == null) {
if (!section.needsBackground()) {
continue;
}
int sectionTop = section.getCurrentBounds().top + animationYOffset;
@@ -2685,40 +2685,40 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private ActivatableNotificationView getLastChildWithBackground() {
private ExpandableView getLastChildWithBackground() {
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
View child = getChildAt(i);
if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
ExpandableView child = (ExpandableView) getChildAt(i);
if (child.getVisibility() != View.GONE && !(child instanceof StackScrollerDecorView)
&& child != mShelf) {
return (ActivatableNotificationView) child;
return child;
}
}
return null;
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private ActivatableNotificationView getFirstChildWithBackground() {
private ExpandableView getFirstChildWithBackground() {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
ExpandableView child = (ExpandableView) getChildAt(i);
if (child.getVisibility() != View.GONE && !(child instanceof StackScrollerDecorView)
&& child != mShelf) {
return (ActivatableNotificationView) child;
return child;
}
}
return null;
}
//TODO: We shouldn't have to generate this list every time
private List<ActivatableNotificationView> getChildrenWithBackground() {
ArrayList<ActivatableNotificationView> children = new ArrayList<>();
private List<ExpandableView> getChildrenWithBackground() {
ArrayList<ExpandableView> children = new ArrayList<>();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
ExpandableView child = (ExpandableView) getChildAt(i);
if (child.getVisibility() != View.GONE && !(child instanceof StackScrollerDecorView)
&& child != mShelf) {
children.add((ActivatableNotificationView) child);
children.add(child);
}
}
@@ -3283,13 +3283,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private void updateFirstAndLastBackgroundViews() {
NotificationSection firstSection = getFirstVisibleSection();
NotificationSection lastSection = getLastVisibleSection();
ActivatableNotificationView previousFirstChild =
ExpandableView previousFirstChild =
firstSection == null ? null : firstSection.getFirstVisibleChild();
ActivatableNotificationView previousLastChild =
ExpandableView previousLastChild =
lastSection == null ? null : lastSection.getLastVisibleChild();
ActivatableNotificationView firstChild = getFirstChildWithBackground();
ActivatableNotificationView lastChild = getLastChildWithBackground();
ExpandableView firstChild = getFirstChildWithBackground();
ExpandableView lastChild = getLastChildWithBackground();
boolean sectionViewsChanged = mSectionsManager.updateFirstAndLastViewsForAllSections(
mSections, getChildrenWithBackground());
@@ -4575,7 +4575,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
? (ExpandableNotificationRow) view
: null;
NotificationSection firstSection = getFirstVisibleSection();
ActivatableNotificationView firstVisibleChild =
ExpandableView firstVisibleChild =
firstSection == null ? null : firstSection.getFirstVisibleChild();
if (row != null) {
if (row == firstVisibleChild
@@ -4611,7 +4611,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
int layoutEnd = mMaxLayoutHeight + (int) mStackTranslation;
NotificationSection lastSection = getLastVisibleSection();
ActivatableNotificationView lastVisibleChild =
ExpandableView lastVisibleChild =
lastSection == null ? null : lastSection.getLastVisibleChild();
if (row != lastVisibleChild && mShelf.getVisibility() != GONE) {
layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements;