Fully removed the bottom stack
Moved the ambient notifications into the shelf instead of having them behave with their own physics. Previously the ambient notifications were stuck in the old world behind the shelf, but this doesn't make sense anymore. This also fixed a bug where the notifications were wrongly positioned on the lockscreen since the shelf counted as a view that wasn't gone. Test: add low-priority notifications, observe scrolling Bug: 32437839 Change-Id: I3921ea9f80a06f1b6330315423b012174269ac8e
This commit is contained in:
@@ -273,16 +273,10 @@
|
||||
<!-- Default distance from each snap target that GlowPadView considers a "hit" -->
|
||||
<dimen name="glowpadview_inner_radius">15dip</dimen>
|
||||
|
||||
<!-- Space reserved for the cards behind the top card in the bottom stack -->
|
||||
<dimen name="bottom_stack_peek_amount">12dp</dimen>
|
||||
|
||||
<!-- bottom_stack_peek_amount + notification_min_height
|
||||
+ notification_collapse_second_card_padding -->
|
||||
<dimen name="min_stack_height">104dp</dimen>
|
||||
|
||||
<!-- The height of the area before the bottom stack in which the notifications slow down -->
|
||||
<dimen name="bottom_stack_slow_down_length">12dp</dimen>
|
||||
|
||||
<!-- Z distance between notifications if they are in the stack -->
|
||||
<dimen name="z_distance_between_notifications">0.5dp</dimen>
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.classifier.FalsingManager;
|
||||
import com.android.systemui.statusbar.notification.FakeShadowView;
|
||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
import com.android.systemui.statusbar.stack.ExpandableViewState;
|
||||
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
|
||||
import com.android.systemui.statusbar.stack.StackStateAnimator;
|
||||
|
||||
@@ -132,7 +131,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
|
||||
private final int mLegacyColor;
|
||||
private final int mNormalColor;
|
||||
private final int mLowPriorityColor;
|
||||
private boolean mIsBelowShelf;
|
||||
private boolean mIsBelowSpeedBump;
|
||||
private FalsingManager mFalsingManager;
|
||||
private boolean mTrackTouch;
|
||||
|
||||
@@ -444,14 +443,25 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBelowShelf(boolean below) {
|
||||
super.setBelowShelf(below);
|
||||
if (below != mIsBelowShelf) {
|
||||
mIsBelowShelf = below;
|
||||
public void setBelowSpeedBump(boolean below) {
|
||||
super.setBelowSpeedBump(below);
|
||||
if (below != mIsBelowSpeedBump) {
|
||||
mIsBelowSpeedBump = below;
|
||||
updateBackgroundTint();
|
||||
onBelowSpeedBumpChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onBelowSpeedBumpChanged() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether we are below the speed bump
|
||||
*/
|
||||
public boolean isBelowSpeedBump() {
|
||||
return mIsBelowSpeedBump;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tint color of the background
|
||||
*/
|
||||
@@ -857,7 +867,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
|
||||
return mBgTint;
|
||||
} else if (mShowingLegacyBackground) {
|
||||
return mLegacyColor;
|
||||
} else if (mIsBelowShelf) {
|
||||
} else if (mIsBelowSpeedBump) {
|
||||
return mLowPriorityColor;
|
||||
} else {
|
||||
return mNormalColor;
|
||||
@@ -869,7 +879,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
|
||||
return mTintedRippleColor;
|
||||
} else if (mShowingLegacyBackground) {
|
||||
return mTintedRippleColor;
|
||||
} else if (mIsBelowShelf) {
|
||||
} else if (mIsBelowSpeedBump) {
|
||||
return mLowPriorityRippleColor;
|
||||
} else {
|
||||
return mNormalRippleColor;
|
||||
@@ -915,7 +925,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
|
||||
setTintColor(0);
|
||||
resetBackgroundAlpha();
|
||||
setShowingLegacyBackground(false);
|
||||
setBelowShelf(false);
|
||||
setBelowSpeedBump(false);
|
||||
}
|
||||
|
||||
public boolean hasSameBgColor(ActivatableNotificationView otherView) {
|
||||
|
||||
@@ -413,6 +413,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
if (mNotificationParent != null) {
|
||||
mNotificationParent.updateBackgroundForGroupState();
|
||||
}
|
||||
updateIconVisibilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -847,6 +848,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBelowSpeedBumpChanged() {
|
||||
updateIconVisibilities();
|
||||
}
|
||||
|
||||
private void updateContentFadeOut() {
|
||||
if (!isChildInGroup()) {
|
||||
float contentAlpha = 1.0f - mIconTransformationAmount;
|
||||
@@ -866,12 +872,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
}
|
||||
|
||||
private void updateIconVisibilities() {
|
||||
if (!isChildInGroup()) {
|
||||
mPublicLayout.setIconsVisible(mIconsVisible);
|
||||
mPrivateLayout.setIconsVisible(mIconsVisible);
|
||||
if (mChildrenContainer != null) {
|
||||
mChildrenContainer.setIconsVisible(mIconsVisible);
|
||||
}
|
||||
boolean visible = isChildInGroup() || isBelowSpeedBump() || mIconsVisible;
|
||||
mPublicLayout.setIconsVisible(visible);
|
||||
mPrivateLayout.setIconsVisible(visible);
|
||||
if (mChildrenContainer != null) {
|
||||
mChildrenContainer.setIconsVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -283,10 +283,10 @@ public abstract class ExpandableView extends FrameLayout {
|
||||
public abstract void performAddAnimation(long delay, long duration);
|
||||
|
||||
/**
|
||||
* Set the notification appearance to be below the shelf.
|
||||
* Set the notification appearance to be below the speed bump.
|
||||
* @param below true if it is below.
|
||||
*/
|
||||
public void setBelowShelf(boolean below) {
|
||||
public void setBelowSpeedBump(boolean below) {
|
||||
}
|
||||
|
||||
public int getPinnedHeadsUpHeight() {
|
||||
|
||||
@@ -32,7 +32,6 @@ import com.android.systemui.statusbar.stack.AmbientState;
|
||||
import com.android.systemui.statusbar.stack.AnimationProperties;
|
||||
import com.android.systemui.statusbar.stack.ExpandableViewState;
|
||||
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
|
||||
import com.android.systemui.statusbar.stack.StackScrollAlgorithm;
|
||||
import com.android.systemui.statusbar.stack.StackScrollState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -131,13 +130,11 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
}
|
||||
|
||||
public void updateState(StackScrollState resultState,
|
||||
StackScrollAlgorithm.StackScrollAlgorithmState algorithmState,
|
||||
AmbientState ambientState) {
|
||||
int shelfIndex = ambientState.getShelfIndex() - 1;
|
||||
if (shelfIndex != -1) {
|
||||
View lastView = ambientState.getLastVisibleBackgroundChild();
|
||||
if (lastView != null) {
|
||||
float maxShelfEnd = ambientState.getInnerHeight() + ambientState.getTopPadding()
|
||||
+ ambientState.getStackTranslation();
|
||||
ExpandableView lastView = algorithmState.visibleChildren.get(shelfIndex);
|
||||
ExpandableViewState lastViewState = resultState.getViewStateForView(lastView);
|
||||
float viewEnd = lastViewState.yTranslation + lastViewState.height;
|
||||
mShelfState.copyFrom(lastViewState);
|
||||
@@ -151,7 +148,7 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
mShelfState.openedAmount = openedAmount;
|
||||
mShelfState.clipTopAmount = 0;
|
||||
mShelfState.alpha = 1.0f;
|
||||
mShelfState.belowShelf = false;
|
||||
mShelfState.belowSpeedBump = false;
|
||||
mShelfState.shadowAlpha = 1.0f;
|
||||
mShelfState.isBottomClipped = false;
|
||||
mShelfState.hideSensitive = false;
|
||||
@@ -174,8 +171,8 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
public void updateAppearance() {
|
||||
WeakHashMap<View, NotificationIconContainer.IconState> iconStates =
|
||||
mShelfIcons.resetViewStates();
|
||||
float numIconsInShelf = 0.0f;
|
||||
int shelfIndex = mAmbientState.getShelfIndex();
|
||||
float numViewsInShelf = 0.0f;
|
||||
View lastChild = mAmbientState.getLastVisibleBackgroundChild();
|
||||
mNotGoneIndex = -1;
|
||||
float interpolationStart = mMaxLayoutHeight - getIntrinsicHeight() * 2;
|
||||
float expandAmount = 0.0f;
|
||||
@@ -185,8 +182,12 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
}
|
||||
// find the first view that doesn't overlap with the shelf
|
||||
int notificationIndex = 0;
|
||||
int notGoneNotifications = 0;
|
||||
while (notGoneNotifications < shelfIndex) {
|
||||
int notGoneIndex = 0;
|
||||
boolean backgroundForceHidden = false;
|
||||
if (mHideBackground && !mShelfState.hasItemsInStableShelf) {
|
||||
backgroundForceHidden = true;
|
||||
}
|
||||
while (notificationIndex < mHostLayout.getChildCount()) {
|
||||
ExpandableView child = (ExpandableView) mHostLayout.getChildAt(notificationIndex);
|
||||
notificationIndex++;
|
||||
if (!(child instanceof ExpandableNotificationRow)
|
||||
@@ -199,7 +200,7 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
float notificationClipEnd;
|
||||
float shelfStart = getTranslationY();
|
||||
boolean aboveShelf = row.getTranslationZ() > mAmbientState.getBaseZHeight();
|
||||
if (notGoneNotifications == shelfIndex - 1 || aboveShelf) {
|
||||
if (child == lastChild || aboveShelf || backgroundForceHidden) {
|
||||
notificationClipEnd = shelfStart + getIntrinsicHeight();
|
||||
} else {
|
||||
notificationClipEnd = shelfStart - mPaddingBetweenElements;
|
||||
@@ -212,34 +213,25 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
}
|
||||
}
|
||||
updateNotificationClipHeight(row, notificationClipEnd);
|
||||
updateIconAppearance(row, iconState, icon, expandAmount);
|
||||
numIconsInShelf += iconState.iconAppearAmount;
|
||||
numViewsInShelf += updateIconAppearance(row, iconState, icon, expandAmount);
|
||||
if (row.getTranslationY() >= getTranslationY() && mNotGoneIndex == -1) {
|
||||
mNotGoneIndex = notGoneNotifications;
|
||||
mNotGoneIndex = notGoneIndex;
|
||||
}
|
||||
if (notGoneNotifications != 0 || !aboveShelf) {
|
||||
if (notGoneIndex != 0 || !aboveShelf) {
|
||||
row.setAboveShelf(false);
|
||||
}
|
||||
notGoneNotifications++;
|
||||
}
|
||||
while (notificationIndex < mHostLayout.getChildCount()) {
|
||||
// We need to reset the clipping in case a notification switches from high to low
|
||||
// priority.
|
||||
ExpandableView child = (ExpandableView) mHostLayout.getChildAt(notificationIndex);
|
||||
if (child.getClipBottomAmount() != 0) {
|
||||
child.setClipBottomAmount(0);
|
||||
}
|
||||
if (child instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||
row.setIconTransformationAmount(0);
|
||||
}
|
||||
notificationIndex++;
|
||||
notGoneIndex++;
|
||||
}
|
||||
mShelfIcons.calculateIconTranslations();
|
||||
mShelfIcons.applyIconStates();
|
||||
setVisibility(numIconsInShelf == 0.0f || !mAmbientState.isShadeExpanded() ? INVISIBLE
|
||||
: VISIBLE);
|
||||
setHideBackground(numIconsInShelf < 1.0f);
|
||||
setVisibility(numViewsInShelf != 0.0f && mAmbientState.isShadeExpanded()
|
||||
? VISIBLE
|
||||
: INVISIBLE);
|
||||
boolean hideBackground = numViewsInShelf < 1.0f;
|
||||
setHideBackground(hideBackground || backgroundForceHidden);
|
||||
if (mNotGoneIndex == -1) {
|
||||
mNotGoneIndex = notGoneIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNotificationClipHeight(ExpandableNotificationRow row,
|
||||
@@ -254,13 +246,16 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateIconAppearance(ExpandableNotificationRow row,
|
||||
private float updateIconAppearance(ExpandableNotificationRow row,
|
||||
NotificationIconContainer.IconState iconState, StatusBarIconView icon,
|
||||
float expandAmount) {
|
||||
// Let calculate how much the view is in the shelf
|
||||
float viewStart = row.getTranslationY();
|
||||
int transformHeight = row.getActualHeight() + mPaddingBetweenElements;
|
||||
float viewEnd = viewStart + transformHeight;
|
||||
float iconAppearAmount;
|
||||
float yTranslation;
|
||||
float alpha = 1.0f;
|
||||
if (viewEnd >= getTranslationY() && (mAmbientState.isShadeExpanded()
|
||||
|| (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) {
|
||||
if (viewStart < getTranslationY()) {
|
||||
@@ -269,12 +264,12 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
linearAmount);
|
||||
interpolatedAmount = NotificationUtils.interpolate(
|
||||
interpolatedAmount, linearAmount, expandAmount);
|
||||
iconState.iconAppearAmount = 1.0f - interpolatedAmount;
|
||||
iconAppearAmount = 1.0f - interpolatedAmount;
|
||||
} else {
|
||||
iconState.iconAppearAmount = 1.0f;
|
||||
iconAppearAmount = 1.0f;
|
||||
}
|
||||
} else {
|
||||
iconState.iconAppearAmount = 0.0f;
|
||||
iconAppearAmount = 0.0f;
|
||||
}
|
||||
|
||||
// Lets now calculate how much of the transformation has already happened. This is different
|
||||
@@ -300,12 +295,12 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
|| (!mAmbientState.isShadeExpanded()
|
||||
&& (row.isPinned() || row.isHeadsUpAnimatingAway()))) {
|
||||
// We simply place it on the icon of the notification
|
||||
iconState.yTranslation = notificationIconPosition - shelfIconPosition;
|
||||
yTranslation = notificationIconPosition - shelfIconPosition;
|
||||
} else {
|
||||
transitionAmount = (viewStart - transformationStartPosition)
|
||||
/ transitionDistance;
|
||||
float startPosition = transformationStartPosition + iconTopPadding;
|
||||
iconState.yTranslation = NotificationUtils.interpolate(
|
||||
yTranslation = NotificationUtils.interpolate(
|
||||
startPosition - shelfIconPosition, 0, transitionAmount);
|
||||
// If we are merging into the shelf, lets make sure the shelf is at least on our height,
|
||||
// otherwise the icons won't be visible.
|
||||
@@ -314,24 +309,30 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
float shelfIconSize = icon.getHeight() * icon.getIconScale();
|
||||
if (!row.isShowingIcon()) {
|
||||
// The view currently doesn't have an icon, lets transform it in!
|
||||
iconState.alpha = transitionAmount;
|
||||
alpha = transitionAmount;
|
||||
notificationIconSize = shelfIconSize / 2.0f;
|
||||
}
|
||||
// The notification size is different from the size in the shelf / statusbar
|
||||
float newSize = NotificationUtils.interpolate(notificationIconSize, shelfIconSize,
|
||||
transitionAmount);
|
||||
iconState.scaleX = newSize / icon.getHeight() / icon.getIconScale();
|
||||
iconState.scaleY = iconState.scaleX;
|
||||
iconState.hidden = transitionAmount == 0.0f;
|
||||
row.setIconTransformationAmount(transitionAmount);
|
||||
icon.setVisibility(transitionAmount == 0.0f ? INVISIBLE : VISIBLE);
|
||||
if (row.isInShelf() && !row.isTransformingIntoShelf()) {
|
||||
iconState.iconAppearAmount = 1.0f;
|
||||
iconState.alpha = 1.0f;
|
||||
iconState.scaleX = 1.0f;
|
||||
iconState.scaleY = 1.0f;
|
||||
iconState.hidden = false;
|
||||
if (iconState != null) {
|
||||
iconState.scaleX = newSize / icon.getHeight() / icon.getIconScale();
|
||||
iconState.scaleY = iconState.scaleX;
|
||||
iconState.hidden = transitionAmount == 0.0f;
|
||||
iconState.iconAppearAmount = iconAppearAmount;
|
||||
iconState.alpha = alpha;
|
||||
iconState.yTranslation = yTranslation;
|
||||
icon.setVisibility(transitionAmount == 0.0f ? INVISIBLE : VISIBLE);
|
||||
if (row.isInShelf() && !row.isTransformingIntoShelf()) {
|
||||
iconState.iconAppearAmount = 1.0f;
|
||||
iconState.alpha = 1.0f;
|
||||
iconState.scaleX = 1.0f;
|
||||
iconState.scaleY = 1.0f;
|
||||
iconState.hidden = false;
|
||||
}
|
||||
}
|
||||
return iconAppearAmount;
|
||||
}
|
||||
|
||||
private float getFullyClosedTranslation() {
|
||||
|
||||
@@ -1490,9 +1490,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
// and expanding/collapsing the whole panel from/to quick settings.
|
||||
if (mNotificationStackScroller.getNotGoneChildCount() == 0
|
||||
&& mShadeEmpty) {
|
||||
notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight()
|
||||
+ mNotificationStackScroller.getBottomStackPeekSize()
|
||||
+ mNotificationStackScroller.getBottomStackSlowDownHeight();
|
||||
notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
|
||||
}
|
||||
int maxQsHeight = mQsMaxExpansionHeight;
|
||||
|
||||
@@ -1523,8 +1521,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
|
||||
private float getFadeoutAlpha() {
|
||||
float alpha = (getNotificationsTopY() + mNotificationStackScroller.getFirstItemMinHeight())
|
||||
/ (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
|
||||
- mNotificationStackScroller.getBottomStackSlowDownHeight());
|
||||
/ mQsMinExpansionHeight;
|
||||
alpha = Math.max(0, Math.min(alpha, 1));
|
||||
alpha = (float) Math.pow(alpha, 0.75);
|
||||
return alpha;
|
||||
|
||||
@@ -1868,7 +1868,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
mTmpChildOrderMap.clear();
|
||||
|
||||
updateRowStates();
|
||||
updateShelfIndex();
|
||||
updateSpeedBumpIndex();
|
||||
updateClearAll();
|
||||
updateEmptyShadeView();
|
||||
|
||||
@@ -1989,8 +1989,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
mNotificationPanel.setShadeEmpty(showEmptyShade);
|
||||
}
|
||||
|
||||
private void updateShelfIndex() {
|
||||
int shelfIndex = -1;
|
||||
private void updateSpeedBumpIndex() {
|
||||
int speedBumpIndex = -1;
|
||||
int currentIndex = 0;
|
||||
final int N = mStackScroller.getChildCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
@@ -2000,17 +2000,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
}
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
|
||||
if (mNotificationData.isAmbient(row.getStatusBarNotification().getKey())) {
|
||||
shelfIndex = currentIndex;
|
||||
speedBumpIndex = currentIndex;
|
||||
break;
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
boolean noAmbient = false;
|
||||
if (shelfIndex == -1) {
|
||||
shelfIndex = currentIndex;
|
||||
if (speedBumpIndex == -1) {
|
||||
speedBumpIndex = currentIndex;
|
||||
noAmbient = true;
|
||||
}
|
||||
mStackScroller.updateShelfIndex(shelfIndex, noAmbient);
|
||||
mStackScroller.updateSpeedBumpIndex(speedBumpIndex, noAmbient);
|
||||
}
|
||||
|
||||
public static boolean isTopLevelChild(Entry entry) {
|
||||
|
||||
@@ -36,7 +36,7 @@ public class AmbientState {
|
||||
private ActivatableNotificationView mActivatedChild;
|
||||
private float mOverScrollTopAmount;
|
||||
private float mOverScrollBottomAmount;
|
||||
private int mShelfIndex = -1;
|
||||
private int mSpeedBumpIndex = -1;
|
||||
private boolean mDark;
|
||||
private boolean mHideSensitive;
|
||||
private HeadsUpManager mHeadsUpManager;
|
||||
@@ -51,6 +51,7 @@ public class AmbientState {
|
||||
private int mZDistanceBetweenElements;
|
||||
private int mBaseZHeight;
|
||||
private int mMaxLayoutHeight;
|
||||
private ActivatableNotificationView mLastVisibleBackgroundChild;
|
||||
|
||||
public AmbientState(Context context) {
|
||||
reload(context);
|
||||
@@ -62,8 +63,7 @@ public class AmbientState {
|
||||
public void reload(Context context) {
|
||||
mZDistanceBetweenElements = Math.max(1, context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.z_distance_between_notifications));
|
||||
mBaseZHeight = (StackScrollAlgorithm.MAX_ITEMS_IN_BOTTOM_STACK + 1)
|
||||
* mZDistanceBetweenElements;
|
||||
mBaseZHeight = 4 * mZDistanceBetweenElements;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,12 +153,12 @@ public class AmbientState {
|
||||
return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
|
||||
}
|
||||
|
||||
public int getShelfIndex() {
|
||||
return mShelfIndex;
|
||||
public int getSpeedBumpIndex() {
|
||||
return mSpeedBumpIndex;
|
||||
}
|
||||
|
||||
public void setShelfIndex(int shelfIndex) {
|
||||
mShelfIndex = shelfIndex;
|
||||
public void setSpeedBumpIndex(int shelfIndex) {
|
||||
mSpeedBumpIndex = shelfIndex;
|
||||
}
|
||||
|
||||
public void setHeadsUpManager(HeadsUpManager headsUpManager) {
|
||||
@@ -228,4 +228,17 @@ public class AmbientState {
|
||||
public void setLayoutMaxHeight(int maxLayoutHeight) {
|
||||
mMaxLayoutHeight = maxLayoutHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last visible view of the host layout, that has a background, i.e the very last
|
||||
* view in the shade, without the clear all button.
|
||||
*/
|
||||
public void setLastVisibleBackgroundChild(
|
||||
ActivatableNotificationView lastVisibleBackgroundChild) {
|
||||
mLastVisibleBackgroundChild = lastVisibleBackgroundChild;
|
||||
}
|
||||
|
||||
public ActivatableNotificationView getLastVisibleBackgroundChild() {
|
||||
return mLastVisibleBackgroundChild;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class ExpandableViewState extends ViewState {
|
||||
public boolean dimmed;
|
||||
public boolean dark;
|
||||
public boolean hideSensitive;
|
||||
public boolean belowShelf;
|
||||
public boolean belowSpeedBump;
|
||||
public float shadowAlpha;
|
||||
public boolean inShelf;
|
||||
|
||||
@@ -121,7 +121,7 @@ public class ExpandableViewState extends ViewState {
|
||||
shadowAlpha = svs.shadowAlpha;
|
||||
dark = svs.dark;
|
||||
hideSensitive = svs.hideSensitive;
|
||||
belowShelf = svs.belowShelf;
|
||||
belowSpeedBump = svs.belowSpeedBump;
|
||||
clipTopAmount = svs.clipTopAmount;
|
||||
notGoneIndex = svs.notGoneIndex;
|
||||
location = svs.location;
|
||||
@@ -161,8 +161,8 @@ public class ExpandableViewState extends ViewState {
|
||||
expandableView.setHideSensitive(
|
||||
this.hideSensitive, false /* animated */, 0 /* delay */, 0 /* duration */);
|
||||
|
||||
// apply below shelf speedBump
|
||||
expandableView.setBelowShelf(this.belowShelf);
|
||||
// apply below shelf speed bump
|
||||
expandableView.setBelowSpeedBump(this.belowSpeedBump);
|
||||
|
||||
// apply dark
|
||||
expandableView.setDark(this.dark, false /* animate */, 0 /* delay */);
|
||||
@@ -211,8 +211,8 @@ public class ExpandableViewState extends ViewState {
|
||||
// start dimmed animation
|
||||
expandableView.setDimmed(this.dimmed, animationFilter.animateDimmed);
|
||||
|
||||
// apply below shelf state
|
||||
expandableView.setBelowShelf(this.belowShelf);
|
||||
// apply below the speed bump
|
||||
expandableView.setBelowSpeedBump(this.belowSpeedBump);
|
||||
|
||||
// start hiding sensitive animation
|
||||
expandableView.setHideSensitive(this.hideSensitive, animationFilter.animateHideSensitive,
|
||||
|
||||
@@ -479,7 +479,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
childState.dimmed = parentState.dimmed;
|
||||
childState.dark = parentState.dark;
|
||||
childState.hideSensitive = parentState.hideSensitive;
|
||||
childState.belowShelf = parentState.belowShelf;
|
||||
childState.belowSpeedBump = parentState.belowSpeedBump;
|
||||
childState.clipTopAmount = 0;
|
||||
childState.alpha = 0;
|
||||
if (i < firstOverflowIndex) {
|
||||
|
||||
@@ -135,8 +135,6 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
private Paint mDebugPaint;
|
||||
private int mContentHeight;
|
||||
private int mCollapsedSize;
|
||||
private int mBottomStackSlowDownHeight;
|
||||
private int mBottomStackPeekSize;
|
||||
private int mPaddingBetweenElements;
|
||||
private int mIncreasedPaddingBetweenElements;
|
||||
private int mTopPadding;
|
||||
@@ -424,11 +422,6 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
if (DEBUG) {
|
||||
int y = mTopPadding;
|
||||
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
|
||||
y = (int) (getLayoutHeight() - mBottomStackPeekSize
|
||||
- mBottomStackSlowDownHeight);
|
||||
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
|
||||
y = (int) (getLayoutHeight() - mBottomStackPeekSize);
|
||||
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
|
||||
y = (int) getLayoutHeight();
|
||||
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
|
||||
y = getHeight() - getEmptyBottomMargin();
|
||||
@@ -465,15 +458,12 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
mOverflingDistance = configuration.getScaledOverflingDistance();
|
||||
mCollapsedSize = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_min_height);
|
||||
mBottomStackPeekSize = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
|
||||
mStackScrollAlgorithm.initView(context);
|
||||
mAmbientState.reload(context);
|
||||
mPaddingBetweenElements = Math.max(1, context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_divider_height));
|
||||
mIncreasedPaddingBetweenElements = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
|
||||
mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength();
|
||||
mMinTopOverScrollToEscape = getResources().getDimensionPixelSize(
|
||||
R.dimen.min_top_overscroll_to_qs);
|
||||
mStatusBarHeight = getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
|
||||
@@ -537,8 +527,8 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
}
|
||||
}
|
||||
|
||||
public void updateShelfIndex(int newIndex, boolean noAmbient) {
|
||||
mAmbientState.setShelfIndex(newIndex);
|
||||
public void updateSpeedBumpIndex(int newIndex, boolean noAmbient) {
|
||||
mAmbientState.setSpeedBumpIndex(newIndex);
|
||||
mNoAmbient = noAmbient;
|
||||
}
|
||||
|
||||
@@ -777,13 +767,12 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
private float getAppearEndPosition() {
|
||||
int appearPosition;
|
||||
if (mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) {
|
||||
appearPosition = mHeadsUpManager.getTopHeadsUpPinnedHeight() + mBottomStackPeekSize
|
||||
+ mBottomStackSlowDownHeight;
|
||||
appearPosition = mHeadsUpManager.getTopHeadsUpPinnedHeight();
|
||||
} else {
|
||||
appearPosition = getFirstItemMinHeight();
|
||||
if (mAmbientState.getShelfIndex() > 1) {
|
||||
appearPosition += mShelf.getIntrinsicHeight();
|
||||
}
|
||||
}
|
||||
if (getNotGoneChildCount() > 1) {
|
||||
appearPosition += mShelf.getIntrinsicHeight();
|
||||
}
|
||||
return appearPosition + (onKeyguard() ? mTopPadding : mIntrinsicPadding);
|
||||
}
|
||||
@@ -826,14 +815,6 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
return firstChild != null ? firstChild.getMinHeight() : mCollapsedSize;
|
||||
}
|
||||
|
||||
public int getBottomStackPeekSize() {
|
||||
return mBottomStackPeekSize;
|
||||
}
|
||||
|
||||
public int getBottomStackSlowDownHeight() {
|
||||
return mBottomStackSlowDownHeight;
|
||||
}
|
||||
|
||||
public void setLongPressListener(SwipeHelper.LongPressListener listener) {
|
||||
mSwipeHelper.setLongPressListener(listener);
|
||||
mLongPressListener = listener;
|
||||
@@ -1803,8 +1784,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
|
||||
private int getScrollRange() {
|
||||
int contentHeight = getContentHeight();
|
||||
int scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize
|
||||
+ mBottomStackSlowDownHeight);
|
||||
int scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight);
|
||||
int imeInset = getImeInset();
|
||||
scrollRange += Math.min(imeInset, Math.max(0,
|
||||
getContentHeight() - (getHeight() - imeInset)));
|
||||
@@ -1822,7 +1802,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child.getVisibility() != View.GONE) {
|
||||
if (child.getVisibility() != View.GONE && child != mShelf) {
|
||||
return (ExpandableView) child;
|
||||
}
|
||||
}
|
||||
@@ -1869,7 +1849,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
int childCount = getChildCount();
|
||||
for (int i = childCount - 1; i >= 0; i--) {
|
||||
View child = getChildAt(i);
|
||||
if (child.getVisibility() != View.GONE) {
|
||||
if (child.getVisibility() != View.GONE && child != mShelf) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
@@ -1884,7 +1864,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
int count = 0;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
ExpandableView child = (ExpandableView) getChildAt(i);
|
||||
if (child.getVisibility() != View.GONE && !child.willBeGone()) {
|
||||
if (child.getVisibility() != View.GONE && !child.willBeGone() && child != mShelf) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -2311,8 +2291,11 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
final ExpandableView firstChild = getFirstChildNotGone();
|
||||
final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight()
|
||||
: mCollapsedSize;
|
||||
return mIntrinsicPadding + firstChildMinHeight + mBottomStackPeekSize
|
||||
+ mBottomStackSlowDownHeight;
|
||||
int shelfHeight = 0;
|
||||
if (mLastVisibleBackgroundChild != null) {
|
||||
shelfHeight = mShelf.getIntrinsicHeight();
|
||||
}
|
||||
return mIntrinsicPadding + firstChildMinHeight + shelfHeight;
|
||||
}
|
||||
|
||||
private int clampPadding(int desiredPadding) {
|
||||
@@ -2651,6 +2634,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
}
|
||||
mFirstVisibleBackgroundChild = firstChild;
|
||||
mLastVisibleBackgroundChild = lastChild;
|
||||
mAmbientState.setLastVisibleBackgroundChild(lastChild);
|
||||
}
|
||||
|
||||
private void onViewAddedInternal(View child) {
|
||||
@@ -3152,13 +3136,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
}
|
||||
|
||||
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);
|
||||
return Math.max(mMaxLayoutHeight - mContentHeight, 0);
|
||||
}
|
||||
|
||||
public void onExpansionStarted() {
|
||||
@@ -3268,20 +3246,18 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
if (row.isChildInGroup()) {
|
||||
endPosition += row.getNotificationParent().getTranslationY();
|
||||
}
|
||||
int stackEnd = getStackEndPosition();
|
||||
if (endPosition > stackEnd) {
|
||||
setOwnScrollY((int) (mOwnScrollY + endPosition - stackEnd));
|
||||
int layoutEnd = mMaxLayoutHeight + (int) mStackTranslation;
|
||||
if (row != mLastVisibleBackgroundChild) {
|
||||
layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
|
||||
}
|
||||
if (endPosition > layoutEnd) {
|
||||
setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd));
|
||||
mDisallowScrollingInThisMotion = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getStackEndPosition() {
|
||||
return mMaxLayoutHeight - mBottomStackPeekSize - mBottomStackSlowDownHeight
|
||||
+ mPaddingBetweenElements + (int) mStackTranslation;
|
||||
}
|
||||
|
||||
public void setOnHeightChangedListener(
|
||||
ExpandableView.OnHeightChangedListener mOnHeightChangedListener) {
|
||||
this.mOnHeightChangedListener = mOnHeightChangedListener;
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.stack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A Functor which interpolates the stack distance linearly based on base values.
|
||||
* The base values are based on an interpolation between a linear function and a
|
||||
* quadratic function
|
||||
*/
|
||||
public class PiecewiseLinearIndentationFunctor extends StackIndentationFunctor {
|
||||
|
||||
private final ArrayList<Float> mBaseValues;
|
||||
private final float mLinearPart;
|
||||
|
||||
/**
|
||||
* @param maxItemsInStack The maximum number of items which should be visible at the same time,
|
||||
* i.e the function returns totalTransitionDistance for the element with
|
||||
* index maxItemsInStack
|
||||
* @param peekSize The visual appearance of this is how far the cards in the stack peek
|
||||
* out below the top card and it is measured in real pixels.
|
||||
* Note that the visual appearance does not necessarily always correspond to
|
||||
* the actual visual distance below the top card but is a maximum,
|
||||
* achieved when the next card just starts transitioning into the stack and
|
||||
* the stack is full.
|
||||
* If distanceToPeekStart is 0, we directly start at the peek, otherwise the
|
||||
* first element transitions between 0 and distanceToPeekStart.
|
||||
* Visualization:
|
||||
* --------------------------------------------------- ---
|
||||
* | | |
|
||||
* | FIRST ITEM | | <- distanceToPeekStart
|
||||
* | | |
|
||||
* |---------------------------------------------------| --- ---
|
||||
* |__________________SECOND ITEM______________________| | <- peekSize
|
||||
* |===================================================| _|_
|
||||
*
|
||||
* @param distanceToPeekStart The distance to the start of the peak.
|
||||
* @param linearPart The interpolation factor between the linear and the quadratic amount taken.
|
||||
* This factor must be somewhere in [0 , 1]
|
||||
*/
|
||||
PiecewiseLinearIndentationFunctor(int maxItemsInStack,
|
||||
int peekSize,
|
||||
int distanceToPeekStart,
|
||||
float linearPart) {
|
||||
super(maxItemsInStack, peekSize, distanceToPeekStart);
|
||||
mBaseValues = new ArrayList<Float>(maxItemsInStack+1);
|
||||
initBaseValues();
|
||||
mLinearPart = linearPart;
|
||||
}
|
||||
|
||||
private void initBaseValues() {
|
||||
int sumOfSquares = getSumOfSquares(mMaxItemsInStack-1);
|
||||
int totalWeight = 0;
|
||||
mBaseValues.add(0.0f);
|
||||
for (int i = 0; i < mMaxItemsInStack - 1; i++) {
|
||||
totalWeight += (mMaxItemsInStack - i - 1) * (mMaxItemsInStack - i - 1);
|
||||
mBaseValues.add((float) totalWeight / sumOfSquares);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sum of squares up to and including n, i.e sum(i * i, 1, n)
|
||||
*
|
||||
* @param n the maximum square to include
|
||||
* @return
|
||||
*/
|
||||
private int getSumOfSquares(int n) {
|
||||
return n * (n + 1) * (2 * n + 1) / 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue(float itemsBefore) {
|
||||
if (mStackStartsAtPeek) {
|
||||
// We directly start at the stack, so no initial interpolation.
|
||||
itemsBefore++;
|
||||
}
|
||||
if (itemsBefore < 0) {
|
||||
return 0;
|
||||
} else if (itemsBefore >= mMaxItemsInStack) {
|
||||
return mTotalTransitionDistance;
|
||||
}
|
||||
int below = (int) itemsBefore;
|
||||
float partialIn = itemsBefore - below;
|
||||
|
||||
if (below == 0) {
|
||||
return mDistanceToPeekStart * partialIn;
|
||||
} else {
|
||||
float result = mDistanceToPeekStart;
|
||||
float progress = mBaseValues.get(below - 1) * (1 - partialIn)
|
||||
+ mBaseValues.get(below) * partialIn;
|
||||
result += (progress * (1 - mLinearPart)
|
||||
+ (itemsBefore - 1) / (mMaxItemsInStack - 1) * mLinearPart) * mPeekSize;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.stack;
|
||||
|
||||
/**
|
||||
* A functor which can be queried for offset given the number of items before it.
|
||||
*/
|
||||
public abstract class StackIndentationFunctor {
|
||||
|
||||
protected int mTotalTransitionDistance;
|
||||
protected int mDistanceToPeekStart;
|
||||
protected int mMaxItemsInStack;
|
||||
protected int mPeekSize;
|
||||
protected boolean mStackStartsAtPeek;
|
||||
|
||||
/**
|
||||
* @param maxItemsInStack The maximum number of items which should be visible at the same time,
|
||||
* i.e the function returns totalTransitionDistance for the element with
|
||||
* index maxItemsInStack
|
||||
* @param peekSize The visual appearance of this is how far the cards in the stack peek
|
||||
* out below the top card and it is measured in real pixels.
|
||||
* Note that the visual appearance does not necessarily always correspond to
|
||||
* the actual visual distance below the top card but is a maximum,
|
||||
* achieved when the next card just starts transitioning into the stack and
|
||||
* the stack is full.
|
||||
* If distanceToPeekStart is 0, we directly start at the peek, otherwise the
|
||||
* first element transitions between 0 and distanceToPeekStart.
|
||||
* Visualization:
|
||||
* --------------------------------------------------- ---
|
||||
* | | |
|
||||
* | FIRST ITEM | | <- distanceToPeekStart
|
||||
* | | |
|
||||
* |---------------------------------------------------| --- ---
|
||||
* |__________________SECOND ITEM______________________| | <- peekSize
|
||||
* |===================================================| _|_
|
||||
*
|
||||
* @param distanceToPeekStart The distance to the start of the peak.
|
||||
*/
|
||||
StackIndentationFunctor(int maxItemsInStack, int peekSize, int distanceToPeekStart) {
|
||||
mDistanceToPeekStart = distanceToPeekStart;
|
||||
mStackStartsAtPeek = mDistanceToPeekStart == 0;
|
||||
mMaxItemsInStack = maxItemsInStack;
|
||||
mPeekSize = peekSize;
|
||||
updateTotalTransitionDistance();
|
||||
|
||||
}
|
||||
|
||||
private void updateTotalTransitionDistance() {
|
||||
mTotalTransitionDistance = mDistanceToPeekStart + mPeekSize;
|
||||
}
|
||||
|
||||
public void setPeekSize(int mPeekSize) {
|
||||
this.mPeekSize = mPeekSize;
|
||||
updateTotalTransitionDistance();
|
||||
}
|
||||
|
||||
public void setDistanceToPeekStart(int distanceToPeekStart) {
|
||||
mDistanceToPeekStart = distanceToPeekStart;
|
||||
mStackStartsAtPeek = mDistanceToPeekStart == 0;
|
||||
updateTotalTransitionDistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset of this Functor given a the quantity of items before it
|
||||
*
|
||||
* @param itemsBefore how many items are already in the stack before this element
|
||||
* @return the offset
|
||||
*/
|
||||
public abstract float getValue(float itemsBefore);
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import com.android.systemui.statusbar.DismissView;
|
||||
import com.android.systemui.statusbar.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.ExpandableView;
|
||||
import com.android.systemui.statusbar.NotificationShelf;
|
||||
import com.android.systemui.statusbar.notification.FakeShadowView;
|
||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -42,18 +41,12 @@ public class StackScrollAlgorithm {
|
||||
|
||||
private static final String LOG_TAG = "StackScrollAlgorithm";
|
||||
|
||||
public static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
|
||||
|
||||
private int mPaddingBetweenElements;
|
||||
private int mIncreasedPaddingBetweenElements;
|
||||
private int mCollapsedSize;
|
||||
private int mBottomStackPeekSize;
|
||||
|
||||
private StackIndentationFunctor mBottomStackIndentationFunctor;
|
||||
|
||||
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
|
||||
private boolean mIsExpanded;
|
||||
private int mBottomStackSlowDownLength;
|
||||
private int mStatusBarHeight;
|
||||
|
||||
public StackScrollAlgorithm(Context context) {
|
||||
@@ -64,26 +57,13 @@ public class StackScrollAlgorithm {
|
||||
initConstants(context);
|
||||
}
|
||||
|
||||
public int getBottomStackSlowDownLength() {
|
||||
return mBottomStackSlowDownLength + mPaddingBetweenElements;
|
||||
}
|
||||
|
||||
private void initConstants(Context context) {
|
||||
mPaddingBetweenElements = Math.max(1, context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_divider_height));
|
||||
mPaddingBetweenElements = context.getResources().getDimensionPixelSize(
|
||||
R.dimen.notification_divider_height);
|
||||
mIncreasedPaddingBetweenElements = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
|
||||
mCollapsedSize = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_min_height);
|
||||
mBottomStackPeekSize = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
|
||||
mBottomStackSlowDownLength = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
|
||||
mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
|
||||
MAX_ITEMS_IN_BOTTOM_STACK,
|
||||
mBottomStackPeekSize,
|
||||
getBottomStackSlowDownLength(),
|
||||
0.5f);
|
||||
mStatusBarHeight = context.getResources().getDimensionPixelSize(R.dimen.status_bar_height);
|
||||
}
|
||||
|
||||
@@ -106,7 +86,8 @@ public class StackScrollAlgorithm {
|
||||
handleDraggedViews(ambientState, resultState, algorithmState);
|
||||
updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
|
||||
updateClipping(resultState, algorithmState, ambientState);
|
||||
updateShelfState(resultState, algorithmState, ambientState);
|
||||
updateSpeedBumpState(resultState, algorithmState, ambientState);
|
||||
updateShelfState(resultState, ambientState);
|
||||
getNotificationChildrenStates(resultState, algorithmState);
|
||||
}
|
||||
|
||||
@@ -122,20 +103,23 @@ public class StackScrollAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateShelfState(StackScrollState resultState,
|
||||
private void updateSpeedBumpState(StackScrollState resultState,
|
||||
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
|
||||
int childCount = algorithmState.visibleChildren.size();
|
||||
int shelfIndex = ambientState.getShelfIndex();
|
||||
int belowSpeedBump = ambientState.getSpeedBumpIndex();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = algorithmState.visibleChildren.get(i);
|
||||
ExpandableViewState childViewState = resultState.getViewStateForView(child);
|
||||
|
||||
// The speed bump can also be gone, so equality needs to be taken when comparing
|
||||
// indices.
|
||||
childViewState.belowShelf = i >= shelfIndex;
|
||||
childViewState.belowSpeedBump = i >= belowSpeedBump;
|
||||
}
|
||||
|
||||
}
|
||||
private void updateShelfState(StackScrollState resultState, AmbientState ambientState) {
|
||||
NotificationShelf shelf = ambientState.getShelf();
|
||||
shelf.updateState(resultState, algorithmState, ambientState);
|
||||
shelf.updateState(resultState, ambientState);
|
||||
}
|
||||
|
||||
private void updateClipping(StackScrollState resultState,
|
||||
@@ -243,8 +227,6 @@ public class StackScrollAlgorithm {
|
||||
*/
|
||||
private void initAlgorithmState(StackScrollState resultState, StackScrollAlgorithmState state,
|
||||
AmbientState ambientState) {
|
||||
state.itemsInBottomStack = 0.0f;
|
||||
state.partialInBottom = 0.0f;
|
||||
float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
|
||||
|
||||
int scrollY = ambientState.getScrollY();
|
||||
@@ -322,72 +304,35 @@ public class StackScrollAlgorithm {
|
||||
private void updatePositionsForState(StackScrollState resultState,
|
||||
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
|
||||
|
||||
// The starting position of the bottom stack peek
|
||||
float bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize;
|
||||
|
||||
// The position where the bottom stack starts.
|
||||
float bottomStackStart = bottomPeekStart - mBottomStackSlowDownLength;
|
||||
|
||||
// The y coordinate of the current child.
|
||||
float currentYPosition = -algorithmState.scrollY;
|
||||
int childCount = algorithmState.visibleChildren.size();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
currentYPosition = updateChild(i, resultState, algorithmState, ambientState,
|
||||
currentYPosition, bottomStackStart);
|
||||
currentYPosition);
|
||||
}
|
||||
}
|
||||
|
||||
protected float updateChild(int i, StackScrollState resultState,
|
||||
StackScrollAlgorithmState algorithmState, AmbientState ambientState,
|
||||
float currentYPosition, float bottomStackStart) {
|
||||
float currentYPosition) {
|
||||
ExpandableView child = algorithmState.visibleChildren.get(i);
|
||||
ExpandableViewState childViewState = resultState.getViewStateForView(child);
|
||||
childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
|
||||
int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
|
||||
int childHeight = getMaxAllowedChildHeight(child);
|
||||
int collapsedHeight = child.getCollapsedHeight();
|
||||
childViewState.yTranslation = currentYPosition;
|
||||
boolean belowShelf = i >= ambientState.getShelfIndex();
|
||||
boolean isDismissView = child instanceof DismissView;
|
||||
if (i == 0) {
|
||||
updateFirstChildHeight(child, childViewState, childHeight, algorithmState, ambientState,
|
||||
belowShelf);
|
||||
updateFirstChildHeight(child, childViewState, childHeight, algorithmState, ambientState);
|
||||
}
|
||||
|
||||
// The y position after this element
|
||||
float nextYPosition = currentYPosition + childHeight +
|
||||
paddingAfterChild;
|
||||
if (nextYPosition >= bottomStackStart && belowShelf && !isDismissView) {
|
||||
// Case 1:
|
||||
// We are in the bottom stack.
|
||||
if (currentYPosition >= bottomStackStart) {
|
||||
// According to the regular scroll view we are fully translated out of the
|
||||
// bottom of the screen so we are fully in the bottom stack
|
||||
updateStateForChildFullyInBottomStack(algorithmState,
|
||||
bottomStackStart, childViewState, collapsedHeight, ambientState, child);
|
||||
} else {
|
||||
// According to the regular scroll view we are currently translating out of /
|
||||
// into the bottom of the screen
|
||||
updateStateForChildTransitioningInBottom(algorithmState,
|
||||
bottomStackStart, child, currentYPosition,
|
||||
childViewState, childHeight);
|
||||
}
|
||||
childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
|
||||
if (isDismissView) {
|
||||
childViewState.yTranslation = Math.min(childViewState.yTranslation,
|
||||
ambientState.getInnerHeight() - childHeight);
|
||||
} else {
|
||||
// Case 2:
|
||||
// We are in the regular scroll area.
|
||||
childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
|
||||
if (belowShelf) {
|
||||
if (!isDismissView) {
|
||||
clampPositionToBottomStackStart(childViewState, childViewState.height,
|
||||
childHeight,
|
||||
ambientState);
|
||||
} else {
|
||||
childViewState.yTranslation = Math.min(childViewState.yTranslation,
|
||||
ambientState.getInnerHeight() - childHeight);
|
||||
}
|
||||
} else {
|
||||
clampPositionToShelf(childViewState, ambientState);
|
||||
}
|
||||
clampPositionToShelf(childViewState, ambientState);
|
||||
}
|
||||
|
||||
currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
|
||||
@@ -475,30 +420,6 @@ public class StackScrollAlgorithm {
|
||||
childState.yTranslation = newTranslation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamp the yTranslation of the child down such that its end is at most on the beginning of
|
||||
* the bottom stack.
|
||||
*
|
||||
* @param childViewState the view state of the child
|
||||
* @param childHeight the height of this child
|
||||
* @param minHeight the minumum Height of the View
|
||||
*/
|
||||
private void clampPositionToBottomStackStart(ExpandableViewState childViewState,
|
||||
int childHeight, int minHeight, AmbientState ambientState) {
|
||||
|
||||
int bottomStackStart = ambientState.getInnerHeight()
|
||||
- mBottomStackPeekSize - mBottomStackSlowDownLength;
|
||||
int childStart = bottomStackStart - childHeight;
|
||||
if (childStart < childViewState.yTranslation) {
|
||||
float newHeight = bottomStackStart - childViewState.yTranslation;
|
||||
if (newHeight < minHeight) {
|
||||
newHeight = minHeight;
|
||||
childViewState.yTranslation = bottomStackStart - minHeight;
|
||||
}
|
||||
childViewState.height = (int) newHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamp the height of the child down such that its end is at most on the beginning of
|
||||
* the shelf.
|
||||
@@ -528,58 +449,6 @@ public class StackScrollAlgorithm {
|
||||
return child == null? mCollapsedSize : child.getHeight();
|
||||
}
|
||||
|
||||
private void updateStateForChildTransitioningInBottom(StackScrollAlgorithmState algorithmState,
|
||||
float transitioningPositionStart, ExpandableView child, float currentYPosition,
|
||||
ExpandableViewState childViewState, int childHeight) {
|
||||
|
||||
// This is the transitioning element on top of bottom stack, calculate how far we are in.
|
||||
algorithmState.partialInBottom = 1.0f - (
|
||||
(transitioningPositionStart - currentYPosition) / (childHeight +
|
||||
getPaddingAfterChild(algorithmState, child)));
|
||||
|
||||
// the offset starting at the transitionPosition of the bottom stack
|
||||
float offset = mBottomStackIndentationFunctor.getValue(algorithmState.partialInBottom);
|
||||
algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
|
||||
int newHeight = childHeight;
|
||||
if (childHeight > child.getCollapsedHeight()) {
|
||||
newHeight = (int) Math.max(Math.min(transitioningPositionStart + offset -
|
||||
getPaddingAfterChild(algorithmState, child) - currentYPosition, childHeight),
|
||||
child.getCollapsedHeight());
|
||||
childViewState.height = newHeight;
|
||||
}
|
||||
childViewState.yTranslation = transitioningPositionStart + offset - newHeight
|
||||
- getPaddingAfterChild(algorithmState, child);
|
||||
childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
|
||||
}
|
||||
|
||||
private void updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
|
||||
float transitioningPositionStart, ExpandableViewState childViewState,
|
||||
int collapsedHeight, AmbientState ambientState, ExpandableView child) {
|
||||
float currentYPosition;
|
||||
algorithmState.itemsInBottomStack += 1.0f;
|
||||
if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) {
|
||||
// We are visually entering the bottom stack
|
||||
currentYPosition = transitioningPositionStart
|
||||
+ mBottomStackIndentationFunctor.getValue(algorithmState.itemsInBottomStack)
|
||||
- getPaddingAfterChild(algorithmState, child);
|
||||
childViewState.location = ExpandableViewState.LOCATION_BOTTOM_STACK_PEEKING;
|
||||
} else {
|
||||
// we are fully inside the stack
|
||||
if (algorithmState.itemsInBottomStack > MAX_ITEMS_IN_BOTTOM_STACK + 2) {
|
||||
childViewState.hidden = true;
|
||||
childViewState.shadowAlpha = 0.0f;
|
||||
} else if (algorithmState.itemsInBottomStack
|
||||
> MAX_ITEMS_IN_BOTTOM_STACK + 1) {
|
||||
childViewState.shadowAlpha = 1.0f - algorithmState.partialInBottom;
|
||||
}
|
||||
childViewState.location = ExpandableViewState.LOCATION_BOTTOM_STACK_HIDDEN;
|
||||
currentYPosition = ambientState.getInnerHeight();
|
||||
}
|
||||
childViewState.height = collapsedHeight;
|
||||
childViewState.yTranslation = currentYPosition - collapsedHeight;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the height of the first child i.e clamp it to the bottom stack
|
||||
* @param child the child to update
|
||||
@@ -587,23 +456,15 @@ public class StackScrollAlgorithm {
|
||||
* @param childHeight the height of the child
|
||||
* @param algorithmState the algorithm state
|
||||
* @param ambientState The ambient state of the algorithm
|
||||
* @param belowShelf whether it is below the shelf
|
||||
*/
|
||||
protected void updateFirstChildHeight(ExpandableView child, ExpandableViewState childViewState,
|
||||
int childHeight, StackScrollAlgorithmState algorithmState,
|
||||
AmbientState ambientState, boolean belowShelf) {
|
||||
AmbientState ambientState) {
|
||||
|
||||
int bottomStart;
|
||||
if (belowShelf) {
|
||||
// The starting position of the bottom stack peek
|
||||
bottomStart = ambientState.getInnerHeight() - mBottomStackPeekSize -
|
||||
mBottomStackSlowDownLength;
|
||||
} else {
|
||||
bottomStart = ambientState.getInnerHeight();
|
||||
if (algorithmState.visibleChildren.size() > 1) {
|
||||
bottomStart -= ambientState.getShelf().getIntrinsicHeight()
|
||||
- mPaddingBetweenElements;
|
||||
}
|
||||
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
|
||||
@@ -623,39 +484,19 @@ public class StackScrollAlgorithm {
|
||||
int childCount = algorithmState.visibleChildren.size();
|
||||
float childrenOnTop = 0.0f;
|
||||
for (int i = childCount - 1; i >= 0; i--) {
|
||||
updateChildZValue(i, childCount, childrenOnTop,
|
||||
updateChildZValue(i, childrenOnTop,
|
||||
resultState, algorithmState, ambientState);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateChildZValue(int i, int childCount, float childrenOnTop,
|
||||
protected void updateChildZValue(int i, float childrenOnTop,
|
||||
StackScrollState resultState, StackScrollAlgorithmState algorithmState,
|
||||
AmbientState ambientState) {
|
||||
ExpandableView child = algorithmState.visibleChildren.get(i);
|
||||
ExpandableViewState childViewState = resultState.getViewStateForView(child);
|
||||
int zDistanceBetweenElements = ambientState.getZDistanceBetweenElements();
|
||||
float baseZ = ambientState.getBaseZHeight();
|
||||
if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
|
||||
// We are in the bottom stack
|
||||
float numItemsAbove = i - (childCount - 1 - algorithmState.itemsInBottomStack);
|
||||
float zSubtraction;
|
||||
if (numItemsAbove <= 1.0f) {
|
||||
float factor = 0.2f;
|
||||
// Lets fade in slower to the threshold to make the shadow fade in look nicer
|
||||
if (numItemsAbove <= factor) {
|
||||
zSubtraction = FakeShadowView.SHADOW_SIBLING_TRESHOLD
|
||||
* numItemsAbove * (1.0f / factor);
|
||||
} else {
|
||||
zSubtraction = FakeShadowView.SHADOW_SIBLING_TRESHOLD
|
||||
+ (numItemsAbove - factor) * (1.0f / (1.0f - factor))
|
||||
* (zDistanceBetweenElements
|
||||
- FakeShadowView.SHADOW_SIBLING_TRESHOLD);
|
||||
}
|
||||
} else {
|
||||
zSubtraction = numItemsAbove * zDistanceBetweenElements;
|
||||
}
|
||||
childViewState.zTranslation = baseZ - zSubtraction;
|
||||
} else if (child.mustStayOnScreen()
|
||||
if (child.mustStayOnScreen()
|
||||
&& childViewState.yTranslation < ambientState.getTopPadding()
|
||||
+ ambientState.getStackTranslation()) {
|
||||
if (childrenOnTop != 0.0f) {
|
||||
@@ -688,25 +529,6 @@ public class StackScrollAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMaxSizeInitialized(ExpandableView child) {
|
||||
if (child instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||
return row.isMaxExpandHeightInitialized();
|
||||
}
|
||||
return child == null || child.getWidth() != 0;
|
||||
}
|
||||
|
||||
private View findFirstVisibleChild(ViewGroup container) {
|
||||
int childCount = container.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = container.getChildAt(i);
|
||||
if (child.getVisibility() != View.GONE) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setIsExpanded(boolean isExpanded) {
|
||||
this.mIsExpanded = isExpanded;
|
||||
}
|
||||
@@ -718,16 +540,6 @@ public class StackScrollAlgorithm {
|
||||
*/
|
||||
public int scrollY;
|
||||
|
||||
/**
|
||||
* The quantity of items which are in the bottom stack.
|
||||
*/
|
||||
public float itemsInBottomStack;
|
||||
|
||||
/**
|
||||
* how far in is the element currently transitioning into the bottom stack
|
||||
*/
|
||||
public float partialInBottom;
|
||||
|
||||
/**
|
||||
* The children from the host view which are not gone.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user