Merge "Modified the way the notifications clip to the boundary" into sc-v2-dev
This commit is contained in:
@@ -330,30 +330,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDistanceToTopRoundness(float distanceToTopRoundness) {
|
|
||||||
super.setDistanceToTopRoundness(distanceToTopRoundness);
|
|
||||||
mBackgroundNormal.setDistanceToTopRoundness(distanceToTopRoundness);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets whether this view is the last notification in a section. */
|
|
||||||
@Override
|
|
||||||
public void setLastInSection(boolean lastInSection) {
|
|
||||||
if (lastInSection != mLastInSection) {
|
|
||||||
super.setLastInSection(lastInSection);
|
|
||||||
mBackgroundNormal.setLastInSection(lastInSection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets whether this view is the first notification in a section. */
|
|
||||||
@Override
|
|
||||||
public void setFirstInSection(boolean firstInSection) {
|
|
||||||
if (firstInSection != mFirstInSection) {
|
|
||||||
super.setFirstInSection(firstInSection);
|
|
||||||
mBackgroundNormal.setFirstInSection(firstInSection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an override tint color that is used for the background.
|
* Set an override tint color that is used for the background.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -846,8 +846,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
updateClickAndFocus();
|
updateClickAndFocus();
|
||||||
if (mNotificationParent != null) {
|
if (mNotificationParent != null) {
|
||||||
setOverrideTintColor(NO_COLOR, 0.0f);
|
setOverrideTintColor(NO_COLOR, 0.0f);
|
||||||
// Let's reset the distance to top roundness, as this isn't applied to group children
|
|
||||||
setDistanceToTopRoundness(NO_ROUNDNESS);
|
|
||||||
mNotificationParent.updateBackgroundForGroupState();
|
mNotificationParent.updateBackgroundForGroupState();
|
||||||
}
|
}
|
||||||
updateBackgroundClipping();
|
updateBackgroundClipping();
|
||||||
@@ -3036,24 +3034,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
|| mExpandAnimationRunning || mChildIsExpanding));
|
|| mExpandAnimationRunning || mChildIsExpanding));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean topAmountNeedsClipping() {
|
|
||||||
if (isGroupExpanded()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (isGroupExpansionChanging()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (getShowingLayout().shouldClipToRounding(true /* topRounded */,
|
|
||||||
false /* bottomRounded */)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (mGuts != null && mGuts.getAlpha() != 0.0f) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean childNeedsClipping(View child) {
|
protected boolean childNeedsClipping(View child) {
|
||||||
if (child instanceof NotificationContentView) {
|
if (child instanceof NotificationContentView) {
|
||||||
|
|||||||
@@ -75,16 +75,13 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
|||||||
* it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
|
* it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
|
||||||
*/
|
*/
|
||||||
protected boolean mShouldTranslateContents;
|
protected boolean mShouldTranslateContents;
|
||||||
private boolean mTopAmountRounded;
|
|
||||||
private float mDistanceToTopRoundness = -1;
|
|
||||||
private float[] mTmpCornerRadii = new float[8];
|
private float[] mTmpCornerRadii = new float[8];
|
||||||
|
|
||||||
private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
|
private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void getOutline(View view, Outline outline) {
|
public void getOutline(View view, Outline outline) {
|
||||||
if (!mCustomOutline && getCurrentTopRoundness() == 0.0f
|
if (!mCustomOutline && getCurrentTopRoundness() == 0.0f
|
||||||
&& getCurrentBottomRoundness() == 0.0f && !mAlwaysRoundBothCorners
|
&& getCurrentBottomRoundness() == 0.0f && !mAlwaysRoundBothCorners) {
|
||||||
&& !mTopAmountRounded) {
|
|
||||||
int translation = mShouldTranslateContents ? (int) getTranslation() : 0;
|
int translation = mShouldTranslateContents ? (int) getTranslation() : 0;
|
||||||
int left = Math.max(translation, 0);
|
int left = Math.max(translation, 0);
|
||||||
int top = mClipTopAmount + mBackgroundTop;
|
int top = mClipTopAmount + mBackgroundTop;
|
||||||
@@ -168,33 +165,15 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
Path intersectPath = null;
|
|
||||||
if (mTopAmountRounded && topAmountNeedsClipping()) {
|
|
||||||
int left = (int) (- mExtraWidthForClipping / 2.0f);
|
|
||||||
int top = (int) (mClipTopAmount - mDistanceToTopRoundness);
|
|
||||||
int right = getWidth() + (int) (mExtraWidthForClipping + left);
|
|
||||||
int bottom = (int) Math.max(mMinimumHeightForClipping,
|
|
||||||
Math.max(getActualHeight() - mClipBottomAmount, top + mOutlineRadius));
|
|
||||||
getRoundedRectPath(left, top, right, bottom, mOutlineRadius, 0.0f, mClipPath);
|
|
||||||
intersectPath = mClipPath;
|
|
||||||
}
|
|
||||||
boolean clipped = false;
|
|
||||||
if (childNeedsClipping(child)) {
|
if (childNeedsClipping(child)) {
|
||||||
Path clipPath = getCustomClipPath(child);
|
Path clipPath = getCustomClipPath(child);
|
||||||
if (clipPath == null) {
|
if (clipPath == null) {
|
||||||
clipPath = getClipPath(false /* ignoreTranslation */);
|
clipPath = getClipPath(false /* ignoreTranslation */);
|
||||||
}
|
}
|
||||||
if (clipPath != null) {
|
if (clipPath != null) {
|
||||||
if (intersectPath != null) {
|
|
||||||
clipPath.op(intersectPath, Path.Op.INTERSECT);
|
|
||||||
}
|
|
||||||
canvas.clipPath(clipPath);
|
canvas.clipPath(clipPath);
|
||||||
clipped = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!clipped && intersectPath != null) {
|
|
||||||
canvas.clipPath(intersectPath);
|
|
||||||
}
|
|
||||||
boolean result = super.drawChild(canvas, child, drawingTime);
|
boolean result = super.drawChild(canvas, child, drawingTime);
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
return result;
|
return result;
|
||||||
@@ -212,24 +191,10 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDistanceToTopRoundness(float distanceToTopRoundness) {
|
|
||||||
super.setDistanceToTopRoundness(distanceToTopRoundness);
|
|
||||||
if (distanceToTopRoundness != mDistanceToTopRoundness) {
|
|
||||||
mTopAmountRounded = distanceToTopRoundness >= 0;
|
|
||||||
mDistanceToTopRoundness = distanceToTopRoundness;
|
|
||||||
applyRoundness();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean childNeedsClipping(View child) {
|
protected boolean childNeedsClipping(View child) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean topAmountNeedsClipping() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isClippingNeeded() {
|
protected boolean isClippingNeeded() {
|
||||||
return mAlwaysRoundBothCorners || mCustomOutline || getTranslation() != 0 ;
|
return mAlwaysRoundBothCorners || mCustomOutline || getTranslation() != 0 ;
|
||||||
}
|
}
|
||||||
@@ -272,11 +237,6 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public float getCurrentBackgroundRadiusTop() {
|
public float getCurrentBackgroundRadiusTop() {
|
||||||
// If this view is top amount notification view, it should always has round corners on top.
|
|
||||||
// It will be applied with applyRoundness()
|
|
||||||
if (mTopAmountRounded) {
|
|
||||||
return mOutlineRadius;
|
|
||||||
}
|
|
||||||
return getCurrentTopRoundness() * mOutlineRadius;
|
return getCurrentTopRoundness() * mOutlineRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ import java.util.List;
|
|||||||
public abstract class ExpandableView extends FrameLayout implements Dumpable {
|
public abstract class ExpandableView extends FrameLayout implements Dumpable {
|
||||||
private static final String TAG = "ExpandableView";
|
private static final String TAG = "ExpandableView";
|
||||||
|
|
||||||
public static final float NO_ROUNDNESS = -1;
|
|
||||||
protected OnHeightChangedListener mOnHeightChangedListener;
|
protected OnHeightChangedListener mOnHeightChangedListener;
|
||||||
private int mActualHeight;
|
private int mActualHeight;
|
||||||
protected int mClipTopAmount;
|
protected int mClipTopAmount;
|
||||||
@@ -192,14 +191,6 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the distance to the top roundness, from where we should start clipping a value above
|
|
||||||
* or equal to 0 is the effective distance, and if a value below 0 is received, there should
|
|
||||||
* be no clipping.
|
|
||||||
*/
|
|
||||||
public void setDistanceToTopRoundness(float distanceToTopRoundness) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setActualHeight(int actualHeight) {
|
public void setActualHeight(int actualHeight) {
|
||||||
setActualHeight(actualHeight, true /* notifyListeners */);
|
setActualHeight(actualHeight, true /* notifyListeners */);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,8 @@ public class NotificationBackgroundView extends View {
|
|||||||
private int mActualHeight;
|
private int mActualHeight;
|
||||||
private int mClipBottomAmount;
|
private int mClipBottomAmount;
|
||||||
private int mTintColor;
|
private int mTintColor;
|
||||||
private float[] mCornerRadii = new float[8];
|
private final float[] mCornerRadii = new float[8];
|
||||||
private boolean mBottomIsRounded;
|
private boolean mBottomIsRounded;
|
||||||
private boolean mLastInSection;
|
|
||||||
private boolean mFirstInSection;
|
|
||||||
private int mBackgroundTop;
|
private int mBackgroundTop;
|
||||||
private boolean mBottomAmountClips = true;
|
private boolean mBottomAmountClips = true;
|
||||||
private boolean mExpandAnimationRunning;
|
private boolean mExpandAnimationRunning;
|
||||||
@@ -53,9 +51,6 @@ public class NotificationBackgroundView extends View {
|
|||||||
private int mDrawableAlpha = 255;
|
private int mDrawableAlpha = 255;
|
||||||
private boolean mIsPressedAllowed;
|
private boolean mIsPressedAllowed;
|
||||||
|
|
||||||
private boolean mTopAmountRounded;
|
|
||||||
private float mDistanceToTopRoundness;
|
|
||||||
|
|
||||||
public NotificationBackgroundView(Context context, AttributeSet attrs) {
|
public NotificationBackgroundView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
mDontModifyCorners = getResources().getBoolean(
|
mDontModifyCorners = getResources().getBoolean(
|
||||||
@@ -90,15 +85,6 @@ public class NotificationBackgroundView extends View {
|
|||||||
left = (int) ((getWidth() - mActualWidth) / 2.0f);
|
left = (int) ((getWidth() - mActualWidth) / 2.0f);
|
||||||
right = (int) (left + mActualWidth);
|
right = (int) (left + mActualWidth);
|
||||||
}
|
}
|
||||||
if (mTopAmountRounded) {
|
|
||||||
int clipTop = (int) (mClipTopAmount - mDistanceToTopRoundness);
|
|
||||||
if (clipTop >= 0 || !mFirstInSection) {
|
|
||||||
top += clipTop;
|
|
||||||
}
|
|
||||||
if (clipTop >= 0 && !mLastInSection) {
|
|
||||||
bottom += clipTop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drawable.setBounds(left, top, right, bottom);
|
drawable.setBounds(left, top, right, bottom);
|
||||||
drawable.draw(canvas);
|
drawable.draw(canvas);
|
||||||
}
|
}
|
||||||
@@ -180,14 +166,6 @@ public class NotificationBackgroundView extends View {
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDistanceToTopRoundness(float distanceToTopRoundness) {
|
|
||||||
if (distanceToTopRoundness != mDistanceToTopRoundness) {
|
|
||||||
mTopAmountRounded = distanceToTopRoundness >= 0;
|
|
||||||
mDistanceToTopRoundness = distanceToTopRoundness;
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasOverlappingRendering() {
|
public boolean hasOverlappingRendering() {
|
||||||
|
|
||||||
@@ -246,18 +224,6 @@ public class NotificationBackgroundView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets whether this background belongs to the last notification in a section. */
|
|
||||||
public void setLastInSection(boolean lastInSection) {
|
|
||||||
mLastInSection = lastInSection;
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets whether this background belongs to the first notification in a section. */
|
|
||||||
public void setFirstInSection(boolean firstInSection) {
|
|
||||||
mFirstInSection = firstInSection;
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateBackgroundRadii() {
|
private void updateBackgroundRadii() {
|
||||||
if (mDontModifyCorners) {
|
if (mDontModifyCorners) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ public class AmbientState {
|
|||||||
private int mExpandAnimationTopChange;
|
private int mExpandAnimationTopChange;
|
||||||
private ExpandableNotificationRow mExpandingNotification;
|
private ExpandableNotificationRow mExpandingNotification;
|
||||||
private float mHideAmount;
|
private float mHideAmount;
|
||||||
private float mNotificationScrimTop;
|
|
||||||
private boolean mAppearing;
|
private boolean mAppearing;
|
||||||
private float mPulseHeight = MAX_PULSE_HEIGHT;
|
private float mPulseHeight = MAX_PULSE_HEIGHT;
|
||||||
private float mDozeAmount = 0.0f;
|
private float mDozeAmount = 0.0f;
|
||||||
@@ -256,20 +255,6 @@ public class AmbientState {
|
|||||||
return mHideAmount;
|
return mHideAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set y position of top of notifications background scrim, relative to top of screen.
|
|
||||||
*/
|
|
||||||
public void setNotificationScrimTop(float notificationScrimTop) {
|
|
||||||
mNotificationScrimTop = notificationScrimTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Y position of top of notifications background scrim, relative to top of screen.
|
|
||||||
*/
|
|
||||||
public float getNotificationScrimTop() {
|
|
||||||
return mNotificationScrimTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHideSensitive(boolean hideSensitive) {
|
public void setHideSensitive(boolean hideSensitive) {
|
||||||
mHideSensitive = hideSensitive;
|
mHideSensitive = hideSensitive;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Outline;
|
import android.graphics.Outline;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -453,6 +454,27 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
private NotificationStackScrollLayoutController mController;
|
private NotificationStackScrollLayoutController mController;
|
||||||
|
|
||||||
private boolean mKeyguardMediaControllorVisible;
|
private boolean mKeyguardMediaControllorVisible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The clip path used to clip the view in a rounded way.
|
||||||
|
*/
|
||||||
|
private final Path mRoundedClipPath = new Path();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we use rounded rect clipping right now
|
||||||
|
*/
|
||||||
|
private boolean mShouldUseRoundedRectClipping = false;
|
||||||
|
|
||||||
|
private int mRoundedRectClippingLeft;
|
||||||
|
private int mRoundedRectClippingTop;
|
||||||
|
private int mRoundedRectClippingBottom;
|
||||||
|
private int mRoundedRectClippingRight;
|
||||||
|
private float[] mBgCornerRadii = new float[8];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we launching a notification right now
|
||||||
|
*/
|
||||||
|
private boolean mLaunchingNotification;
|
||||||
private NotificationEntry mTopHeadsUpEntry;
|
private NotificationEntry mTopHeadsUpEntry;
|
||||||
private long mNumHeadsUp;
|
private long mNumHeadsUp;
|
||||||
private NotificationStackScrollLayoutController.TouchHandler mTouchHandler;
|
private NotificationStackScrollLayoutController.TouchHandler mTouchHandler;
|
||||||
@@ -1017,33 +1039,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||||
private void onPreDrawDuringAnimation() {
|
private void onPreDrawDuringAnimation() {
|
||||||
mShelf.updateAppearance();
|
mShelf.updateAppearance();
|
||||||
updateClippingToTopRoundedCorner();
|
|
||||||
if (!mNeedsAnimation && !mChildrenUpdateRequested) {
|
if (!mNeedsAnimation && !mChildrenUpdateRequested) {
|
||||||
updateBackground();
|
updateBackground();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
|
||||||
private void updateClippingToTopRoundedCorner() {
|
|
||||||
Float clipStart = mAmbientState.getNotificationScrimTop();
|
|
||||||
Float clipEnd = clipStart + mCornerRadius;
|
|
||||||
boolean first = true;
|
|
||||||
for (int i = 0; i < getChildCount(); i++) {
|
|
||||||
ExpandableView child = (ExpandableView) getChildAt(i);
|
|
||||||
if (child.getVisibility() == GONE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
float start = child.getTranslationY();
|
|
||||||
float end = start + child.getActualHeight();
|
|
||||||
boolean clip = clipStart > start && clipStart < end
|
|
||||||
|| clipEnd >= start && clipEnd <= end;
|
|
||||||
clip &= !(first && mScrollAdapter.isScrolledToTop());
|
|
||||||
child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0)
|
|
||||||
: ExpandableView.NO_ROUNDNESS);
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
||||||
private void updateScrollStateForAddedChildren() {
|
private void updateScrollStateForAddedChildren() {
|
||||||
if (mChildrenToAddAnimated.isEmpty()) {
|
if (mChildrenToAddAnimated.isEmpty()) {
|
||||||
@@ -1601,6 +1601,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
Resources res = getResources();
|
Resources res = getResources();
|
||||||
mShouldUseSplitNotificationShade = shouldUseSplitNotificationShade(mFeatureFlags, res);
|
mShouldUseSplitNotificationShade = shouldUseSplitNotificationShade(mFeatureFlags, res);
|
||||||
|
updateUseRoundedRectClipping();
|
||||||
mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
|
mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
|
||||||
float densityScale = res.getDisplayMetrics().density;
|
float densityScale = res.getDisplayMetrics().density;
|
||||||
mSwipeHelper.setDensityScale(densityScale);
|
mSwipeHelper.setDensityScale(densityScale);
|
||||||
@@ -2818,6 +2819,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
||||||
public void applyExpandAnimationParams(ExpandAnimationParameters params) {
|
public void applyExpandAnimationParams(ExpandAnimationParameters params) {
|
||||||
mAmbientState.setExpandAnimationTopChange(params == null ? 0 : params.getTopChange());
|
mAmbientState.setExpandAnimationTopChange(params == null ? 0 : params.getTopChange());
|
||||||
|
|
||||||
|
// Disable clipping for launches
|
||||||
|
setLaunchingNotification(params != null);
|
||||||
requestChildrenUpdate();
|
requestChildrenUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2901,7 +2905,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
mAnimationEvents.clear();
|
mAnimationEvents.clear();
|
||||||
updateBackground();
|
updateBackground();
|
||||||
updateViewShadows();
|
updateViewShadows();
|
||||||
updateClippingToTopRoundedCorner();
|
|
||||||
} else {
|
} else {
|
||||||
applyCurrentState();
|
applyCurrentState();
|
||||||
}
|
}
|
||||||
@@ -3795,6 +3798,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
updateNotificationAnimationStates();
|
updateNotificationAnimationStates();
|
||||||
updateChronometers();
|
updateChronometers();
|
||||||
requestChildrenUpdate();
|
requestChildrenUpdate();
|
||||||
|
updateUseRoundedRectClipping();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4015,7 +4019,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
setAnimationRunning(false);
|
setAnimationRunning(false);
|
||||||
updateBackground();
|
updateBackground();
|
||||||
updateViewShadows();
|
updateViewShadows();
|
||||||
updateClippingToTopRoundedCorner();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
||||||
@@ -4550,6 +4553,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||||
public void setQsExpansionFraction(float qsExpansionFraction) {
|
public void setQsExpansionFraction(float qsExpansionFraction) {
|
||||||
mQsExpansionFraction = qsExpansionFraction;
|
mQsExpansionFraction = qsExpansionFraction;
|
||||||
|
updateUseRoundedRectClipping();
|
||||||
|
|
||||||
// If notifications are scrolled,
|
// If notifications are scrolled,
|
||||||
// clear out scrollY by the time we push notifications offscreen
|
// clear out scrollY by the time we push notifications offscreen
|
||||||
@@ -5191,6 +5195,69 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
mScrollListener = listener;
|
mScrollListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set rounded rect clipping bounds on this view.
|
||||||
|
*/
|
||||||
|
public void setRoundedClippingBounds(int left, int top, int right, int bottom, int topRadius,
|
||||||
|
int bottomRadius) {
|
||||||
|
if (mRoundedRectClippingLeft == left && mRoundedRectClippingRight == right
|
||||||
|
&& mRoundedRectClippingBottom == bottom && mRoundedRectClippingTop == top
|
||||||
|
&& mBgCornerRadii[0] == topRadius && mBgCornerRadii[5] == bottomRadius) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mRoundedRectClippingLeft = left;
|
||||||
|
mRoundedRectClippingTop = top;
|
||||||
|
mRoundedRectClippingBottom = bottom;
|
||||||
|
mRoundedRectClippingRight = right;
|
||||||
|
mBgCornerRadii[0] = topRadius;
|
||||||
|
mBgCornerRadii[1] = topRadius;
|
||||||
|
mBgCornerRadii[2] = topRadius;
|
||||||
|
mBgCornerRadii[3] = topRadius;
|
||||||
|
mBgCornerRadii[4] = bottomRadius;
|
||||||
|
mBgCornerRadii[5] = bottomRadius;
|
||||||
|
mBgCornerRadii[6] = bottomRadius;
|
||||||
|
mBgCornerRadii[7] = bottomRadius;
|
||||||
|
mRoundedClipPath.reset();
|
||||||
|
mRoundedClipPath.addRoundRect(left, top, right, bottom, mBgCornerRadii, Path.Direction.CW);
|
||||||
|
if (mShouldUseRoundedRectClipping) {
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if we're launching a notification right now.
|
||||||
|
*/
|
||||||
|
private void setLaunchingNotification(boolean launching) {
|
||||||
|
if (launching == mLaunchingNotification) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mLaunchingNotification = launching;
|
||||||
|
updateUseRoundedRectClipping();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we use rounded rect clipping
|
||||||
|
*/
|
||||||
|
private void updateUseRoundedRectClipping() {
|
||||||
|
// We don't want to clip notifications when QS is expanded, because incoming heads up on
|
||||||
|
// the bottom would be clipped otherwise
|
||||||
|
boolean qsAllowsClipping = mQsExpansionFraction < 0.5f || mShouldUseSplitNotificationShade;
|
||||||
|
boolean clip = !mLaunchingNotification && mIsExpanded && qsAllowsClipping;
|
||||||
|
if (clip != mShouldUseRoundedRectClipping) {
|
||||||
|
mShouldUseRoundedRectClipping = clip;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dispatchDraw(Canvas canvas) {
|
||||||
|
if (mShouldUseRoundedRectClipping) {
|
||||||
|
// Let's clip rounded.
|
||||||
|
canvas.clipPath(mRoundedClipPath);
|
||||||
|
}
|
||||||
|
super.dispatchDraw(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A listener that is notified when the empty space below the notifications is clicked on
|
* A listener that is notified when the empty space below the notifications is clicked on
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -822,10 +822,20 @@ public class NotificationStackScrollLayoutController {
|
|||||||
return mView.isLayoutRtl();
|
return mView.isLayoutRtl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the left of the view.
|
||||||
|
*/
|
||||||
public int getLeft() {
|
public int getLeft() {
|
||||||
return mView.getLeft();
|
return mView.getLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the top of the view.
|
||||||
|
*/
|
||||||
|
public int getTop() {
|
||||||
|
return mView.getTop();
|
||||||
|
}
|
||||||
|
|
||||||
public float getTranslationX() {
|
public float getTranslationX() {
|
||||||
return mView.getTranslationX();
|
return mView.getTranslationX();
|
||||||
}
|
}
|
||||||
@@ -1444,6 +1454,14 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mView.setOnScrollListener(listener);
|
mView.setOnScrollListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set rounded rect clipping bounds on this view.
|
||||||
|
*/
|
||||||
|
public void setRoundedClippingBounds(int left, int top, int right, int bottom, int topRadius,
|
||||||
|
int bottomRadius) {
|
||||||
|
mView.setRoundedClippingBounds(left, top, right, bottom, topRadius, bottomRadius);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum for UiEvent logged from this class
|
* Enum for UiEvent logged from this class
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ public class StackScrollAlgorithm {
|
|||||||
AmbientState ambientState) {
|
AmbientState ambientState) {
|
||||||
float drawStart = ambientState.isOnKeyguard() ? 0
|
float drawStart = ambientState.isOnKeyguard() ? 0
|
||||||
: ambientState.getStackY() - ambientState.getScrollY();
|
: ambientState.getStackY() - ambientState.getScrollY();
|
||||||
float clipStart = ambientState.getNotificationScrimTop();
|
float clipStart = 0;
|
||||||
int childCount = algorithmState.visibleChildren.size();
|
int childCount = algorithmState.visibleChildren.size();
|
||||||
boolean firstHeadsUp = true;
|
boolean firstHeadsUp = true;
|
||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
|||||||
@@ -2241,29 +2241,21 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
* and QS state.
|
* and QS state.
|
||||||
*/
|
*/
|
||||||
private void setQSClippingBounds() {
|
private void setQSClippingBounds() {
|
||||||
int top = 0;
|
int top;
|
||||||
int bottom = 0;
|
int bottom;
|
||||||
int left = 0;
|
int left;
|
||||||
int right = 0;
|
int right;
|
||||||
|
|
||||||
final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
|
final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
|
||||||
final boolean quickSettingsVisible = computeQsExpansionFraction() > 0 || qsPanelBottomY > 0;
|
final boolean qsVisible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0);
|
||||||
|
|
||||||
if (mShouldUseSplitNotificationShade && quickSettingsVisible) {
|
if (!mShouldUseSplitNotificationShade) {
|
||||||
mAmbientState.setNotificationScrimTop(mSplitShadeNotificationsTopPadding);
|
|
||||||
|
|
||||||
top = Math.max(0, Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding));
|
|
||||||
bottom = mNotificationStackScrollLayoutController.getHeight();
|
|
||||||
left = mNotificationStackScrollLayoutController.getLeft();
|
|
||||||
right = mNotificationStackScrollLayoutController.getRight();
|
|
||||||
} else {
|
|
||||||
if (mTransitioningToFullShadeProgress > 0.0f) {
|
if (mTransitioningToFullShadeProgress > 0.0f) {
|
||||||
// If we're transitioning, let's use the actual value. The else case
|
// If we're transitioning, let's use the actual value. The else case
|
||||||
// can be wrong during transitions when waiting for the keyguard to unlock
|
// can be wrong during transitions when waiting for the keyguard to unlock
|
||||||
top = mTransitionToFullShadeQSPosition;
|
top = mTransitionToFullShadeQSPosition;
|
||||||
} else {
|
} else {
|
||||||
final float notificationTop = getQSEdgePosition();
|
final float notificationTop = getQSEdgePosition();
|
||||||
mAmbientState.setNotificationScrimTop(notificationTop);
|
|
||||||
top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
|
top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
|
||||||
: notificationTop);
|
: notificationTop);
|
||||||
}
|
}
|
||||||
@@ -2271,21 +2263,25 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
// notification bounds should take full screen width regardless of insets
|
// notification bounds should take full screen width regardless of insets
|
||||||
left = 0;
|
left = 0;
|
||||||
right = getView().getRight() + mDisplayRightInset;
|
right = getView().getRight() + mDisplayRightInset;
|
||||||
|
} else {
|
||||||
|
top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding);
|
||||||
|
bottom = mNotificationStackScrollLayoutController.getHeight();
|
||||||
|
left = mNotificationStackScrollLayoutController.getLeft();
|
||||||
|
right = mNotificationStackScrollLayoutController.getRight();
|
||||||
}
|
}
|
||||||
// top should never be lower than bottom, otherwise it will be invisible.
|
// top should never be lower than bottom, otherwise it will be invisible.
|
||||||
top = Math.min(top, bottom);
|
top = Math.min(top, bottom);
|
||||||
applyQSClippingBounds(left, top, right, bottom,
|
applyQSClippingBounds(left, top, right, bottom, qsVisible);
|
||||||
quickSettingsVisible && !mShouldUseSplitNotificationShade);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyQSClippingBounds(int left, int top, int right, int bottom,
|
private void applyQSClippingBounds(int left, int top, int right, int bottom,
|
||||||
boolean visible) {
|
boolean qsVisible) {
|
||||||
if (!mAnimateNextNotificationBounds || mKeyguardStatusAreaClipBounds.isEmpty()) {
|
if (!mAnimateNextNotificationBounds || mKeyguardStatusAreaClipBounds.isEmpty()) {
|
||||||
if (mQsClippingAnimation != null) {
|
if (mQsClippingAnimation != null) {
|
||||||
// update the end position of the animator
|
// update the end position of the animator
|
||||||
mQsClippingAnimationEndBounds.set(left, top, right, bottom);
|
mQsClippingAnimationEndBounds.set(left, top, right, bottom);
|
||||||
} else {
|
} else {
|
||||||
applyQSClippingImmediately(left, top, right, bottom, visible);
|
applyQSClippingImmediately(left, top, right, bottom, qsVisible);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mQsClippingAnimationEndBounds.set(left, top, right, bottom);
|
mQsClippingAnimationEndBounds.set(left, top, right, bottom);
|
||||||
@@ -2309,7 +2305,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
int animBottom = (int) MathUtils.lerp(startBottom,
|
int animBottom = (int) MathUtils.lerp(startBottom,
|
||||||
mQsClippingAnimationEndBounds.bottom, fraction);
|
mQsClippingAnimationEndBounds.bottom, fraction);
|
||||||
applyQSClippingImmediately(animLeft, animTop, animRight, animBottom,
|
applyQSClippingImmediately(animLeft, animTop, animRight, animBottom,
|
||||||
visible /* visible */);
|
qsVisible /* qsVisible */);
|
||||||
});
|
});
|
||||||
mQsClippingAnimation.addListener(new AnimatorListenerAdapter() {
|
mQsClippingAnimation.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@@ -2324,7 +2320,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void applyQSClippingImmediately(int left, int top, int right, int bottom,
|
private void applyQSClippingImmediately(int left, int top, int right, int bottom,
|
||||||
boolean visible) {
|
boolean qsVisible) {
|
||||||
// Fancy clipping for quick settings
|
// Fancy clipping for quick settings
|
||||||
int radius = mScrimCornerRadius;
|
int radius = mScrimCornerRadius;
|
||||||
int statusBarClipTop = 0;
|
int statusBarClipTop = 0;
|
||||||
@@ -2332,19 +2328,34 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
if (!mShouldUseSplitNotificationShade) {
|
if (!mShouldUseSplitNotificationShade) {
|
||||||
// The padding on this area is large enough that we can use a cheaper clipping strategy
|
// The padding on this area is large enough that we can use a cheaper clipping strategy
|
||||||
mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
|
mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
|
||||||
clipStatusView = visible;
|
clipStatusView = qsVisible;
|
||||||
radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius,
|
radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius,
|
||||||
Math.min(top / (float) mScrimCornerRadius, 1f));
|
Math.min(top / (float) mScrimCornerRadius, 1f));
|
||||||
statusBarClipTop = top - mKeyguardStatusBar.getTop();
|
statusBarClipTop = top - mKeyguardStatusBar.getTop();
|
||||||
}
|
}
|
||||||
if (mQs != null) {
|
if (mQs != null) {
|
||||||
mQs.setFancyClipping(top, bottom, radius, visible);
|
mQs.setFancyClipping(top, bottom, radius, qsVisible
|
||||||
|
&& !mShouldUseSplitNotificationShade);
|
||||||
}
|
}
|
||||||
mKeyguardStatusViewController.setClipBounds(
|
mKeyguardStatusViewController.setClipBounds(
|
||||||
clipStatusView ? mKeyguardStatusAreaClipBounds : null);
|
clipStatusView ? mKeyguardStatusAreaClipBounds : null);
|
||||||
|
if (!qsVisible && mShouldUseSplitNotificationShade) {
|
||||||
|
// On the lockscreen when qs isn't visible, we don't want the bounds of the shade to
|
||||||
|
// be visible, otherwise you can see the bounds once swiping up to see bouncer
|
||||||
|
mScrimController.setNotificationsBounds(0, 0, 0, 0);
|
||||||
|
} else {
|
||||||
mScrimController.setNotificationsBounds(left, top, right, bottom);
|
mScrimController.setNotificationsBounds(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
mScrimController.setScrimCornerRadius(radius);
|
mScrimController.setScrimCornerRadius(radius);
|
||||||
mKeyguardStatusBar.setTopClipping(statusBarClipTop);
|
mKeyguardStatusBar.setTopClipping(statusBarClipTop);
|
||||||
|
int nsslLeft = left - mNotificationStackScrollLayoutController.getLeft();
|
||||||
|
int nsslRight = right - mNotificationStackScrollLayoutController.getLeft();
|
||||||
|
int nsslTop = top - mNotificationStackScrollLayoutController.getTop();
|
||||||
|
int nsslBottom = bottom - mNotificationStackScrollLayoutController.getTop();
|
||||||
|
int bottomRadius = mShouldUseSplitNotificationShade ? radius : 0;
|
||||||
|
mNotificationStackScrollLayoutController.setRoundedClippingBounds(
|
||||||
|
nsslLeft, nsslTop, nsslRight, nsslBottom, radius, bottomRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getQSEdgePosition() {
|
private float getQSEdgePosition() {
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ import com.android.systemui.media.MediaDataManager;
|
|||||||
import com.android.systemui.media.MediaHierarchyManager;
|
import com.android.systemui.media.MediaHierarchyManager;
|
||||||
import com.android.systemui.navigationbar.NavigationModeController;
|
import com.android.systemui.navigationbar.NavigationModeController;
|
||||||
import com.android.systemui.plugins.FalsingManager;
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
import com.android.systemui.plugins.qs.QS;
|
|
||||||
import com.android.systemui.qs.QSDetailDisplayer;
|
import com.android.systemui.qs.QSDetailDisplayer;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
@@ -678,21 +677,6 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
|||||||
verify(mTapAgainViewController).show();
|
verify(mTapAgainViewController).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNotificationClipping_isAlignedWithNotificationScrimInSplitShade() {
|
|
||||||
mStatusBarStateController.setState(SHADE);
|
|
||||||
QS qs = mock(QS.class);
|
|
||||||
when(qs.getHeader()).thenReturn(mock(View.class));
|
|
||||||
mNotificationPanelViewController.mQs = qs;
|
|
||||||
enableSplitShade();
|
|
||||||
|
|
||||||
// hacky way to refresh notification scrim top with non-zero qsPanelBottom value
|
|
||||||
mNotificationPanelViewController.setTransitionToFullShadeAmount(200, false, 0);
|
|
||||||
|
|
||||||
verify(mAmbientState)
|
|
||||||
.setNotificationScrimTop(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSwitchesToCorrectClockInSinglePaneShade() {
|
public void testSwitchesToCorrectClockInSinglePaneShade() {
|
||||||
mStatusBarStateController.setState(KEYGUARD);
|
mStatusBarStateController.setState(KEYGUARD);
|
||||||
|
|||||||
Reference in New Issue
Block a user