Improved the transition into the statusbar
When expanding, the shelf now transforms into
the statusbar, providing a more seemless transition.
This also modifies the panel peeking:
previously the panel was always peeking right after a tap timeout
which would take the panel away from the users finger.
The panel is now only peeking when the user clicked on the bar instead.
Test: Add some notification and collapse the panel. Observe nicer transition
Bug: 32437839
Change-Id: I772f6684e1cee2004e9b366d203a5c5188af4a93
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 1a69492..ff644ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -50,6 +50,8 @@
private int[] mTmp = new int[2];
private boolean mHideBackground;
private int mIconAppearTopPadding;
+ private int mStatusBarHeight;
+ private int mStatusBarPaddingStart;
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -75,6 +77,9 @@
private void initDimens() {
mIconAppearTopPadding = getResources().getDimensionPixelSize(
R.dimen.notification_icon_appear_padding);
+ mStatusBarHeight = getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
+ mStatusBarPaddingStart = getResources().getDimensionPixelOffset(
+ R.dimen.status_bar_padding_start);
}
@Override
@@ -124,6 +129,11 @@
mShelfState.yTranslation = Math.min(viewEnd, maxShelfEnd) - mShelfState.height;
mShelfState.zTranslation = Math.max(mShelfState.zTranslation,
ambientState.getBaseZHeight());
+ float openedAmount = (mShelfState.yTranslation - getFullyClosedTranslation())
+ / (getIntrinsicHeight() * 2);
+ openedAmount = Math.min(1.0f, openedAmount);
+ mShelfState.iconContainerTranslation = (1.0f - openedAmount)
+ * (mStatusBarPaddingStart - mNotificationIconContainer.getLeft());
mShelfState.clipTopAmount = 0;
mShelfState.alpha = 1.0f;
mShelfState.belowShelf = false;
@@ -173,6 +183,10 @@
}
}
+ private float getFullyClosedTranslation() {
+ return - (getIntrinsicHeight() - mStatusBarHeight) / 2;
+ }
+
private void updateIconAppearance(NotificationData.Entry entry,
ExpandableNotificationRow.NotificationViewState rowState,
ShelfState shelfState) {
@@ -254,15 +268,21 @@
return super.shouldHideBackground() || mHideBackground;
}
+ private void setIconContainerTranslation(float iconContainerTranslation) {
+ mNotificationIconContainer.setTranslationX(iconContainerTranslation);
+ }
+
private class ShelfState extends ExpandableViewState {
private WeakHashMap<View, ViewState> iconStates = new WeakHashMap<>();
private boolean hideBackground;
+ private float iconContainerTranslation;
@Override
public void applyToView(View view) {
super.applyToView(view);
mNotificationIconContainer.applyIconStates(iconStates);
setHideBackground(hideBackground);
+ setIconContainerTranslation(iconContainerTranslation);
}
public void resetIcons() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 081ed51..584d5c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -207,6 +207,7 @@
}
};
private NotificationGroupManager mGroupManager;
+ private boolean mOpening;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -557,9 +558,7 @@
protected void flingToHeight(float vel, boolean expand, float target,
float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
mHeadsUpTouchHelper.notifyFling(!expand);
- setClosingWithAlphaFadeout(!expand
- && mNotificationStackScroller.getFirstChildIntrinsicHeight() <= mMaxFadeoutHeight
- && getFadeoutAlpha() == 1.0f);
+ setClosingWithAlphaFadeout(!expand && getFadeoutAlpha() == 1.0f);
super.flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
}
@@ -734,6 +733,11 @@
}
@Override
+ protected float getOpeningHeight() {
+ return mNotificationStackScroller.getMinExpansionHeight();
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent event) {
if (mBlockTouches || (mQs != null && mQs.isCustomizing())) {
return false;
@@ -1426,7 +1430,7 @@
if (mKeyguardShowing) {
// On Keyguard, interpolate the QS expansion linearly to the panel expansion
- t = expandedHeight / getMaxPanelHeight();
+ t = expandedHeight / (getMaxPanelHeight());
} else {
// In Shade, interpolate linearly such that QS is closed whenever panel height is
@@ -2276,6 +2280,14 @@
protected void updateExpandedHeight(float expandedHeight) {
mNotificationStackScroller.setExpandedHeight(expandedHeight);
updateKeyguardBottomAreaAlpha();
+ setOpening(expandedHeight <= getOpeningHeight());
+ }
+
+ private void setOpening(boolean opening) {
+ if (opening != mOpening) {
+ mOpening = opening;
+ mStatusBar.recomputeDisableFlags(false);
+ }
}
public void setPanelScrimMinFraction(float minFraction) {
@@ -2327,7 +2339,18 @@
@Override
public void setAlpha(float alpha) {
super.setAlpha(alpha);
- mNotificationStackScroller.setParentFadingOut(alpha != 1.0f);
+ updateFullyVisibleState();
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ super.setVisibility(visibility);
+ updateFullyVisibleState();
+ }
+
+ private void updateFullyVisibleState() {
+ mNotificationStackScroller.setParentNotFullyVisible(getAlpha() != 1.0f
+ || getVisibility() != VISIBLE);
}
/**
@@ -2369,6 +2392,15 @@
mGroupManager = groupManager;
}
+ public boolean shouldHideNotificationIcons() {
+ return !mOpening && !isFullyCollapsed();
+ }
+
+ public boolean shouldAnimateIconHiding() {
+ // TODO: handle this correctly, not completely working yet
+ return mNotificationStackScroller.getTranslationX() != 0;
+ }
+
private final FragmentListener mFragmentListener = new FragmentListener() {
@Override
public void onFragmentViewCreated(String tag, Fragment fragment) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index f2c57e5..87a3848 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -118,7 +118,7 @@
boolean fullyOpened = false;
if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
PanelView pv = mPanel;
- pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);
+ pv.setVisibility(expanded ? VISIBLE : INVISIBLE);
// adjust any other panels that may be partially visible
if (expanded) {
if (mState == STATE_CLOSED) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 3de03b5..570d5d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputDevice;
@@ -50,6 +51,10 @@
public abstract class PanelView extends FrameLayout {
public static final boolean DEBUG = PanelBar.DEBUG;
public static final String TAG = PanelView.class.getSimpleName();
+ private static final int INITIAL_OPENING_PEEK_DURATION = 200;
+ private static final int PEEK_ANIMATION_DURATION = 360;
+ private long mDownTime;
+ private float mMinExpandHeight;
private final void logf(String fmt, Object... args) {
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
@@ -88,6 +93,7 @@
private ObjectAnimator mPeekAnimator;
private VelocityTrackerInterface mVelocityTracker;
private FlingAnimationUtils mFlingAnimationUtils;
+ private FlingAnimationUtils mFlingAnimationUtilsClosing;
private FalsingManager mFalsingManager;
/**
@@ -106,9 +112,6 @@
private Interpolator mBounceInterpolator;
protected KeyguardBottomAreaView mKeyguardBottomArea;
- private boolean mPeekPending;
- private boolean mCollapseAfterPeek;
-
/**
* Speed-up factor to be used when {@link #mFlingCollapseRunnable} runs the next time.
*/
@@ -118,13 +121,6 @@
private boolean mGestureWaitForTouchSlop;
private boolean mIgnoreXTouchSlop;
private boolean mExpandLatencyTracking;
- private Runnable mPeekRunnable = new Runnable() {
- @Override
- public void run() {
- mPeekPending = false;
- runPeekAnimation();
- }
- };
protected void onExpandingFinished() {
mBar.onExpandingFinished();
@@ -148,21 +144,17 @@
}
}
- private void schedulePeek() {
- mPeekPending = true;
- long timeout = ViewConfiguration.getTapTimeout();
- postOnAnimationDelayed(mPeekRunnable, timeout);
- notifyBarPanelExpansionChanged();
- }
-
- private void runPeekAnimation() {
- mPeekHeight = getPeekHeight();
+ private void runPeekAnimation(long duration, float peekHeight, boolean collapseWhenFinished) {
+ mPeekHeight = peekHeight;
if (DEBUG) logf("peek to height=%.1f", mPeekHeight);
if (mHeightAnimator != null) {
return;
}
+ if (mPeekAnimator != null) {
+ mPeekAnimator.cancel();
+ }
mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", mPeekHeight)
- .setDuration(250);
+ .setDuration(duration);
mPeekAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
mPeekAnimator.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled;
@@ -175,10 +167,10 @@
@Override
public void onAnimationEnd(Animator animation) {
mPeekAnimator = null;
- if (mCollapseAfterPeek && !mCancelled) {
+ if (!mCancelled && collapseWhenFinished) {
postOnAnimation(mPostCollapseRunnable);
}
- mCollapseAfterPeek = false;
+
}
});
notifyExpandingStarted();
@@ -189,6 +181,7 @@
public PanelView(Context context, AttributeSet attrs) {
super(context, attrs);
mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f);
+ mFlingAnimationUtilsClosing = new FlingAnimationUtils(context, 0.4f);
mBounceInterpolator = new BounceInterpolator();
mFalsingManager = FalsingManager.getInstance(context);
}
@@ -267,11 +260,13 @@
case MotionEvent.ACTION_DOWN:
startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
mJustPeeked = false;
+ mMinExpandHeight = 0.0f;
mPanelClosedOnDown = isFullyCollapsed();
mHasLayoutedSinceDown = false;
mUpdateFlingOnLayout = false;
mMotionAborted = false;
mPeekTouching = mPanelClosedOnDown;
+ mDownTime = SystemClock.uptimeMillis();
mTouchAboveFalsingThreshold = false;
mCollapsedAndHeadsUpOnDown = isFullyCollapsed()
&& mHeadsUpManager.hasPinnedHeadsUp();
@@ -279,16 +274,16 @@
initVelocityTracker();
}
trackMovement(event);
- if (!mGestureWaitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning) ||
- mPeekPending || mPeekAnimator != null) {
+ if (!mGestureWaitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning)
+ || mPeekAnimator != null) {
cancelHeightAnimator();
cancelPeek();
mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning)
- || mPeekPending || mPeekAnimator != null;
+ || mPeekAnimator != null;
onTrackingStarted();
}
if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()) {
- schedulePeek();
+ startOpening();
}
break;
@@ -317,7 +312,7 @@
// y-component of the gesture, as we have no conflicting horizontal gesture.
if (Math.abs(h) > mTouchSlop
&& (Math.abs(h) > Math.abs(x - mInitialTouchX)
- || mIgnoreXTouchSlop)) {
+ || mIgnoreXTouchSlop)) {
mTouchSlopExceeded = true;
if (mGestureWaitForTouchSlop && !mTracking && !mCollapsedAndHeadsUpOnDown) {
if (!mJustPeeked && mInitialOffsetOnTouch != 0f) {
@@ -325,23 +320,30 @@
h = 0;
}
cancelHeightAnimator();
- removeCallbacks(mPeekRunnable);
- mPeekPending = false;
onTrackingStarted();
}
}
- final float newHeight = Math.max(0, h + mInitialOffsetOnTouch);
+ float newHeight = Math.max(0, h + mInitialOffsetOnTouch);
if (newHeight > mPeekHeight) {
if (mPeekAnimator != null) {
mPeekAnimator.cancel();
}
mJustPeeked = false;
+ } else if (mPeekAnimator == null && mJustPeeked) {
+ // The initial peek has finished, but we haven't dragged as far yet, lets
+ // speed it up by starting at the peek height.
+ mInitialOffsetOnTouch = mExpandedHeight;
+ mInitialTouchY = y;
+ mMinExpandHeight = mExpandedHeight;
+ mJustPeeked = false;
}
+ newHeight = Math.max(newHeight, mMinExpandHeight);
if (-h >= getFalsingThreshold()) {
mTouchAboveFalsingThreshold = true;
mUpwardsWhenTresholdReached = isDirectionUpwards(x, y);
}
- if (!mJustPeeked && (!mGestureWaitForTouchSlop || mTracking) && !isTrackingBlocked()) {
+ if (!mJustPeeked && (!mGestureWaitForTouchSlop || mTracking) &&
+ !isTrackingBlocked()) {
setExpandedHeightInternal(newHeight);
}
@@ -357,6 +359,14 @@
return !mGestureWaitForTouchSlop || mTracking;
}
+ private void startOpening() {;
+ runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(),
+ false /* collapseWhenFinished */);
+ notifyBarPanelExpansionChanged();
+ }
+
+ protected abstract float getOpeningHeight();
+
/**
* @return whether the swiping direction is upwards and above a 45 degree angle compared to the
* horizontal direction
@@ -418,6 +428,15 @@
if (mUpdateFlingOnLayout) {
mUpdateFlingVelocity = vel;
}
+ } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking) {
+ long timePassed = SystemClock.uptimeMillis() - mDownTime;
+ if (timePassed < ViewConfiguration.getLongPressTimeout()) {
+ // Lets show the user that he can actually expand the panel
+ runPeekAnimation(PEEK_ANIMATION_DURATION, getPeekHeight(), true /* collapseWhenFinished */);
+ } else {
+ // We need to collapse the panel since we peeked to the small height.
+ postOnAnimation(mPostCollapseRunnable);
+ }
} else {
boolean expands = onEmptySpaceClick(mInitialTouchX);
onTrackingStopped(expands);
@@ -448,7 +467,6 @@
protected void onTrackingStarted() {
endClosing();
mTracking = true;
- mCollapseAfterPeek = false;
mBar.onTrackingStarted();
notifyExpandingStarted();
notifyBarPanelExpansionChanged();
@@ -482,7 +500,10 @@
case MotionEvent.ACTION_DOWN:
mStatusBar.userActivity();
mAnimatingOnDown = mHeightAnimator != null;
- if (mAnimatingOnDown && mClosing && !mHintAnimationRunning || mPeekPending || mPeekAnimator != null) {
+ mMinExpandHeight = 0.0f;
+ mDownTime = SystemClock.uptimeMillis();
+ if (mAnimatingOnDown && mClosing && !mHintAnimationRunning
+ || mPeekAnimator != null) {
cancelHeightAnimator();
cancelPeek();
mTouchSlopExceeded = true;
@@ -639,7 +660,7 @@
protected void fling(float vel, boolean expand, float collapseSpeedUpFactor,
boolean expandBecauseOfFalsing) {
cancelPeek();
- float target = expand ? getMaxPanelHeight() : 0.0f;
+ float target = expand ? getMaxPanelHeight() : 0;
if (!expand) {
mClosing = true;
}
@@ -672,8 +693,7 @@
animator.setDuration(350);
}
} else {
- mFlingAnimationUtils.applyDismissing(animator, mExpandedHeight, target, vel,
- getHeight());
+ mFlingAnimationUtilsClosing.apply(animator, mExpandedHeight, target, vel, getHeight());
// Make it shorter if we run a canned animation
if (vel == 0) {
@@ -742,7 +762,6 @@
&& mHeightAnimator == null
&& !isFullyCollapsed()
&& currentMaxPanelHeight != mExpandedHeight
- && !mPeekPending
&& mPeekAnimator == null
&& !mPeekTouching) {
setExpandedHeight(currentMaxPanelHeight);
@@ -769,10 +788,8 @@
}
}
- mExpandedHeight = Math.max(0, mExpandedHeight);
- mExpandedFraction = Math.min(1f, fhWithoutOverExpansion == 0
- ? 0
- : mExpandedHeight / fhWithoutOverExpansion);
+ mExpandedFraction = Math.min(1f,
+ fhWithoutOverExpansion == 0 ? 0 : mExpandedHeight / fhWithoutOverExpansion);
onHeightUpdated(mExpandedHeight);
notifyBarPanelExpansionChanged();
}
@@ -816,7 +833,7 @@
}
public boolean isFullyCollapsed() {
- return mExpandedHeight <= 0;
+ return mExpandedFraction <= 0.0f;
}
public boolean isCollapsing() {
@@ -833,16 +850,7 @@
public void collapse(boolean delayed, float speedUpFactor) {
if (DEBUG) logf("collapse: " + this);
- if (mPeekPending || mPeekAnimator != null) {
- mCollapseAfterPeek = true;
- if (mPeekPending) {
-
- // We know that the whole gesture is just a peek triggered by a simple click, so
- // better start it now.
- removeCallbacks(mPeekRunnable);
- mPeekRunnable.run();
- }
- } else if (!isFullyCollapsed() && !mTracking && !mClosing) {
+ if (!isFullyCollapsed() && !mTracking && !mClosing) {
cancelHeightAnimator();
notifyExpandingStarted();
@@ -866,13 +874,11 @@
};
public void cancelPeek() {
- boolean cancelled = mPeekPending;
+ boolean cancelled = false;
if (mPeekAnimator != null) {
cancelled = true;
mPeekAnimator.cancel();
}
- removeCallbacks(mPeekRunnable);
- mPeekPending = false;
if (cancelled) {
// When peeking, we already tell mBar that we expanded ourselves. Make sure that we also
@@ -1048,7 +1054,7 @@
}
protected void notifyBarPanelExpansionChanged() {
- mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f || mPeekPending
+ mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f
|| mPeekAnimator != null || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp()
|| mTracking || mHeightAnimator != null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index fb51f51..604e8e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1054,7 +1054,7 @@
private void inflateShelf() {
mNotificationShelf =
(NotificationShelf) LayoutInflater.from(mContext).inflate(
- R.layout.status_bar_notification_icon_container, mStackScroller, false);
+ R.layout.status_bar_notification_shelf, mStackScroller, false);
mNotificationShelf.setOnActivatedListener(this);
mNotificationShelf.setOnClickListener(mShelfClickListener);
mStackScroller.setShelf(mNotificationShelf);
@@ -2005,10 +2005,12 @@
}
currentIndex++;
}
+ boolean noAmbient = false;
if (shelfIndex == -1) {
shelfIndex = currentIndex;
+ noAmbient = true;
}
- mStackScroller.updateShelfIndex(shelfIndex);
+ mStackScroller.updateShelfIndex(shelfIndex, noAmbient);
}
public static boolean isTopLevelChild(Entry entry) {
@@ -2380,8 +2382,7 @@
}
protected int adjustDisableFlags(int state) {
- if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway
- && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) {
+ if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway && shouldHideNotificationIcons()) {
state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
state |= StatusBarManager.DISABLE_SYSTEM_INFO;
}
@@ -2396,6 +2397,10 @@
return state;
}
+ private boolean shouldHideNotificationIcons() {
+ return mExpandedVisible && mNotificationPanel.shouldHideNotificationIcons();
+ }
+
/**
* State is one or more of the DISABLE constants from StatusBarManager.
*/
@@ -2502,7 +2507,7 @@
*
* This needs to be called if state used by {@link #adjustDisableFlags} changes.
*/
- private void recomputeDisableFlags(boolean animate) {
+ public void recomputeDisableFlags(boolean animate) {
disable(mDisabledUnmodified1, mDisabledUnmodified2, animate);
}
@@ -2948,7 +2953,7 @@
runPostCollapseRunnables();
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
showBouncer();
- recomputeDisableFlags(true /* animate */);
+ recomputeDisableFlags(shouldAnimatIconHiding() /* animate */);
// Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
// the bouncer appear animation.
@@ -2957,6 +2962,10 @@
}
}
+ private boolean shouldAnimatIconHiding() {
+ return mNotificationPanel.shouldAnimateIconHiding();
+ }
+
public boolean interceptTouchEvent(MotionEvent event) {
if (DEBUG_GESTURES) {
if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
@@ -4166,7 +4175,7 @@
mScrimController.forceHideScrims(true /* hide */);
updateMediaMetaData(false, true);
mNotificationPanel.setAlpha(1);
- mStackScroller.setParentFadingOut(true);
+ mStackScroller.setParentNotFullyVisible(true);
mNotificationPanel.animate()
.alpha(0)
.setStartDelay(FADE_KEYGUARD_START_DELAY)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 6217433..f6dd88d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -235,7 +235,7 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN
- && mNotificationPanel.getExpandedHeight() == 0f) {
+ && mNotificationPanel.isFullyCollapsed()) {
mNotificationPanel.startExpandLatencyTracking();
}
mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 39b56d7..d046723 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -333,7 +333,7 @@
private boolean mPulsing;
private boolean mDrawBackgroundAsSrc;
private boolean mFadingOut;
- private boolean mParentFadingOut;
+ private boolean mParentNotFullyVisible;
private boolean mGroupExpandedForMeasure;
private boolean mScrollable;
private View mForcedScroll;
@@ -355,6 +355,10 @@
private boolean mBackwardScrollable;
private NotificationShelf mShelf;
private int mMaxDisplayedNotifications = -1;
+ private int mStatusBarHeight;
+ private boolean mNoAmbient;
+ private final Rect mClipRect = new Rect();
+ private boolean mIsClipped;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -472,6 +476,7 @@
mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength();
mMinTopOverScrollToEscape = getResources().getDimensionPixelSize(
R.dimen.min_top_overscroll_to_qs);
+ mStatusBarHeight = getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
}
public void setDrawBackgroundAsSrc(boolean asSrc) {
@@ -480,7 +485,7 @@
}
private void updateSrcDrawing() {
- mBackgroundPaint.setXfermode(mDrawBackgroundAsSrc && (!mFadingOut && !mParentFadingOut)
+ mBackgroundPaint.setXfermode(mDrawBackgroundAsSrc && !mFadingOut && !mParentNotFullyVisible
? mSrcMode : null);
invalidate();
}
@@ -532,9 +537,10 @@
}
}
- public void updateShelfIndex(int newIndex) {
+ public void updateShelfIndex(int newIndex, boolean noAmbient) {
mAmbientState.setShelfIndex(newIndex);
changeViewPosition(mShelf, newIndex);
+ mNoAmbient = noAmbient;
}
public void setChildLocationsChangedListener(OnChildLocationsChangedListener listener) {
@@ -668,6 +674,16 @@
}
}
+ @Override
+ public void setClipBounds(Rect clipBounds) {
+ super.setClipBounds(clipBounds);
+ boolean clipped = clipBounds != null;
+ if (clipped != mIsClipped) {
+ mIsClipped = clipped;
+ updateFadingState();
+ }
+ }
+
/**
* Update the height of the panel.
*
@@ -675,7 +691,18 @@
*/
public void setExpandedHeight(float height) {
mExpandedHeight = height;
- setIsExpanded(height > 0.0f);
+ int minExpansionHeight = getMinExpansionHeight();
+ if (height < minExpansionHeight) {
+ mClipRect.left = 0;
+ mClipRect.right = getWidth();
+ mClipRect.top = 0;
+ mClipRect.bottom = (int) height;
+ height = minExpansionHeight;
+ setClipBounds(mClipRect);
+ } else {
+ setClipBounds(null);
+ }
+ setIsExpanded(height > getMinExpansionHeight());
int stackHeight;
float translationY;
float appearEndPosition = getAppearEndPosition();
@@ -708,13 +735,7 @@
* Measured relative to the resting position.
*/
private float getExpandTranslationStart() {
- int startPosition = 0;
- if (!mTrackingHeadsUp && !mHeadsUpManager.hasPinnedHeadsUp()) {
- startPosition = - Math.min(getFirstChildIntrinsicHeight(),
- mMaxLayoutHeight - mIntrinsicPadding - mBottomStackSlowDownHeight
- - mBottomStackPeekSize);
- }
- return startPosition - mTopPadding;
+ return - mTopPadding;
}
/**
@@ -722,9 +743,7 @@
* Measured in absolute height.
*/
private float getAppearStartPosition() {
- return mTrackingHeadsUp
- ? mHeadsUpManager.getTopHeadsUpPinnedHeight()
- : 0;
+ return getMinExpansionHeight();
}
/**
@@ -735,7 +754,7 @@
int firstItemHeight = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()
? mHeadsUpManager.getTopHeadsUpPinnedHeight() + mBottomStackPeekSize
+ mBottomStackSlowDownHeight
- : getLayoutMinHeight();
+ : getFirstItemMinHeight() + mShelf.getIntrinsicHeight();
return firstItemHeight + (onKeyguard() ? mTopPadding : mIntrinsicPadding);
}
@@ -2052,7 +2071,7 @@
private void applyCurrentBackgroundBounds() {
mScrimController.setExcludedBackgroundArea(
- mFadingOut || mParentFadingOut || mAmbientState.isDark() ? null
+ mFadingOut || mParentNotFullyVisible || mAmbientState.isDark() || mIsClipped ? null
: mCurrentBounds);
invalidate();
}
@@ -2131,8 +2150,8 @@
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
View child = getChildAt(i);
- if (child.getVisibility() != View.GONE
- && child instanceof ActivatableNotificationView) {
+ if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
+ && child != mShelf) {
return (ActivatableNotificationView) child;
}
}
@@ -2143,8 +2162,8 @@
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child.getVisibility() != View.GONE
- && child instanceof ActivatableNotificationView) {
+ if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
+ && child != mShelf) {
return (ActivatableNotificationView) child;
}
}
@@ -2227,9 +2246,7 @@
}
public int getLayoutMinHeight() {
- int firstChildMinHeight = getFirstChildIntrinsicHeight();
- return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
- mMaxLayoutHeight - mIntrinsicPadding);
+ return mShelf.getIntrinsicHeight();
}
public int getFirstChildIntrinsicHeight() {
@@ -3095,6 +3112,11 @@
public int getEmptyBottomMargin() {
int emptyMargin = mMaxLayoutHeight - mContentHeight;
+ if (!mNoAmbient || mEmptyShadeView.getVisibility() == VISIBLE) {
+ // If we have ambient notifications or a clear all button, we need to make sure that the
+ // notifications are a bit taller, otherwise they will be pushed under the other cards
+ emptyMargin -= (mBottomStackPeekSize + mBottomStackSlowDownHeight);
+ }
return Math.max(emptyMargin, 0);
}
@@ -3876,9 +3898,13 @@
}
}
- public void setParentFadingOut(boolean fadingOut) {
- if (fadingOut != mParentFadingOut) {
- mParentFadingOut = fadingOut;
+ public void setParentNotFullyVisible(boolean parentNotFullyVisible) {
+ if (mScrimController == null) {
+ // we're not set up yet.
+ return;
+ }
+ if (parentNotFullyVisible != mParentNotFullyVisible) {
+ mParentNotFullyVisible = parentNotFullyVisible;
updateFadingState();
}
}
@@ -3938,6 +3964,13 @@
}
}
+ public int getMinExpansionHeight() {
+ return mTrackingHeadsUp
+ ? mHeadsUpManager.getTopHeadsUpPinnedHeight()
+ : mShelf.getIntrinsicHeight()
+ - (mShelf.getIntrinsicHeight() - mStatusBarHeight) / 2;
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index b8acb8c..1b3afe7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -379,12 +379,6 @@
}
}
- if (i == 0 && ambientState.getScrollY() <= 0) {
- // The first card can get into the bottom stack if it's the only one
- // on the lockscreen which pushes it up. Let's make sure that doesn't happen and
- // it stays at the top
- childViewState.yTranslation = Math.max(0, childViewState.yTranslation);
- }
currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
if (currentYPosition <= 0) {
childViewState.location = ExpandableViewState.LOCATION_HIDDEN_TOP;