Improved the clipping of notification groups
Groups now correctly respect the clipBottomAmount and animations work much better when swiping things away. Also removed the group measuring logic when expanding, Since we're now not shrinking the first notification anymore! This also fixed a bug where a child could be invisible Test: Add group, swipe children away Bug: 32437839 Bug: 33203156 Change-Id: I255aa9695086e64eb10c7dccdc6122d8a8572bb5
This commit is contained in:
@@ -1685,6 +1685,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
if (mGuts != null) {
|
||||
mGuts.setClipBottomAmount(clipBottomAmount);
|
||||
}
|
||||
if (mChildrenContainer != null) {
|
||||
mChildrenContainer.setClipBottomAmount(clipBottomAmount);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMaxExpandHeightInitialized() {
|
||||
@@ -1863,9 +1866,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
super.applyToView(view);
|
||||
if (view instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
|
||||
if (this.isBottomClipped) {
|
||||
row.setClipToActualHeight(true);
|
||||
}
|
||||
row.applyChildrenState(mOverallState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
outline.setRect(translation,
|
||||
mClipTopAmount,
|
||||
getWidth() + translation,
|
||||
Math.max(getActualHeight(), mClipTopAmount));
|
||||
Math.max(getActualHeight() - mClipBottomAmount, mClipTopAmount));
|
||||
} else {
|
||||
outline.setRect(mOutlineRect);
|
||||
}
|
||||
@@ -66,6 +66,12 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
invalidateOutline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClipBottomAmount(int clipBottomAmount) {
|
||||
super.setClipBottomAmount(clipBottomAmount);
|
||||
invalidateOutline();
|
||||
}
|
||||
|
||||
protected void setOutlineAlpha(float alpha) {
|
||||
if (alpha != mOutlineAlpha) {
|
||||
mOutlineAlpha = alpha;
|
||||
|
||||
@@ -38,7 +38,7 @@ public abstract class ExpandableView extends FrameLayout {
|
||||
protected OnHeightChangedListener mOnHeightChangedListener;
|
||||
private int mActualHeight;
|
||||
protected int mClipTopAmount;
|
||||
private float mClipBottomAmount;
|
||||
protected int mClipBottomAmount;
|
||||
private boolean mDark;
|
||||
private ArrayList<View> mMatchParentViews = new ArrayList<View>();
|
||||
private static Rect mClipRect = new Rect();
|
||||
@@ -241,7 +241,7 @@ public abstract class ExpandableView extends FrameLayout {
|
||||
return mClipTopAmount;
|
||||
}
|
||||
|
||||
public float getClipBottomAmount() {
|
||||
public int getClipBottomAmount() {
|
||||
return mClipBottomAmount;
|
||||
}
|
||||
|
||||
@@ -354,11 +354,8 @@ public abstract class ExpandableView extends FrameLayout {
|
||||
private void updateClipping() {
|
||||
if (mClipToActualHeight) {
|
||||
int top = getClipTopAmount();
|
||||
if (top >= getActualHeight()) {
|
||||
top = getActualHeight() - 1;
|
||||
}
|
||||
mClipRect.set(0, top, getWidth(), (int) (getActualHeight() + getExtraBottomPadding()
|
||||
- mClipBottomAmount));
|
||||
mClipRect.set(0, top, getWidth(), Math.max(getActualHeight() + getExtraBottomPadding()
|
||||
- mClipBottomAmount, top));
|
||||
setClipBounds(mClipRect);
|
||||
} else {
|
||||
setClipBounds(null);
|
||||
|
||||
@@ -156,7 +156,6 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
mShelfState.alpha = 1.0f;
|
||||
mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
|
||||
mShelfState.shadowAlpha = 1.0f;
|
||||
mShelfState.isBottomClipped = false;
|
||||
mShelfState.hideSensitive = false;
|
||||
mShelfState.xTranslation = getTranslationX();
|
||||
if (mNotGoneIndex != -1) {
|
||||
|
||||
@@ -48,7 +48,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
return mAnimationFilter;
|
||||
}
|
||||
}.setDuration(200);
|
||||
|
||||
|
||||
private static final AnimationProperties ADD_ICON_PROPERTIES = new AnimationProperties() {
|
||||
private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
|
||||
|
||||
|
||||
@@ -106,11 +106,6 @@ public class ExpandableViewState extends ViewState {
|
||||
*/
|
||||
public int location;
|
||||
|
||||
/**
|
||||
* Whether a child in a group is being clipped at the bottom.
|
||||
*/
|
||||
public boolean isBottomClipped;
|
||||
|
||||
@Override
|
||||
public void copyFrom(ViewState viewState) {
|
||||
super.copyFrom(viewState);
|
||||
@@ -125,7 +120,6 @@ public class ExpandableViewState extends ViewState {
|
||||
clipTopAmount = svs.clipTopAmount;
|
||||
notGoneIndex = svs.notGoneIndex;
|
||||
location = svs.location;
|
||||
isBottomClipped = svs.isBottomClipped;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
private NotificationViewWrapper mNotificationHeaderWrapper;
|
||||
private NotificationHeaderUtil mHeaderUtil;
|
||||
private ViewState mHeaderViewState;
|
||||
private int mClipBottomAmount;
|
||||
|
||||
public NotificationChildrenContainer(Context context) {
|
||||
this(context, null);
|
||||
@@ -433,7 +434,6 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
|
||||
boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging()
|
||||
&& mChildrenExpanded;
|
||||
int parentHeight = parentState.height;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
ExpandableNotificationRow child = mChildren.get(i);
|
||||
if (!firstChild) {
|
||||
@@ -457,20 +457,9 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
|
||||
ExpandableViewState childState = resultState.getViewStateForView(child);
|
||||
int intrinsicHeight = child.getIntrinsicHeight();
|
||||
if (childrenExpanded) {
|
||||
// When a group is expanded and moving into bottom stack, the bottom visible child
|
||||
// adjusts its height to move into it. Children after it are hidden.
|
||||
if (updateChildStateForExpandedGroup(child, parentHeight, childState, yPosition)) {
|
||||
// Clipping might be deactivated if the view is transforming, however, clipping
|
||||
// the child into the bottom stack should take precedent over this.
|
||||
childState.isBottomClipped = true;
|
||||
}
|
||||
} else {
|
||||
childState.hidden = false;
|
||||
childState.height = intrinsicHeight;
|
||||
childState.isBottomClipped = false;
|
||||
}
|
||||
childState.height = intrinsicHeight;
|
||||
childState.yTranslation = yPosition;
|
||||
childState.hidden = false;
|
||||
// When the group is expanded, the children cast the shadows rather than the parent
|
||||
// so use the parent's elevation here.
|
||||
childState.zTranslation = childrenExpanded
|
||||
@@ -601,6 +590,34 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
if (mHeaderViewState != null) {
|
||||
mHeaderViewState.applyToView(mNotificationHeader);
|
||||
}
|
||||
updateChildrenClipping();
|
||||
}
|
||||
|
||||
private void updateChildrenClipping() {
|
||||
int childCount = mChildren.size();
|
||||
int layoutEnd = mNotificationParent.getActualHeight() - mClipBottomAmount;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
ExpandableNotificationRow child = mChildren.get(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
float childTop = child.getTranslationY();
|
||||
float childBottom = childTop + child.getActualHeight();
|
||||
boolean visible = true;
|
||||
int clipBottomAmount = 0;
|
||||
if (childTop > layoutEnd) {
|
||||
visible = false;
|
||||
} else if (childBottom > layoutEnd) {
|
||||
clipBottomAmount = (int) (childBottom - layoutEnd);
|
||||
}
|
||||
|
||||
boolean isVisible = child.getVisibility() == VISIBLE;
|
||||
if (visible != isVisible) {
|
||||
child.setVisibility(visible ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
child.setClipBottomAmount(clipBottomAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -653,6 +670,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
if (mNotificationHeader != null) {
|
||||
mHeaderViewState.applyToView(mNotificationHeader);
|
||||
}
|
||||
updateChildrenClipping();
|
||||
}
|
||||
|
||||
public ExpandableNotificationRow getViewAtPosition(float y) {
|
||||
@@ -889,4 +907,9 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setClipBottomAmount(int clipBottomAmount) {
|
||||
mClipBottomAmount = clipBottomAmount;
|
||||
updateChildrenClipping();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,12 +766,14 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
*/
|
||||
private float getAppearEndPosition() {
|
||||
int appearPosition;
|
||||
int minNotificationsForShelf = 1;
|
||||
if (mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) {
|
||||
appearPosition = mHeadsUpManager.getTopHeadsUpPinnedHeight();
|
||||
minNotificationsForShelf = 2;
|
||||
} else {
|
||||
appearPosition = getFirstItemMinHeight();
|
||||
appearPosition = 0;
|
||||
}
|
||||
if (getNotGoneChildCount() > 1) {
|
||||
if (getNotGoneChildCount() >= minNotificationsForShelf) {
|
||||
appearPosition += mShelf.getIntrinsicHeight();
|
||||
}
|
||||
return appearPosition + (onKeyguard() ? mTopPadding : mIntrinsicPadding);
|
||||
@@ -1092,29 +1094,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
|
||||
@Override
|
||||
public int getMaxExpandHeight(ExpandableView view) {
|
||||
int maxContentHeight = view.getMaxContentHeight();
|
||||
if (view.isSummaryWithChildren() && view.getParent() == this) {
|
||||
// Faking a measure with the group expanded to simulate how the group would look if
|
||||
// it was. Doing a calculation here would be highly non-trivial because of the
|
||||
// algorithm
|
||||
mGroupExpandedForMeasure = true;
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
|
||||
mGroupManager.toggleGroupExpansion(row.getStatusBarNotification());
|
||||
row.setForceUnlocked(true);
|
||||
mAmbientState.setLayoutHeight(mMaxLayoutHeight);
|
||||
mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState);
|
||||
mAmbientState.setLayoutHeight(getLayoutHeight());
|
||||
mGroupManager.toggleGroupExpansion(
|
||||
row.getStatusBarNotification());
|
||||
mGroupExpandedForMeasure = false;
|
||||
row.setForceUnlocked(false);
|
||||
ExpandableViewState viewState = mCurrentStackScrollState.getViewStateForView(view);
|
||||
if (viewState != null) {
|
||||
// The view could have been removed
|
||||
return Math.min(viewState.height, maxContentHeight);
|
||||
}
|
||||
}
|
||||
return maxContentHeight;
|
||||
return view.getMaxContentHeight();
|
||||
}
|
||||
|
||||
public void setScrollingEnabled(boolean enable) {
|
||||
|
||||
@@ -323,9 +323,6 @@ public class StackScrollAlgorithm {
|
||||
int childHeight = getMaxAllowedChildHeight(child);
|
||||
childViewState.yTranslation = currentYPosition;
|
||||
boolean isDismissView = child instanceof DismissView;
|
||||
if (i == 0) {
|
||||
updateFirstChildHeight(child, childViewState, childHeight, algorithmState, ambientState);
|
||||
}
|
||||
|
||||
childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
|
||||
if (isDismissView) {
|
||||
@@ -449,29 +446,6 @@ public class StackScrollAlgorithm {
|
||||
return child == null? mCollapsedSize : child.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the height of the first child i.e clamp it to the bottom stack
|
||||
* @param child the child to update
|
||||
* @param childViewState the viewstate of the child
|
||||
* @param childHeight the height of the child
|
||||
* @param algorithmState the algorithm state
|
||||
* @param ambientState The ambient state of the algorithm
|
||||
*/
|
||||
protected void updateFirstChildHeight(ExpandableView child, ExpandableViewState childViewState,
|
||||
int childHeight, StackScrollAlgorithmState algorithmState,
|
||||
AmbientState ambientState) {
|
||||
|
||||
int bottomStart= ambientState.getInnerHeight();
|
||||
if (algorithmState.visibleChildren.size() > 1) {
|
||||
bottomStart -= ambientState.getShelf().getIntrinsicHeight()
|
||||
- mPaddingBetweenElements;
|
||||
}
|
||||
bottomStart += ambientState.getScrollY();
|
||||
// Collapse and expand the first child while the shade is being expanded
|
||||
childViewState.height = (int) Math.max(Math.min(bottomStart, (float) childHeight),
|
||||
child.getCollapsedHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the Z positions for all children based on the number of items in both stacks and
|
||||
* save it in the resultState
|
||||
|
||||
Reference in New Issue
Block a user