Methods Summary |
---|
private void | clampPositionToBottomStackStart(StackScrollState.ViewState childViewState, int childHeight)Clamp the yTranslation of the child down such that its end is at most on the beginning of
the bottom stack.
childViewState.yTranslation = Math.min(childViewState.yTranslation,
mInnerHeight - mBottomStackPeekSize - mCollapseSecondCardPadding - childHeight);
|
private void | clampPositionToTopStackEnd(StackScrollState.ViewState childViewState, int childHeight)Clamp the yTranslation of the child up such that its end is at lest on the end of the top
stack.get
childViewState.yTranslation = Math.max(childViewState.yTranslation,
mCollapsedSize - childHeight);
|
private void | clampYTranslation(StackScrollState.ViewState childViewState, int childHeight)Clamp the yTranslation both up and down to valid positions.
clampPositionToBottomStackStart(childViewState, childHeight);
clampPositionToTopStackEnd(childViewState, childHeight);
|
private android.view.View | findFirstVisibleChild(android.view.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;
|
private void | findNumberOfItemsInTopStackAndUpdateState(StackScrollState resultState, com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState)Find the number of items in the top stack and update the result state if needed.
// The y Position if the element would be in a regular scrollView
float yPositionInScrollView = 0.0f;
int childCount = algorithmState.visibleChildren.size();
// find the number of elements in the top stack.
for (int i = 0; i < childCount; i++) {
ExpandableView child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
int childHeight = getMaxAllowedChildHeight(child);
float yPositionInScrollViewAfterElement = yPositionInScrollView
+ childHeight
+ mPaddingBetweenElements;
if (yPositionInScrollView < algorithmState.scrollY) {
if (i == 0 && algorithmState.scrollY <= mCollapsedSize) {
// The starting position of the bottom stack peek
int bottomPeekStart = mInnerHeight - mBottomStackPeekSize -
mCollapseSecondCardPadding;
// Collapse and expand the first child while the shade is being expanded
float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
? mFirstChildMaxHeight
: childHeight;
childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
mCollapsedSize);
algorithmState.itemsInTopStack = 1.0f;
} else if (yPositionInScrollViewAfterElement < algorithmState.scrollY) {
// According to the regular scroll view we are fully off screen
algorithmState.itemsInTopStack += 1.0f;
if (i == 0) {
childViewState.height = mCollapsedSize;
}
} else {
// According to the regular scroll view we are partially off screen
// How much did we scroll into this child
algorithmState.scrolledPixelsTop = algorithmState.scrollY
- yPositionInScrollView;
algorithmState.partialInTop = (algorithmState.scrolledPixelsTop) / (childHeight
+ mPaddingBetweenElements);
// Our element can be expanded, so this can get negative
algorithmState.partialInTop = Math.max(0.0f, algorithmState.partialInTop);
algorithmState.itemsInTopStack += algorithmState.partialInTop;
if (i == 0) {
// If it is expanded we have to collapse it to a new size
float newSize = yPositionInScrollViewAfterElement
- mPaddingBetweenElements
- algorithmState.scrollY + mCollapsedSize;
newSize = Math.max(mCollapsedSize, newSize);
algorithmState.itemsInTopStack = 1.0f;
childViewState.height = (int) newSize;
}
algorithmState.lastTopStackIndex = i;
break;
}
} else {
algorithmState.lastTopStackIndex = i - 1;
// We are already past the stack so we can end the loop
break;
}
yPositionInScrollView = yPositionInScrollViewAfterElement;
}
|
public int | getBottomStackSlowDownLength()
return mBottomStackSlowDownLength + mPaddingBetweenElements;
|
private int | getMaxAllowedChildHeight(android.view.View child)
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
return row.getIntrinsicHeight();
} else if (child instanceof ExpandableView) {
ExpandableView expandableView = (ExpandableView) child;
return expandableView.getActualHeight();
}
return child == null? mCollapsedSize : child.getHeight();
|
public void | getStackScrollState(AmbientState ambientState, StackScrollState resultState)
// The state of the local variables are saved in an algorithmState to easily subdivide it
// into multiple phases.
StackScrollAlgorithmState algorithmState = mTempAlgorithmState;
// First we reset the view states to their default values.
resultState.resetViewStates();
algorithmState.itemsInTopStack = 0.0f;
algorithmState.partialInTop = 0.0f;
algorithmState.lastTopStackIndex = 0;
algorithmState.scrolledPixelsTop = 0;
algorithmState.itemsInBottomStack = 0.0f;
algorithmState.partialInBottom = 0.0f;
float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
int scrollY = ambientState.getScrollY();
// Due to the overScroller, the stackscroller can have negative scroll state. This is
// already accounted for by the top padding and doesn't need an additional adaption
scrollY = Math.max(0, scrollY);
algorithmState.scrollY = (int) (scrollY + mCollapsedSize + bottomOverScroll);
updateVisibleChildren(resultState, algorithmState);
// Phase 1:
findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState);
// Phase 2:
updatePositionsForState(resultState, algorithmState);
// Phase 3:
updateZValuesForState(resultState, algorithmState);
handleDraggedViews(ambientState, resultState, algorithmState);
updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
updateClipping(resultState, algorithmState);
updateSpeedBumpState(resultState, algorithmState, ambientState.getSpeedBumpIndex());
|
private void | handleDraggedViews(AmbientState ambientState, StackScrollState resultState, com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState)Handle the special state when views are being dragged
ArrayList<View> draggedViews = ambientState.getDraggedViews();
for (View draggedView : draggedViews) {
int childIndex = algorithmState.visibleChildren.indexOf(draggedView);
if (childIndex >= 0 && childIndex < algorithmState.visibleChildren.size() - 1) {
View nextChild = algorithmState.visibleChildren.get(childIndex + 1);
if (!draggedViews.contains(nextChild)) {
// only if the view is not dragged itself we modify its state to be fully
// visible
StackScrollState.ViewState viewState = resultState.getViewStateForView(
nextChild);
// The child below the dragged one must be fully visible
viewState.alpha = 1;
}
// Lets set the alpha to the one it currently has, as its currently being dragged
StackScrollState.ViewState viewState = resultState.getViewStateForView(draggedView);
// The dragged child should keep the set alpha
viewState.alpha = draggedView.getAlpha();
}
}
|
private void | initConstants(android.content.Context context)
mPaddingBetweenElementsDimmed = context.getResources()
.getDimensionPixelSize(R.dimen.notification_padding_dimmed);
mPaddingBetweenElementsNormal = context.getResources()
.getDimensionPixelSize(R.dimen.notification_padding);
mCollapsedSize = context.getResources()
.getDimensionPixelSize(R.dimen.notification_min_height);
mMaxNotificationHeight = context.getResources()
.getDimensionPixelSize(R.dimen.notification_max_height);
mTopStackPeekSize = context.getResources()
.getDimensionPixelSize(R.dimen.top_stack_peek_amount);
mBottomStackPeekSize = context.getResources()
.getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
mZDistanceBetweenElements = context.getResources()
.getDimensionPixelSize(R.dimen.z_distance_between_notifications);
mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
mBottomStackSlowDownLength = context.getResources()
.getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
mTopStackSlowDownLength = context.getResources()
.getDimensionPixelSize(R.dimen.top_stack_slow_down_length);
mRoundedRectCornerRadius = context.getResources().getDimensionPixelSize(
R.dimen.notification_material_rounded_rect_radius);
mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
R.dimen.notification_collapse_second_card_padding);
mScaleDimmed = context.getResources().getDisplayMetrics().densityDpi
>= DisplayMetrics.DENSITY_XXHIGH;
|
private boolean | isMaxSizeInitialized(com.android.systemui.statusbar.ExpandableView child)
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
return row.isMaxExpandHeightInitialized();
}
return child == null || child.getWidth() != 0;
|
public void | notifyChildrenChanged(android.view.ViewGroup hostView)
if (mIsExpansionChanging) {
hostView.post(new Runnable() {
@Override
public void run() {
updateFirstChildHeightWhileExpanding(hostView);
}
});
}
|
public void | onExpansionStarted(StackScrollState currentState)
mIsExpansionChanging = true;
mExpandedOnStart = mIsExpanded;
ViewGroup hostView = currentState.getHostView();
updateFirstChildHeightWhileExpanding(hostView);
|
public void | onExpansionStopped()
mIsExpansionChanging = false;
mFirstChildWhileExpanding = null;
|
public void | onReset(com.android.systemui.statusbar.ExpandableView view)
if (view.equals(mFirstChildWhileExpanding)) {
updateFirstChildMaxSizeToMaxHeight();
}
|
public void | setDimmed(boolean dimmed)
updatePadding(dimmed);
|
public void | setIsExpanded(boolean isExpanded)
this.mIsExpanded = isExpanded;
|
public void | setLayoutHeight(int layoutHeight)
this.mLayoutHeight = layoutHeight;
updateInnerHeight();
|
public void | setTopPadding(int topPadding)
mTopPadding = topPadding;
updateInnerHeight();
|
public boolean | shouldScaleDimmed()
return mScaleDimmed;
|
private void | updateChildClippingAndBackground(StackScrollState.ViewState state, float realHeight, float clipHeight, float backgroundHeight)Updates the shadow outline and the clipping for a view.
if (realHeight > clipHeight) {
// Rather overlap than create a hole.
state.topOverLap = (int) Math.floor((realHeight - clipHeight) / state.scale);
} else {
state.topOverLap = 0;
}
if (realHeight > backgroundHeight) {
// Rather overlap than create a hole.
state.clipTopAmount = (int) Math.floor((realHeight - backgroundHeight) / state.scale);
} else {
state.clipTopAmount = 0;
}
|
private void | updateClipping(StackScrollState resultState, com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState)
float previousNotificationEnd = 0;
float previousNotificationStart = 0;
boolean previousNotificationIsSwiped = false;
int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
ExpandableView child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState state = resultState.getViewStateForView(child);
float newYTranslation = state.yTranslation + state.height * (1f - state.scale) / 2f;
float newHeight = state.height * state.scale;
// apply clipping and shadow
float newNotificationEnd = newYTranslation + newHeight;
float clipHeight;
if (previousNotificationIsSwiped) {
// When the previous notification is swiped, we don't clip the content to the
// bottom of it.
clipHeight = newHeight;
} else {
clipHeight = newNotificationEnd - previousNotificationEnd;
clipHeight = Math.max(0.0f, clipHeight);
if (clipHeight != 0.0f) {
// In the unlocked shade we have to clip a little bit higher because of the rounded
// corners of the notifications, but only if we are not fully overlapped by
// the top card.
float clippingCorrection = state.dimmed
? 0
: mRoundedRectCornerRadius * state.scale;
clipHeight += clippingCorrection;
}
}
updateChildClippingAndBackground(state, newHeight, clipHeight,
newHeight - (previousNotificationStart - newYTranslation));
if (!child.isTransparent()) {
// Only update the previous values if we are not transparent,
// otherwise we would clip to a transparent view.
previousNotificationStart = newYTranslation + state.clipTopAmount * state.scale;
previousNotificationEnd = newNotificationEnd;
previousNotificationIsSwiped = child.getTranslationX() != 0;
}
}
|
private void | updateDimmedActivatedHideSensitive(AmbientState ambientState, StackScrollState resultState, com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState)Updates the dimmed, activated and hiding sensitive states of the children.
boolean dimmed = ambientState.isDimmed();
boolean dark = ambientState.isDark();
boolean hideSensitive = ambientState.isHideSensitive();
View activatedChild = ambientState.getActivatedChild();
int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
childViewState.dimmed = dimmed;
childViewState.dark = dark;
childViewState.hideSensitive = hideSensitive;
boolean isActivatedChild = activatedChild == child;
childViewState.scale = !mScaleDimmed || !dimmed || isActivatedChild
? 1.0f
: DIMMED_SCALE;
if (dimmed && isActivatedChild) {
childViewState.zTranslation += 2.0f * mZDistanceBetweenElements;
}
}
|
private void | updateFirstChildHeightWhileExpanding(android.view.ViewGroup hostView)
mFirstChildWhileExpanding = (ExpandableView) findFirstVisibleChild(hostView);
if (mFirstChildWhileExpanding != null) {
if (mExpandedOnStart) {
// We are collapsing the shade, so the first child can get as most as high as the
// current height or the end value of the animation.
mFirstChildMaxHeight = StackStateAnimator.getFinalActualHeight(
mFirstChildWhileExpanding);
} else {
updateFirstChildMaxSizeToMaxHeight();
}
} else {
mFirstChildMaxHeight = 0;
}
|
private void | updateFirstChildMaxSizeToMaxHeight()
// We are expanding the shade, expand it to its full height.
if (!isMaxSizeInitialized(mFirstChildWhileExpanding)) {
// This child was not layouted yet, wait for a layout pass
mFirstChildWhileExpanding
.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight,
int oldBottom) {
if (mFirstChildWhileExpanding != null) {
mFirstChildMaxHeight = getMaxAllowedChildHeight(
mFirstChildWhileExpanding);
} else {
mFirstChildMaxHeight = 0;
}
v.removeOnLayoutChangeListener(this);
}
});
} else {
mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
}
|
private void | updateInnerHeight()
mInnerHeight = mLayoutHeight - mTopPadding;
|
public void | updateIsSmallScreen(int panelHeight)Update whether the device is very small, i.e. Notifications can be in both the top and the
bottom stack at the same time
mIsSmallScreen = panelHeight <
mCollapsedSize /* top stack */
+ mBottomStackSlowDownLength + mBottomStackPeekSize /* bottom stack */
+ mMaxNotificationHeight; /* max notification height */
|
private void | updatePadding(boolean dimmed)
mPaddingBetweenElements = dimmed && mScaleDimmed
? mPaddingBetweenElementsDimmed
: mPaddingBetweenElementsNormal;
mTopStackTotalSize = mTopStackSlowDownLength + mPaddingBetweenElements
+ mTopStackPeekSize;
mTopStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
MAX_ITEMS_IN_TOP_STACK,
mTopStackPeekSize,
mTopStackTotalSize - mTopStackPeekSize,
0.5f);
mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
MAX_ITEMS_IN_BOTTOM_STACK,
mBottomStackPeekSize,
getBottomStackSlowDownLength(),
0.5f);
|
private void | updatePositionsForState(StackScrollState resultState, com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState)Determine the positions for the views. This is the main part of the algorithm.
// The starting position of the bottom stack peek
float bottomPeekStart = mInnerHeight - mBottomStackPeekSize;
// The position where the bottom stack starts.
float bottomStackStart = bottomPeekStart - mBottomStackSlowDownLength;
// The y coordinate of the current child.
float currentYPosition = 0.0f;
// How far in is the element currently transitioning into the bottom stack.
float yPositionInScrollView = 0.0f;
int childCount = algorithmState.visibleChildren.size();
int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack;
for (int i = 0; i < childCount; i++) {
ExpandableView child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
int childHeight = getMaxAllowedChildHeight(child);
float yPositionInScrollViewAfterElement = yPositionInScrollView
+ childHeight
+ mPaddingBetweenElements;
float scrollOffset = yPositionInScrollView - algorithmState.scrollY + mCollapsedSize;
if (i == algorithmState.lastTopStackIndex + 1) {
// Normally the position of this child is the position in the regular scrollview,
// but if the two stacks are very close to each other,
// then have have to push it even more upwards to the position of the bottom
// stack start.
currentYPosition = Math.min(scrollOffset, bottomStackStart);
}
childViewState.yTranslation = currentYPosition;
// The y position after this element
float nextYPosition = currentYPosition + childHeight +
mPaddingBetweenElements;
if (i <= algorithmState.lastTopStackIndex) {
// Case 1:
// We are in the top Stack
updateStateForTopStackChild(algorithmState,
numberOfElementsCompletelyIn, i, childHeight, childViewState, scrollOffset);
clampPositionToTopStackEnd(childViewState, childHeight);
// check if we are overlapping with the bottom stack
if (childViewState.yTranslation + childHeight + mPaddingBetweenElements
>= bottomStackStart && !mIsExpansionChanging && i != 0 && mIsSmallScreen) {
// we just collapse this element slightly
int newSize = (int) Math.max(bottomStackStart - mPaddingBetweenElements -
childViewState.yTranslation, mCollapsedSize);
childViewState.height = newSize;
updateStateForChildTransitioningInBottom(algorithmState, bottomStackStart,
bottomPeekStart, childViewState.yTranslation, childViewState,
childHeight);
}
clampPositionToBottomStackStart(childViewState, childViewState.height);
} else if (nextYPosition >= bottomStackStart) {
// Case 2:
// 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, childHeight);
} else {
// According to the regular scroll view we are currently translating out of /
// into the bottom of the screen
updateStateForChildTransitioningInBottom(algorithmState,
bottomStackStart, bottomPeekStart, currentYPosition,
childViewState, childHeight);
}
} else {
// Case 3:
// We are in the regular scroll area.
childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
clampYTranslation(childViewState, childHeight);
}
// The first card is always rendered.
if (i == 0) {
childViewState.alpha = 1.0f;
childViewState.yTranslation = Math.max(mCollapsedSize - algorithmState.scrollY, 0);
if (childViewState.yTranslation + childViewState.height
> bottomPeekStart - mCollapseSecondCardPadding) {
childViewState.height = (int) Math.max(
bottomPeekStart - mCollapseSecondCardPadding
- childViewState.yTranslation, mCollapsedSize);
}
childViewState.location = StackScrollState.ViewState.LOCATION_FIRST_CARD;
}
if (childViewState.location == StackScrollState.ViewState.LOCATION_UNKNOWN) {
Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
}
currentYPosition = childViewState.yTranslation + childHeight + mPaddingBetweenElements;
yPositionInScrollView = yPositionInScrollViewAfterElement;
childViewState.yTranslation += mTopPadding;
}
|
private void | updateSpeedBumpState(StackScrollState resultState, com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState, int speedBumpIndex)
int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
// The speed bump can also be gone, so equality needs to be taken when comparing
// indices.
childViewState.belowSpeedBump = speedBumpIndex != -1 && i >= speedBumpIndex;
}
|
private void | updateStateForChildFullyInBottomStack(com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState, float transitioningPositionStart, StackScrollState.ViewState childViewState, int childHeight)
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)
- mPaddingBetweenElements;
childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_PEEKING;
} else {
// we are fully inside the stack
if (algorithmState.itemsInBottomStack > MAX_ITEMS_IN_BOTTOM_STACK + 2) {
childViewState.alpha = 0.0f;
} else if (algorithmState.itemsInBottomStack
> MAX_ITEMS_IN_BOTTOM_STACK + 1) {
childViewState.alpha = 1.0f - algorithmState.partialInBottom;
}
childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_HIDDEN;
currentYPosition = mInnerHeight;
}
childViewState.yTranslation = currentYPosition - childHeight;
clampPositionToTopStackEnd(childViewState, childHeight);
|
private void | updateStateForChildTransitioningInBottom(com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState, float transitioningPositionStart, float bottomPeakStart, float currentYPosition, StackScrollState.ViewState 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 +
mPaddingBetweenElements));
// 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 > mCollapsedSize && mIsSmallScreen) {
newHeight = (int) Math.max(Math.min(transitioningPositionStart + offset -
mPaddingBetweenElements - currentYPosition, childHeight), mCollapsedSize);
childViewState.height = newHeight;
}
childViewState.yTranslation = transitioningPositionStart + offset - newHeight
- mPaddingBetweenElements;
// We want at least to be at the end of the top stack when collapsing
clampPositionToTopStackEnd(childViewState, newHeight);
childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
|
private void | updateStateForTopStackChild(com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState, int numberOfElementsCompletelyIn, int i, int childHeight, StackScrollState.ViewState childViewState, float scrollOffset)
// First we calculate the index relative to the current stack window of size at most
// {@link #MAX_ITEMS_IN_TOP_STACK}
int paddedIndex = i - 1
- Math.max(numberOfElementsCompletelyIn - MAX_ITEMS_IN_TOP_STACK, 0);
if (paddedIndex >= 0) {
// We are currently visually entering the top stack
float distanceToStack = (childHeight + mPaddingBetweenElements)
- algorithmState.scrolledPixelsTop;
if (i == algorithmState.lastTopStackIndex
&& distanceToStack > (mTopStackTotalSize + mPaddingBetweenElements)) {
// Child is currently translating into stack but not yet inside slow down zone.
// Handle it like the regular scrollview.
childViewState.yTranslation = scrollOffset;
} else {
// Apply stacking logic.
float numItemsBefore;
if (i == algorithmState.lastTopStackIndex) {
numItemsBefore = 1.0f
- (distanceToStack / (mTopStackTotalSize + mPaddingBetweenElements));
} else {
numItemsBefore = algorithmState.itemsInTopStack - i;
}
// The end position of the current child
float currentChildEndY = mCollapsedSize + mTopStackTotalSize
- mTopStackIndentationFunctor.getValue(numItemsBefore);
childViewState.yTranslation = currentChildEndY - childHeight;
}
childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
} else {
if (paddedIndex == -1) {
childViewState.alpha = 1.0f - algorithmState.partialInTop;
} else {
// We are hidden behind the top card and faded out, so we can hide ourselves.
childViewState.alpha = 0.0f;
}
childViewState.yTranslation = mCollapsedSize - childHeight;
childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
}
|
private void | updateVisibleChildren(StackScrollState resultState, com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState state)Update the visible children on the state.
ViewGroup hostView = resultState.getHostView();
int childCount = hostView.getChildCount();
state.visibleChildren.clear();
state.visibleChildren.ensureCapacity(childCount);
for (int i = 0; i < childCount; i++) {
ExpandableView v = (ExpandableView) hostView.getChildAt(i);
if (v.getVisibility() != View.GONE) {
StackScrollState.ViewState viewState = resultState.getViewStateForView(v);
viewState.notGoneIndex = state.visibleChildren.size();
state.visibleChildren.add(v);
}
}
|
private void | updateZValuesForState(StackScrollState resultState, com.android.systemui.statusbar.stack.StackScrollAlgorithm$StackScrollAlgorithmState algorithmState)Calculate the Z positions for all children based on the number of items in both stacks and
save it in the resultState
int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
if (i < algorithmState.itemsInTopStack) {
float stackIndex = algorithmState.itemsInTopStack - i;
// Ensure that the topmost item is a little bit higher than the rest when fully
// scrolled, to avoid drawing errors when swiping it out
float max = MAX_ITEMS_IN_TOP_STACK + (i == 0 ? 2.5f : 2);
stackIndex = Math.min(stackIndex, max);
if (i == 0 && algorithmState.itemsInTopStack < 2.0f) {
// We only have the top item and an additional item in the top stack,
// Interpolate the index from 0 to 2 while the second item is
// translating in.
stackIndex -= 1.0f;
if (algorithmState.scrollY > mCollapsedSize) {
// Since there is a shadow treshhold, we cant just interpolate from 0 to
// 2 but we interpolate from 0.1f to 2.0f when scrolled in. The jump in
// height will not be noticable since we have padding in between.
stackIndex = 0.1f + stackIndex * 1.9f;
}
}
childViewState.zTranslation = mZBasicHeight
+ stackIndex * mZDistanceBetweenElements;
} else if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
float numItemsAbove = i - (childCount - 1 - algorithmState.itemsInBottomStack);
float translationZ = mZBasicHeight
- numItemsAbove * mZDistanceBetweenElements;
childViewState.zTranslation = translationZ;
} else {
childViewState.zTranslation = mZBasicHeight;
}
}
|