Merge "Refactor ExpandableView to maintain its own ExpandableViewState."

This commit is contained in:
Ned Burns
2018-11-28 00:37:57 +00:00
committed by Android (Google) Code Review
15 changed files with 292 additions and 389 deletions

View File

@@ -27,7 +27,6 @@ import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.StackScrollState;
public class EmptyShadeView extends StackScrollerDecorView {
@@ -74,7 +73,7 @@ public class EmptyShadeView extends StackScrollerDecorView {
}
@Override
public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
public ExpandableViewState createExpandableViewState() {
return new EmptyShadeViewState();
}

View File

@@ -47,7 +47,6 @@ import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackScrollState;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
@@ -68,7 +67,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
private boolean mDark;
private NotificationIconContainer mShelfIcons;
private ShelfState mShelfState;
private int[] mTmp = new int[2];
private boolean mHideBackground;
private int mIconAppearTopPadding;
@@ -115,7 +113,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
setClipChildren(false);
setClipToPadding(false);
mShelfIcons.setIsStaticLayout(false);
mShelfState = new ShelfState();
setBottomRoundness(1.0f, false /* animate */);
initDimens();
}
@@ -187,52 +184,53 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
@Override
public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
return mShelfState;
public ExpandableViewState createExpandableViewState() {
return new ShelfState();
}
public void updateState(StackScrollState resultState,
AmbientState ambientState) {
View lastView = ambientState.getLastVisibleBackgroundChild();
/** Update the state of the shelf. */
public void updateState(AmbientState ambientState) {
ExpandableView lastView = ambientState.getLastVisibleBackgroundChild();
ShelfState viewState = (ShelfState) getViewState();
if (mShowNotificationShelf && lastView != null) {
float maxShelfEnd = ambientState.getInnerHeight() + ambientState.getTopPadding()
+ ambientState.getStackTranslation();
ExpandableViewState lastViewState = resultState.getViewStateForView(lastView);
ExpandableViewState lastViewState = lastView.getViewState();
float viewEnd = lastViewState.yTranslation + lastViewState.height;
mShelfState.copyFrom(lastViewState);
mShelfState.height = getIntrinsicHeight();
viewState.copyFrom(lastViewState);
viewState.height = getIntrinsicHeight();
float awakenTranslation = Math.max(Math.min(viewEnd, maxShelfEnd) - mShelfState.height,
float awakenTranslation = Math.max(Math.min(viewEnd, maxShelfEnd) - viewState.height,
getFullyClosedTranslation());
float darkTranslation = mAmbientState.getDarkTopPadding();
float yRatio = mAmbientState.hasPulsingNotifications() ?
0 : mAmbientState.getDarkAmount();
mShelfState.yTranslation = MathUtils.lerp(awakenTranslation, darkTranslation, yRatio);
mShelfState.zTranslation = ambientState.getBaseZHeight();
viewState.yTranslation = MathUtils.lerp(awakenTranslation, darkTranslation, yRatio);
viewState.zTranslation = ambientState.getBaseZHeight();
// For the small display size, it's not enough to make the icon not covered by
// the top cutout so the denominator add the height of cutout.
// Totally, (getIntrinsicHeight() * 2 + mCutoutHeight) should be smaller then
// mAmbientState.getTopPadding().
float openedAmount = (mShelfState.yTranslation - getFullyClosedTranslation())
float openedAmount = (viewState.yTranslation - getFullyClosedTranslation())
/ (getIntrinsicHeight() * 2 + mCutoutHeight);
openedAmount = Math.min(1.0f, openedAmount);
mShelfState.openedAmount = openedAmount;
mShelfState.clipTopAmount = 0;
mShelfState.alpha = mAmbientState.hasPulsingNotifications() ? 0 : 1;
mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
mShelfState.hideSensitive = false;
mShelfState.xTranslation = getTranslationX();
viewState.openedAmount = openedAmount;
viewState.clipTopAmount = 0;
viewState.alpha = mAmbientState.hasPulsingNotifications() ? 0 : 1;
viewState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
viewState.hideSensitive = false;
viewState.xTranslation = getTranslationX();
if (mNotGoneIndex != -1) {
mShelfState.notGoneIndex = Math.min(mShelfState.notGoneIndex, mNotGoneIndex);
viewState.notGoneIndex = Math.min(viewState.notGoneIndex, mNotGoneIndex);
}
mShelfState.hasItemsInStableShelf = lastViewState.inShelf;
mShelfState.hidden = !mAmbientState.isShadeExpanded()
viewState.hasItemsInStableShelf = lastViewState.inShelf;
viewState.hidden = !mAmbientState.isShadeExpanded()
|| mAmbientState.isQsCustomizerShowing();
mShelfState.maxShelfEnd = maxShelfEnd;
viewState.maxShelfEnd = maxShelfEnd;
} else {
mShelfState.hidden = true;
mShelfState.location = ExpandableViewState.LOCATION_GONE;
mShelfState.hasItemsInStableShelf = false;
viewState.hidden = true;
viewState.location = ExpandableViewState.LOCATION_GONE;
viewState.hasItemsInStableShelf = false;
}
}
@@ -261,7 +259,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
int notGoneIndex = 0;
int colorOfViewBeforeLast = NO_COLOR;
boolean backgroundForceHidden = false;
if (mHideBackground && !mShelfState.hasItemsInStableShelf) {
if (mHideBackground && !((ShelfState) getViewState()).hasItemsInStableShelf) {
backgroundForceHidden = true;
}
int colorTwoBefore = NO_COLOR;

View File

@@ -17,22 +17,14 @@
package com.android.systemui.statusbar.notification.row;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.row.NotificationContentView
.VISIBLE_TYPE_AMBIENT;
import static com.android.systemui.statusbar.notification.row.NotificationContentView
.VISIBLE_TYPE_CONTRACTED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView
.VISIBLE_TYPE_HEADSUP;
import static com.android.systemui.statusbar.notification.row.NotificationInflater
.FLAG_CONTENT_VIEW_AMBIENT;
import static com.android.systemui.statusbar.notification.row.NotificationInflater
.FLAG_CONTENT_VIEW_HEADS_UP;
import static com.android.systemui.statusbar.notification.row.NotificationInflater
.FLAG_CONTENT_VIEW_PUBLIC;
import static com.android.systemui.statusbar.notification.row.NotificationInflater
.InflationCallback;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_AMBIENT;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_PUBLIC;
import static com.android.systemui.statusbar.notification.row.NotificationInflater.InflationCallback;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -105,7 +97,6 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackScrollState;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -337,7 +328,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private float mTranslationWhenRemoved;
private boolean mWasChildInGroupWhenRemoved;
private int mNotificationColorAmbient;
private NotificationViewState mNotificationViewState;
private SystemNotificationAsyncTask mSystemNotificationAsyncTask =
new SystemNotificationAsyncTask();
@@ -894,29 +884,32 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
visualStabilityManager, callback);
}
public void getChildrenStates(StackScrollState resultState,
AmbientState ambientState) {
/** Updates states of all children. */
public void updateChildrenStates(AmbientState ambientState) {
if (mIsSummaryWithChildren) {
ExpandableViewState parentState = resultState.getViewStateForView(this);
mChildrenContainer.getState(resultState, parentState, ambientState);
ExpandableViewState parentState = getViewState();
mChildrenContainer.updateState(parentState, ambientState);
}
}
public void applyChildrenState(StackScrollState state) {
/** Applies children states. */
public void applyChildrenState() {
if (mIsSummaryWithChildren) {
mChildrenContainer.applyState(state);
mChildrenContainer.applyState();
}
}
public void prepareExpansionChanged(StackScrollState state) {
/** Prepares expansion changed. */
public void prepareExpansionChanged() {
if (mIsSummaryWithChildren) {
mChildrenContainer.prepareExpansionChanged(state);
mChildrenContainer.prepareExpansionChanged();
}
}
public void startChildAnimation(StackScrollState finalState, AnimationProperties properties) {
/** Starts child animations. */
public void startChildAnimation(AnimationProperties properties) {
if (mIsSummaryWithChildren) {
mChildrenContainer.startAnimationToState(finalState, properties);
mChildrenContainer.startAnimationToState(properties);
}
}
@@ -2047,7 +2040,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
.setInterpolator(Interpolators.ALPHA_OUT);
setAboveShelf(true);
mExpandAnimationRunning = true;
mNotificationViewState.cancelAnimations(this);
getViewState().cancelAnimations(this);
mNotificationLaunchHeight = AmbientState.getNotificationLaunchHeight(getContext());
} else {
mExpandAnimationRunning = false;
@@ -2924,13 +2917,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
@Override
public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
mNotificationViewState = new NotificationViewState(stackScrollState);
return mNotificationViewState;
}
public NotificationViewState getViewState() {
return mNotificationViewState;
public ExpandableViewState createExpandableViewState() {
return new NotificationViewState();
}
@Override
@@ -3040,14 +3028,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
public static class NotificationViewState extends ExpandableViewState {
private final StackScrollState mOverallState;
private NotificationViewState(StackScrollState stackScrollState) {
mOverallState = stackScrollState;
}
private static class NotificationViewState extends ExpandableViewState {
@Override
public void applyToView(View view) {
@@ -3058,7 +3039,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
handleFixedTranslationZ(row);
super.applyToView(view);
row.applyChildrenState(mOverallState);
row.applyChildrenState();
}
}
@@ -3089,7 +3070,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
handleFixedTranslationZ(row);
super.animateTo(child, properties);
row.startChildAnimation(mOverallState, properties);
row.startChildAnimation(properties);
}
}
}
@@ -3144,8 +3125,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
pw.println();
showingLayout.dump(fd, pw, args);
pw.print(" ");
if (mNotificationViewState != null) {
mNotificationViewState.dump(fd, pw, args);
if (getViewState() != null) {
getViewState().dump(fd, pw, args);
} else {
pw.print("no viewState!!!");
}

View File

@@ -21,23 +21,27 @@ import android.content.Context;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackScrollState;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* An abstract view for expandable views.
*/
public abstract class ExpandableView extends FrameLayout implements Dumpable {
private static final String TAG = "ExpandableView";
public static final float NO_ROUNDNESS = -1;
protected OnHeightChangedListener mOnHeightChangedListener;
@@ -54,6 +58,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
private ViewGroup mTransientContainer;
private boolean mInShelf;
private boolean mTransformingInShelf;
@Nullable private ExpandableViewState mViewState;
public ExpandableView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -511,10 +516,56 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
public void setActualHeightAnimating(boolean animating) {}
public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
protected ExpandableViewState createExpandableViewState() {
return new ExpandableViewState();
}
/** Sets {@link ExpandableViewState} to default state. */
public ExpandableViewState resetViewState() {
// TODO(http://b/119762423): Move the null check to getViewState().
if (mViewState == null) {
mViewState = createExpandableViewState();
}
// initialize with the default values of the view
mViewState.height = getIntrinsicHeight();
mViewState.gone = getVisibility() == View.GONE;
mViewState.alpha = 1f;
mViewState.notGoneIndex = -1;
mViewState.xTranslation = getTranslationX();
mViewState.hidden = false;
mViewState.scaleX = getScaleX();
mViewState.scaleY = getScaleY();
mViewState.inShelf = false;
mViewState.headsUpIsVisible = false;
// handling reset for child notifications
if (this instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) this;
List<ExpandableNotificationRow> children = row.getNotificationChildren();
if (row.isSummaryWithChildren() && children != null) {
for (ExpandableNotificationRow childRow : children) {
childRow.resetViewState();
}
}
}
return mViewState;
}
@Nullable public ExpandableViewState getViewState() {
return mViewState;
}
/** Applies internal {@link ExpandableViewState} to this view. */
public void applyViewState() {
if (mViewState == null) {
Log.wtf(TAG, "No child state was found when applying this state to the hostView");
} else if (!mViewState.gone) {
mViewState.applyToView(this);
}
}
/**
* @return whether the current view doesn't add height to the overall content. This means that
* if it is added to a list of items, it's content will still have the same height.

View File

@@ -24,7 +24,6 @@ import android.view.View;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.StackScrollState;
public class FooterView extends StackScrollerDecorView {
private final int mClearAllTopPadding;
@@ -87,7 +86,7 @@ public class FooterView extends StackScrollerDecorView {
}
@Override
public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
public ExpandableViewState createExpandableViewState() {
return new FooterViewState();
}

View File

@@ -40,7 +40,7 @@ public class AmbientState {
private static final int NO_SECTION_BOUNDARY = -1;
private ArrayList<View> mDraggedViews = new ArrayList<>();
private ArrayList<ExpandableView> mDraggedViews = new ArrayList<>();
private int mScrollY;
private boolean mDimmed;
private ActivatableNotificationView mActivatedChild;
@@ -131,7 +131,8 @@ public class AmbientState {
this.mScrollY = scrollY;
}
public void onBeginDrag(View view) {
/** Call when dragging begins. */
public void onBeginDrag(ExpandableView view) {
mDraggedViews.add(view);
}
@@ -139,7 +140,7 @@ public class AmbientState {
mDraggedViews.remove(view);
}
public ArrayList<View> getDraggedViews() {
public ArrayList<ExpandableView> getDraggedViews() {
return mDraggedViews;
}

View File

@@ -274,7 +274,7 @@ public class NotificationChildrenContainer extends ViewGroup {
updateGroupOverflow();
row.setContentTransformationAmount(0, false /* isLastChild */);
// It doesn't make sense to keep old animations around, lets cancel them!
ExpandableNotificationRow.NotificationViewState viewState = row.getViewState();
ExpandableViewState viewState = row.getViewState();
if (viewState != null) {
viewState.cancelAnimations(row);
row.cancelAppearDrawing();
@@ -562,12 +562,10 @@ public class NotificationChildrenContainer extends ViewGroup {
/**
* Update the state of all its children based on a linear layout algorithm.
* @param resultState the state to update
* @param parentState the state of the parent
* @param ambientState
*/
public void getState(StackScrollState resultState, ExpandableViewState parentState,
AmbientState ambientState) {
public void updateState(ExpandableViewState parentState, AmbientState ambientState) {
int childCount = mChildren.size();
int yPosition = mNotificationHeaderMargin + mCurrentHeaderTranslation;
boolean firstChild = true;
@@ -605,7 +603,7 @@ public class NotificationChildrenContainer extends ViewGroup {
firstChild = false;
}
ExpandableViewState childState = resultState.getViewStateForView(child);
ExpandableViewState childState = child.getViewState();
int intrinsicHeight = child.getIntrinsicHeight();
childState.height = intrinsicHeight;
childState.yTranslation = yPosition + launchTransitionCompensation;
@@ -639,7 +637,7 @@ public class NotificationChildrenContainer extends ViewGroup {
if (mOverflowNumber != null) {
ExpandableNotificationRow overflowView = mChildren.get(Math.min(
getMaxAllowedVisibleChildren(true /* likeCollapsed */), childCount) - 1);
mGroupOverFlowState.copyFrom(resultState.getViewStateForView(overflowView));
mGroupOverFlowState.copyFrom(overflowView.getViewState());
if (mContainingNotification.isOnAmbient()) {
mGroupOverFlowState.alpha = 0.0f;
@@ -724,7 +722,8 @@ public class NotificationChildrenContainer extends ViewGroup {
return NUMBER_OF_CHILDREN_WHEN_COLLAPSED;
}
public void applyState(StackScrollState state) {
/** Applies state to children. */
public void applyState() {
int childCount = mChildren.size();
ViewState tmpState = new ViewState();
float expandFraction = 0.0f;
@@ -737,7 +736,7 @@ public class NotificationChildrenContainer extends ViewGroup {
&& !mHideDividersDuringExpand);
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
ExpandableViewState viewState = state.getViewStateForView(child);
ExpandableViewState viewState = child.getViewState();
viewState.applyToView(child);
// layout the divider
@@ -799,14 +798,14 @@ public class NotificationChildrenContainer extends ViewGroup {
* This is called when the children expansion has changed and positions the children properly
* for an appear animation.
*
* @param state the new state we animate to
*/
public void prepareExpansionChanged(StackScrollState state) {
public void prepareExpansionChanged() {
// TODO: do something that makes sense, like placing the invisible views correctly
return;
}
public void startAnimationToState(StackScrollState state, AnimationProperties properties) {
/** Animate to a given state. */
public void startAnimationToState(AnimationProperties properties) {
int childCount = mChildren.size();
ViewState tmpState = new ViewState();
float expandFraction = getGroupExpandFraction();
@@ -816,7 +815,7 @@ public class NotificationChildrenContainer extends ViewGroup {
&& !mHideDividersDuringExpand);
for (int i = childCount - 1; i >= 0; i--) {
ExpandableNotificationRow child = mChildren.get(i);
ExpandableViewState viewState = state.getViewStateForView(child);
ExpandableViewState viewState = child.getViewState();
viewState.animateTo(child, properties);
// layout the divider

View File

@@ -45,34 +45,31 @@ public interface NotificationListContainer extends ExpandableView.OnHeightChange
/**
* Change the position of child to a new location
*
* @param child the view to change the position for
* @param child the view to change the position for
* @param newIndex the new index
*/
void changeViewPosition(View child, int newIndex);
void changeViewPosition(ExpandableView child, int newIndex);
/**
* Called when a child was added to a group.
*
* @param row row of the group child that was added
*/
void notifyGroupChildAdded(View row);
void notifyGroupChildAdded(ExpandableView row);
/**
* Called when a child was removed from a group.
*
* @param row row of the child that was removed
* @param row row of the child that was removed
* @param childrenContainer ViewGroup of the group that the child was removed from
*/
void notifyGroupChildRemoved(View row, ViewGroup childrenContainer);
void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer);
/**
* Generate an animation for an added child view.
*
* @param child The view to be added.
* @param child The view to be added.
* @param fromMoreCard Whether this add is coming from the "more" card on lockscreen.
*/
void generateAddAnimation(View child, boolean fromMoreCard);
void generateAddAnimation(ExpandableView child, boolean fromMoreCard);
/**
* Generate a child order changed event.

View File

@@ -16,14 +16,12 @@
package com.android.systemui.statusbar.notification.stack;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
.NUM_SECTIONS;
import android.view.View;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.NUM_SECTIONS;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import java.util.HashSet;
@@ -38,7 +36,7 @@ class NotificationRoundnessManager implements OnHeadsUpChangedListener {
private ActivatableNotificationView[] mLastInSectionViews;
private ActivatableNotificationView[] mTmpFirstInSectionViews;
private ActivatableNotificationView[] mTmpLastInSectionViews;
private HashSet<View> mAnimatedChildren;
private HashSet<ExpandableView> mAnimatedChildren;
private Runnable mRoundingChangedCallback;
private ExpandableNotificationRow mTrackedHeadsUp;
private float mAppearFraction;
@@ -212,7 +210,7 @@ class NotificationRoundnessManager implements OnHeadsUpChangedListener {
return anyChanged;
}
public void setAnimatedChildren(HashSet<View> animatedChildren) {
public void setAnimatedChildren(HashSet<ExpandableView> animatedChildren) {
mAnimatedChildren = animatedChildren;
}

View File

@@ -208,16 +208,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
*/
protected final StackScrollAlgorithm mStackScrollAlgorithm;
/**
* The current State this Layout is in
*/
private StackScrollState mCurrentStackScrollState = new StackScrollState(this);
private final AmbientState mAmbientState;
private NotificationGroupManager mGroupManager;
private HashSet<View> mChildrenToAddAnimated = new HashSet<>();
private HashSet<ExpandableView> mChildrenToAddAnimated = new HashSet<>();
private ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>();
private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<>();
private ArrayList<View> mChildrenChangingPositions = new ArrayList<>();
private ArrayList<ExpandableView> mChildrenToRemoveAnimated = new ArrayList<>();
private ArrayList<ExpandableView> mChildrenChangingPositions = new ArrayList<>();
private HashSet<View> mFromMoreCardAdditions = new HashSet<>();
private ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>();
private ArrayList<View> mSwipedOutViews = new ArrayList<>();
@@ -275,7 +271,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private boolean mDontReportNextOverScroll;
private boolean mDontClampNextScroll;
private boolean mNeedViewResizeAnimation;
private View mExpandedGroupView;
private ExpandableView mExpandedGroupView;
private boolean mEverythingNeedsAnimation;
/**
@@ -382,7 +378,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private boolean mGroupExpandedForMeasure;
private boolean mScrollable;
private View mForcedScroll;
private View mNeedingPulseAnimation;
private ExpandableView mNeedingPulseAnimation;
/**
* @see #setDarkAmount(float, float)
@@ -899,7 +895,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
public boolean isInVisibleLocation(NotificationData.Entry entry) {
ExpandableNotificationRow row = entry.getRow();
ExpandableViewState childViewState = mCurrentStackScrollState.getViewStateForView(row);
ExpandableViewState childViewState = row.getViewState();
if (childViewState == null) {
return false;
}
@@ -945,7 +942,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
? 0
: mScroller.getCurrVelocity());
mAmbientState.setScrollY(mOwnScrollY);
mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState);
mStackScrollAlgorithm.resetViewStates(mAmbientState);
if (!isCurrentlyAnimating() && !mNeedsAnimation) {
applyCurrentState();
} else {
@@ -1937,12 +1934,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
* @return the last child which has visibility unequal to GONE
*/
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
public View getLastChildNotGone() {
public ExpandableView getLastChildNotGone() {
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
View child = getChildAt(i);
if (child.getVisibility() != View.GONE && child != mShelf) {
return child;
return (ExpandableView) child;
}
}
return null;
@@ -2511,7 +2508,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
// we only call our internal methods if this is actually a removal and not just a
// notification which becomes a child notification
if (!mChildTransferInProgress) {
onViewRemovedInternal(child, this);
onViewRemovedInternal((ExpandableView) child, this);
}
}
@@ -2522,25 +2519,22 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
if (child == mSwipeHelper.getTranslatingParentView()) {
mSwipeHelper.clearTranslatingParentView();
}
mCurrentStackScrollState.removeViewStateForView(child);
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private void onViewRemovedInternal(View child, ViewGroup container) {
private void onViewRemovedInternal(ExpandableView child, ViewGroup container) {
if (mChangePositionInProgress) {
// This is only a position change, don't do anything special
return;
}
ExpandableView expandableView = (ExpandableView) child;
expandableView.setOnHeightChangedListener(null);
mCurrentStackScrollState.removeViewStateForView(child);
updateScrollStateForRemovedChild(expandableView);
child.setOnHeightChangedListener(null);
updateScrollStateForRemovedChild(child);
boolean animationGenerated = generateRemoveAnimation(child);
if (animationGenerated) {
if (!mSwipedOutViews.contains(child)
|| Math.abs(expandableView.getTranslation()) != expandableView.getWidth()) {
|| Math.abs(child.getTranslation()) != child.getWidth()) {
container.addTransientView(child, 0);
expandableView.setTransientContainer(container);
child.setTransientContainer(container);
}
} else {
mSwipedOutViews.remove(child);
@@ -2584,14 +2578,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
* @return Whether an animation was generated.
*/
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private boolean generateRemoveAnimation(View child) {
private boolean generateRemoveAnimation(ExpandableView child) {
if (removeRemovedChildFromHeadsUpChangeAnimations(child)) {
mAddedHeadsUpChildren.remove(child);
return false;
}
if (isClickedHeadsUp(child)) {
// An animation is already running, add it transiently
mClearTransientViewsWhenFinished.add((ExpandableView) child);
mClearTransientViewsWhenFinished.add(child);
return true;
}
if (mIsExpanded && mAnimationsEnabled && !isChildInInvisibleGroup(child)) {
@@ -2765,7 +2759,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void onViewAdded(View child) {
super.onViewAdded(child);
onViewAddedInternal(child);
onViewAddedInternal((ExpandableView) child);
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -2835,31 +2829,28 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private void onViewAddedInternal(View child) {
private void onViewAddedInternal(ExpandableView child) {
updateHideSensitiveForChild(child);
((ExpandableView) child).setOnHeightChangedListener(this);
child.setOnHeightChangedListener(this);
generateAddAnimation(child, false /* fromMoreCard */);
updateAnimationState(child);
updateChronometerForChild(child);
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private void updateHideSensitiveForChild(View child) {
if (child instanceof ExpandableView) {
ExpandableView expandableView = (ExpandableView) child;
expandableView.setHideSensitiveForIntrinsicHeight(mAmbientState.isHideSensitive());
}
private void updateHideSensitiveForChild(ExpandableView child) {
child.setHideSensitiveForIntrinsicHeight(mAmbientState.isHideSensitive());
}
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void notifyGroupChildRemoved(View row, ViewGroup childrenContainer) {
public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {
onViewRemovedInternal(row, childrenContainer);
}
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void notifyGroupChildAdded(View row) {
public void notifyGroupChildAdded(ExpandableView row) {
onViewAddedInternal(row);
}
@@ -2931,7 +2922,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void generateAddAnimation(View child, boolean fromMoreCard) {
public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {
if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress) {
// Generate Animations
mChildrenToAddAnimated.add(child);
@@ -2948,7 +2939,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void changeViewPosition(View child, int newIndex) {
public void changeViewPosition(ExpandableView child, int newIndex) {
int currentIndex = indexOfChild(child);
if (currentIndex == -1) {
@@ -2987,8 +2978,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
if (!mAnimationEvents.isEmpty() || isCurrentlyAnimating()) {
setAnimationRunning(true);
mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState,
mGoToFullShadeDelay);
mStateAnimator.startAnimationForEvents(mAnimationEvents, mGoToFullShadeDelay);
mAnimationEvents.clear();
updateBackground();
updateViewShadows();
@@ -3035,7 +3025,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
continue;
}
} else {
ExpandableViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
ExpandableViewState viewState = row.getViewState();
if (viewState == null) {
// A view state was never generated for this view, so we don't need to animate
// this. This may happen with notification children.
@@ -3101,7 +3091,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void generateChildRemovalEvents() {
for (View child : mChildrenToRemoveAnimated) {
for (ExpandableView child : mChildrenToRemoveAnimated) {
boolean childWasSwipedOut = mSwipedOutViews.contains(child);
// we need to know the view after this one
@@ -3143,7 +3133,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void generatePositionChangeEvents() {
for (View child : mChildrenChangingPositions) {
for (ExpandableView child : mChildrenChangingPositions) {
mAnimationEvents.add(new AnimationEvent(child,
AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION));
}
@@ -3157,7 +3147,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void generateChildAdditionEvents() {
for (View child : mChildrenToAddAnimated) {
for (ExpandableView child : mChildrenToAddAnimated) {
if (mFromMoreCardAdditions.contains(child)) {
mAnimationEvents.add(new AnimationEvent(child,
AnimationEvent.ANIMATION_TYPE_ADD,
@@ -3249,7 +3239,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
protected StackScrollAlgorithm createStackScrollAlgorithm(Context context) {
return new StackScrollAlgorithm(context);
return new StackScrollAlgorithm(context, this);
}
/**
@@ -3914,7 +3904,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mStatusBar.resetUserExpandedStates();
clearTemporaryViews();
clearUserLockedViews();
ArrayList<View> draggedViews = mAmbientState.getDraggedViews();
ArrayList<ExpandableView> draggedViews = mAmbientState.getDraggedViews();
if (draggedViews.size() > 0) {
draggedViews.clear();
updateContinuousShadowDrawing();
@@ -4198,7 +4188,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void applyCurrentState() {
mCurrentStackScrollState.apply();
int numChildren = getChildCount();
for (int i = 0; i < numChildren; i++) {
ExpandableView child = (ExpandableView) getChildAt(i);
child.applyViewState();
}
if (mListener != null) {
mListener.onChildLocationsChanged();
}
@@ -4942,8 +4937,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
if (!(child instanceof ExpandableNotificationRow)) {
pw.println(" " + child.getClass().getSimpleName());
// Notifications dump it's viewstate as part of their dump to support children
ExpandableViewState viewState = mCurrentStackScrollState.getViewStateForView(
child);
ExpandableViewState viewState = child.getViewState();
if (viewState == null) {
pw.println(" no viewState!!!");
} else {
@@ -4960,7 +4954,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
ExpandableView child = (ExpandableView) getTransientView(i);
child.dump(fd, pw, args);
}
ArrayList<View> draggedViews = mAmbientState.getDraggedViews();
ArrayList<ExpandableView> draggedViews = mAmbientState.getDraggedViews();
int draggedCount = draggedViews.size();
pw.println(" Dragged Views: " + draggedCount);
for (int i = 0; i < draggedCount; i++) {
@@ -5496,7 +5490,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
static final int DARK_ANIMATION_ORIGIN_INDEX_BELOW = -2;
final long eventStartTime;
final View changingView;
final ExpandableView mChangingView;
final int animationType;
final AnimationFilter filter;
final long length;
@@ -5504,21 +5498,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
int darkAnimationOriginIndex;
boolean headsUpFromBottom;
AnimationEvent(View view, int type) {
AnimationEvent(ExpandableView view, int type) {
this(view, type, LENGTHS[type]);
}
AnimationEvent(View view, int type, AnimationFilter filter) {
AnimationEvent(ExpandableView view, int type, AnimationFilter filter) {
this(view, type, LENGTHS[type], filter);
}
AnimationEvent(View view, int type, long length) {
AnimationEvent(ExpandableView view, int type, long length) {
this(view, type, length, FILTERS[type]);
}
AnimationEvent(View view, int type, long length, AnimationFilter filter) {
AnimationEvent(ExpandableView view, int type, long length, AnimationFilter filter) {
eventStartTime = AnimationUtils.currentAnimationTimeMillis();
changingView = view;
mChangingView = view;
animationType = type;
this.length = length;
this.filter = filter;
@@ -5716,7 +5710,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
public void onBeginDrag(View v) {
mFalsingManager.onNotificatonStartDismissing();
setSwipingInProgress(true);
mAmbientState.onBeginDrag(v);
mAmbientState.onBeginDrag((ExpandableView) v);
updateContinuousShadowDrawing();
requestChildrenUpdate();
}

View File

@@ -42,6 +42,7 @@ import java.util.List;
public class StackScrollAlgorithm {
private static final String LOG_TAG = "StackScrollAlgorithm";
private final ViewGroup mHostView;
private int mPaddingBetweenElements;
private int mIncreasedPaddingBetweenElements;
@@ -55,7 +56,8 @@ public class StackScrollAlgorithm {
private float mHeadsUpInset;
private int mPinnedZTranslationExtra;
public StackScrollAlgorithm(Context context) {
public StackScrollAlgorithm(Context context, ViewGroup hostView) {
mHostView = hostView;
initView(context);
}
@@ -79,49 +81,59 @@ public class StackScrollAlgorithm {
mGapHeight = res.getDimensionPixelSize(R.dimen.notification_section_divider_height);
}
public void getStackScrollState(AmbientState ambientState, StackScrollState resultState) {
/**
* Updates the state of all children in the hostview based on this algorithm.
*/
public void resetViewStates(AmbientState ambientState) {
// 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();
resetChildViewStates();
initAlgorithmState(resultState, algorithmState, ambientState);
initAlgorithmState(mHostView, algorithmState, ambientState);
updatePositionsForState(resultState, algorithmState, ambientState);
updatePositionsForState(algorithmState, ambientState);
updateZValuesForState(resultState, algorithmState, ambientState);
updateZValuesForState(algorithmState, ambientState);
updateHeadsUpStates(resultState, algorithmState, ambientState);
updateHeadsUpStates(algorithmState, ambientState);
updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
updateClipping(resultState, algorithmState, ambientState);
updateSpeedBumpState(resultState, algorithmState, ambientState);
updateShelfState(resultState, ambientState);
getNotificationChildrenStates(resultState, algorithmState, ambientState);
updateDimmedActivatedHideSensitive(ambientState, algorithmState);
updateClipping(algorithmState, ambientState);
updateSpeedBumpState(algorithmState, ambientState);
updateShelfState(ambientState);
getNotificationChildrenStates(algorithmState, ambientState);
}
private void getNotificationChildrenStates(StackScrollState resultState,
StackScrollAlgorithmState algorithmState,
private void resetChildViewStates() {
int numChildren = mHostView.getChildCount();
for (int i = 0; i < numChildren; i++) {
ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
child.resetViewState();
}
}
private void getNotificationChildrenStates(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
ExpandableView v = algorithmState.visibleChildren.get(i);
if (v instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) v;
row.getChildrenStates(resultState, ambientState);
row.updateChildrenStates(ambientState);
}
}
}
private void updateSpeedBumpState(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
private void updateSpeedBumpState(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
int childCount = algorithmState.visibleChildren.size();
int belowSpeedBump = ambientState.getSpeedBumpIndex();
for (int i = 0; i < childCount; i++) {
View child = algorithmState.visibleChildren.get(i);
ExpandableViewState childViewState = resultState.getViewStateForView(child);
ExpandableView child = algorithmState.visibleChildren.get(i);
ExpandableViewState childViewState = child.getViewState();
// The speed bump can also be gone, so equality needs to be taken when comparing
// indices.
@@ -129,15 +141,16 @@ public class StackScrollAlgorithm {
}
}
private void updateShelfState(StackScrollState resultState, AmbientState ambientState) {
private void updateShelfState(AmbientState ambientState) {
NotificationShelf shelf = ambientState.getShelf();
if (shelf != null) {
shelf.updateState(resultState, ambientState);
shelf.updateState(ambientState);
}
}
private void updateClipping(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
private void updateClipping(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding()
+ ambientState.getStackTranslation() + ambientState.getExpandAnimationTopChange()
: 0;
@@ -146,7 +159,7 @@ public class StackScrollAlgorithm {
int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
ExpandableView child = algorithmState.visibleChildren.get(i);
ExpandableViewState state = resultState.getViewStateForView(child);
ExpandableViewState state = child.getViewState();
if (!child.mustStayOnScreen() || state.headsUpIsVisible) {
previousNotificationEnd = Math.max(drawStart, previousNotificationEnd);
previousNotificationStart = Math.max(drawStart, previousNotificationStart);
@@ -190,15 +203,15 @@ public class StackScrollAlgorithm {
* Updates the dimmed, activated and hiding sensitive states of the children.
*/
private void updateDimmedActivatedHideSensitive(AmbientState ambientState,
StackScrollState resultState, StackScrollAlgorithmState algorithmState) {
StackScrollAlgorithmState algorithmState) {
boolean dimmed = ambientState.isDimmed();
boolean dark = ambientState.isFullyDark();
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);
ExpandableViewState childViewState = resultState.getViewStateForView(child);
ExpandableView child = algorithmState.visibleChildren.get(i);
ExpandableViewState childViewState = child.getViewState();
childViewState.dimmed = dimmed;
childViewState.dark = dark;
childViewState.hideSensitive = hideSensitive;
@@ -212,7 +225,7 @@ public class StackScrollAlgorithm {
/**
* Initialize the algorithm state like updating the visible children.
*/
private void initAlgorithmState(StackScrollState resultState, StackScrollAlgorithmState state,
private void initAlgorithmState(ViewGroup hostView, StackScrollAlgorithmState state,
AmbientState ambientState) {
float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
@@ -224,7 +237,6 @@ public class StackScrollAlgorithm {
state.scrollY = (int) (scrollY + bottomOverScroll);
//now init the visible children and update paddings
ViewGroup hostView = resultState.getHostView();
int childCount = hostView.getChildCount();
state.visibleChildren.clear();
state.visibleChildren.ensureCapacity(childCount);
@@ -249,7 +261,7 @@ public class StackScrollAlgorithm {
// we need normal padding now, to be in sync with what the stack calculates
lastView = null;
}
notGoneIndex = updateNotGoneIndex(resultState, state, notGoneIndex, v);
notGoneIndex = updateNotGoneIndex(state, notGoneIndex, v);
float increasedPadding = v.getIncreasedPaddingAmount();
if (increasedPadding != 0.0f) {
state.paddingMap.put(v, increasedPadding);
@@ -282,13 +294,11 @@ public class StackScrollAlgorithm {
ExpandableNotificationRow row = (ExpandableNotificationRow) v;
// handle the notgoneIndex for the children as well
List<ExpandableNotificationRow> children =
row.getNotificationChildren();
List<ExpandableNotificationRow> children = row.getNotificationChildren();
if (row.isSummaryWithChildren() && children != null) {
for (ExpandableNotificationRow childRow : children) {
if (childRow.getVisibility() != View.GONE) {
ExpandableViewState childState
= resultState.getViewStateForView(childRow);
ExpandableViewState childState = childRow.getViewState();
childState.notGoneIndex = notGoneIndex;
notGoneIndex++;
}
@@ -301,8 +311,8 @@ public class StackScrollAlgorithm {
ExpandableNotificationRow expandingNotification = ambientState.getExpandingNotification();
state.indexOfExpandingNotification = expandingNotification != null
? expandingNotification.isChildInGroup()
? state.visibleChildren.indexOf(expandingNotification.getNotificationParent())
: state.visibleChildren.indexOf(expandingNotification)
? state.visibleChildren.indexOf(expandingNotification.getNotificationParent())
: state.visibleChildren.indexOf(expandingNotification)
: -1;
}
@@ -322,10 +332,9 @@ public class StackScrollAlgorithm {
}
}
private int updateNotGoneIndex(StackScrollState resultState,
StackScrollAlgorithmState state, int notGoneIndex,
private int updateNotGoneIndex(StackScrollAlgorithmState state, int notGoneIndex,
ExpandableView v) {
ExpandableViewState viewState = resultState.getViewStateForView(v);
ExpandableViewState viewState = v.getViewState();
viewState.notGoneIndex = notGoneIndex;
state.visibleChildren.add(v);
notGoneIndex++;
@@ -335,27 +344,27 @@ public class StackScrollAlgorithm {
/**
* Determine the positions for the views. This is the main part of the algorithm.
*
* @param resultState The result state to update if a change to the properties of a child occurs
* @param algorithmState The state in which the current pass of the algorithm is currently in
* @param ambientState The current ambient state
* @param ambientState The current ambient state
*/
private void updatePositionsForState(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
private void updatePositionsForState(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
// 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);
currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition);
}
}
protected float updateChild(int i, StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState,
protected float updateChild(
int i,
StackScrollAlgorithmState algorithmState,
AmbientState ambientState,
float currentYPosition) {
ExpandableView child = algorithmState.visibleChildren.get(i);
ExpandableViewState childViewState = resultState.getViewStateForView(child);
ExpandableViewState childViewState = child.getViewState();
childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
int childHeight = getMaxAllowedChildHeight(child);
@@ -404,8 +413,8 @@ public class StackScrollAlgorithm {
return algorithmState.getPaddingAfterChild(child);
}
private void updateHeadsUpStates(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
private void updateHeadsUpStates(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
int childCount = algorithmState.visibleChildren.size();
ExpandableNotificationRow topHeadsUpEntry = null;
for (int i = 0; i < childCount; i++) {
@@ -417,7 +426,7 @@ public class StackScrollAlgorithm {
if (!row.isHeadsUp()) {
break;
}
ExpandableViewState childState = resultState.getViewStateForView(row);
ExpandableViewState childState = row.getViewState();
if (topHeadsUpEntry == null && row.mustStayOnScreen() && !childState.headsUpIsVisible) {
topHeadsUpEntry = row;
childState.location = ExpandableViewState.LOCATION_FIRST_HUN;
@@ -439,7 +448,8 @@ public class StackScrollAlgorithm {
childState.yTranslation = Math.max(childState.yTranslation, mHeadsUpInset);
childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
childState.hidden = false;
ExpandableViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
ExpandableViewState topState =
topHeadsUpEntry == null ? null : topHeadsUpEntry.getViewState();
if (topState != null && !isTopEntry && (!mIsExpanded
|| unmodifiedEndLocation < topState.yTranslation + topState.height)) {
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
@@ -491,9 +501,8 @@ public class StackScrollAlgorithm {
* Clamp the height of the child down such that its end is at most on the beginning of
* the shelf.
*
* @param child
* @param childViewState the view state of the child
* @param ambientState the ambient state
* @param ambientState the ambient state
*/
private void clampPositionToShelf(ExpandableView child,
ExpandableViewState childViewState,
@@ -521,31 +530,31 @@ public class StackScrollAlgorithm {
ExpandableView expandableView = (ExpandableView) child;
return expandableView.getIntrinsicHeight();
}
return child == null? mCollapsedSize : child.getHeight();
return child == null ? mCollapsedSize : child.getHeight();
}
/**
* Calculate the Z positions for all children based on the number of items in both stacks and
* save it in the resultState
* @param resultState The result state to update the zTranslation values
*
* @param algorithmState The state in which the current pass of the algorithm is currently in
* @param ambientState The ambient state of the algorithm
* @param ambientState The ambient state of the algorithm
*/
private void updateZValuesForState(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
private void updateZValuesForState(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
int childCount = algorithmState.visibleChildren.size();
float childrenOnTop = 0.0f;
for (int i = childCount - 1; i >= 0; i--) {
childrenOnTop = updateChildZValue(i, childrenOnTop,
resultState, algorithmState, ambientState);
algorithmState, ambientState);
}
}
protected float updateChildZValue(int i, float childrenOnTop,
StackScrollState resultState, StackScrollAlgorithmState algorithmState,
StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
ExpandableView child = algorithmState.visibleChildren.get(i);
ExpandableViewState childViewState = resultState.getViewStateForView(child);
ExpandableViewState childViewState = child.getViewState();
int zDistanceBetweenElements = ambientState.getZDistanceBetweenElements();
float baseZ = ambientState.getBaseZHeight();
if (child.mustStayOnScreen() && !childViewState.headsUpIsVisible

View File

@@ -1,117 +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.notification.stack;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import java.util.List;
import java.util.WeakHashMap;
/**
* A state of a
* {@link com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout} which
* can be applied to a viewGroup.
*/
public class StackScrollState {
private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
private final ViewGroup mHostView;
private WeakHashMap<ExpandableView, ExpandableViewState> mStateMap;
public StackScrollState(ViewGroup hostView) {
mHostView = hostView;
mStateMap = new WeakHashMap<>();
}
public ViewGroup getHostView() {
return mHostView;
}
public void resetViewStates() {
int numChildren = mHostView.getChildCount();
for (int i = 0; i < numChildren; i++) {
ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
resetViewState(child);
// handling reset for child notifications
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
List<ExpandableNotificationRow> children =
row.getNotificationChildren();
if (row.isSummaryWithChildren() && children != null) {
for (ExpandableNotificationRow childRow : children) {
resetViewState(childRow);
}
}
}
}
}
private void resetViewState(ExpandableView view) {
ExpandableViewState viewState = mStateMap.get(view);
if (viewState == null) {
viewState = view.createNewViewState(this);
mStateMap.put(view, viewState);
}
// initialize with the default values of the view
viewState.height = view.getIntrinsicHeight();
viewState.gone = view.getVisibility() == View.GONE;
viewState.alpha = 1f;
viewState.notGoneIndex = -1;
viewState.xTranslation = view.getTranslationX();
viewState.hidden = false;
viewState.scaleX = view.getScaleX();
viewState.scaleY = view.getScaleY();
viewState.inShelf = false;
viewState.headsUpIsVisible = false;
}
public ExpandableViewState getViewStateForView(View requestedView) {
return mStateMap.get(requestedView);
}
public void removeViewStateForView(View child) {
mStateMap.remove(child);
}
/**
* Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
* The properties are only applied if they effectively changed.
*/
public void apply() {
int numChildren = mHostView.getChildCount();
for (int i = 0; i < numChildren; i++) {
ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
ExpandableViewState state = mStateMap.get(child);
if (state == null) {
Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
"to the hostView");
continue;
}
if (state.gone) {
continue;
}
state.applyToView(child);
}
}
}

View File

@@ -128,25 +128,25 @@ public class StackStateAnimator {
public void startAnimationForEvents(
ArrayList<NotificationStackScrollLayout.AnimationEvent> mAnimationEvents,
StackScrollState finalState, long additionalDelay) {
long additionalDelay) {
processAnimationEvents(mAnimationEvents, finalState);
processAnimationEvents(mAnimationEvents);
int childCount = mHostLayout.getChildCount();
mAnimationFilter.applyCombination(mNewEvents);
mCurrentAdditionalDelay = additionalDelay;
mCurrentLength = NotificationStackScrollLayout.AnimationEvent.combineLength(mNewEvents);
mCurrentLastNotAddedIndex = findLastNotAddedIndex(finalState);
mCurrentLastNotAddedIndex = findLastNotAddedIndex();
for (int i = 0; i < childCount; i++) {
final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
ExpandableViewState viewState = finalState.getViewStateForView(child);
ExpandableViewState viewState = child.getViewState();
if (viewState == null || child.getVisibility() == View.GONE
|| applyWithoutAnimation(child, viewState, finalState)) {
|| applyWithoutAnimation(child, viewState)) {
continue;
}
initAnimationProperties(finalState, child, viewState);
initAnimationProperties(child, viewState);
viewState.animateTo(child, mAnimationProperties);
}
if (!isRunning()) {
@@ -159,7 +159,7 @@ public class StackStateAnimator {
mNewAddChildren.clear();
}
private void initAnimationProperties(StackScrollState finalState, ExpandableView child,
private void initAnimationProperties(ExpandableView child,
ExpandableViewState viewState) {
boolean wasAdded = mAnimationProperties.wasAdded(child);
mAnimationProperties.duration = mCurrentLength;
@@ -173,7 +173,7 @@ public class StackStateAnimator {
|| viewState.clipTopAmount != child.getClipTopAmount()
|| viewState.dark != child.isDark())) {
mAnimationProperties.delay = mCurrentAdditionalDelay
+ calculateChildAnimationDelay(viewState, finalState);
+ calculateChildAnimationDelay(viewState);
}
}
@@ -193,8 +193,7 @@ public class StackStateAnimator {
*
* @return true if no animation should be performed
*/
private boolean applyWithoutAnimation(ExpandableView child, ExpandableViewState viewState,
StackScrollState finalState) {
private boolean applyWithoutAnimation(ExpandableView child, ExpandableViewState viewState) {
if (mShadeExpanded) {
return false;
}
@@ -214,12 +213,12 @@ public class StackStateAnimator {
return true;
}
private int findLastNotAddedIndex(StackScrollState finalState) {
private int findLastNotAddedIndex() {
int childCount = mHostLayout.getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
ExpandableViewState viewState = finalState.getViewStateForView(child);
ExpandableViewState viewState = child.getViewState();
if (viewState == null || child.getVisibility() == View.GONE) {
continue;
}
@@ -230,8 +229,7 @@ public class StackStateAnimator {
return -1;
}
private long calculateChildAnimationDelay(ExpandableViewState viewState,
StackScrollState finalState) {
private long calculateChildAnimationDelay(ExpandableViewState viewState) {
if (mAnimationFilter.hasGoToFullShadeEvent) {
return calculateDelayGoToFullShade(viewState);
}
@@ -244,8 +242,8 @@ public class StackStateAnimator {
switch (event.animationType) {
case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD: {
int ownIndex = viewState.notGoneIndex;
int changingIndex = finalState
.getViewStateForView(event.changingView).notGoneIndex;
int changingIndex =
((ExpandableView) (event.mChangingView)).getViewState().notGoneIndex;
int difference = Math.abs(ownIndex - changingIndex);
difference = Math.max(0, Math.min(DELAY_EFFECT_MAX_INDEX_DIFFERENCE,
difference - 1));
@@ -258,9 +256,9 @@ public class StackStateAnimator {
case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE: {
int ownIndex = viewState.notGoneIndex;
boolean noNextView = event.viewAfterChangingView == null;
View viewAfterChangingView = noNextView
ExpandableView viewAfterChangingView = noNextView
? mHostLayout.getLastChildNotGone()
: event.viewAfterChangingView;
: (ExpandableView) event.viewAfterChangingView;
if (viewAfterChangingView == null) {
// This can happen when the last view in the list is removed.
// Since the shelf is still around and the only view, the code still goes
@@ -268,8 +266,7 @@ public class StackStateAnimator {
// have changed.
continue;
}
int nextIndex = finalState
.getViewStateForView(viewAfterChangingView).notGoneIndex;
int nextIndex = viewAfterChangingView.getViewState().notGoneIndex;
if (ownIndex >= nextIndex) {
// we only have the view afterwards
ownIndex++;
@@ -351,20 +348,17 @@ public class StackStateAnimator {
/**
* Process the animationEvents for a new animation
*
* @param animationEvents the animation events for the animation to perform
* @param finalState the final state to animate to
* @param animationEvents the animation events for the animation to perform
*/
private void processAnimationEvents(
ArrayList<NotificationStackScrollLayout.AnimationEvent> animationEvents,
StackScrollState finalState) {
ArrayList<NotificationStackScrollLayout.AnimationEvent> animationEvents) {
for (NotificationStackScrollLayout.AnimationEvent event : animationEvents) {
final ExpandableView changingView = (ExpandableView) event.changingView;
final ExpandableView changingView = (ExpandableView) event.mChangingView;
if (event.animationType ==
NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD) {
// This item is added, initialize it's properties.
ExpandableViewState viewState = finalState
.getViewStateForView(changingView);
ExpandableViewState viewState = changingView.getViewState();
if (viewState == null || viewState.gone) {
// The position for this child was never generated, let's continue.
continue;
@@ -381,8 +375,8 @@ public class StackStateAnimator {
// Find the amount to translate up. This is needed in order to understand the
// direction of the remove animation (either downwards or upwards)
ExpandableViewState viewState = finalState
.getViewStateForView(event.viewAfterChangingView);
ExpandableViewState viewState =
((ExpandableView) event.viewAfterChangingView).getViewState();
int actualHeight = changingView.getActualHeight();
// upwards by default
float translationDirection = -1.0f;
@@ -426,11 +420,11 @@ public class StackStateAnimator {
}
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_GROUP_EXPANSION_CHANGED) {
ExpandableNotificationRow row = (ExpandableNotificationRow) event.changingView;
row.prepareExpansionChanged(finalState);
ExpandableNotificationRow row = (ExpandableNotificationRow) event.mChangingView;
row.prepareExpansionChanged();
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_PULSE_APPEAR) {
ExpandableViewState viewState = finalState.getViewStateForView(changingView);
ExpandableViewState viewState = changingView.getViewState();
if (viewState != null) {
mTmpState.copyFrom(viewState);
mTmpState.yTranslation += mPulsingAppearingTranslation;
@@ -439,7 +433,7 @@ public class StackStateAnimator {
}
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
ExpandableViewState viewState = finalState.getViewStateForView(changingView);
ExpandableViewState viewState = changingView.getViewState();
if (viewState != null) {
viewState.alpha = 0;
// We want to animate the alpha away before the view starts translating,
@@ -454,7 +448,7 @@ public class StackStateAnimator {
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR) {
// This item is added, initialize it's properties.
ExpandableViewState viewState = finalState.getViewStateForView(changingView);
ExpandableViewState viewState = changingView.getViewState();
mTmpState.copyFrom(viewState);
if (event.headsUpFromBottom) {
mTmpState.yTranslation = mHeadsUpAppearHeightBottom;

View File

@@ -74,7 +74,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
@Mock private ShadeController mShadeController;
private NotificationViewHierarchyManager mViewHierarchyManager;
private NotificationTestHelper mHelper = new NotificationTestHelper(mContext);;
private NotificationTestHelper mHelper = new NotificationTestHelper(mContext);
@Before
public void setUp() {
@@ -209,19 +209,19 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
public void setChildTransferInProgress(boolean childTransferInProgress) {}
@Override
public void changeViewPosition(View child, int newIndex) {
public void changeViewPosition(ExpandableView child, int newIndex) {
mRows.remove(child);
mRows.add(newIndex, child);
}
@Override
public void notifyGroupChildAdded(View row) {}
public void notifyGroupChildAdded(ExpandableView row) {}
@Override
public void notifyGroupChildRemoved(View row, ViewGroup childrenContainer) {}
public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {}
@Override
public void generateAddAnimation(View child, boolean fromMoreCard) {}
public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {}
@Override
public void generateChildOrderChangedEvent() {}

View File

@@ -26,11 +26,11 @@ import static org.mockito.Mockito.when;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.View;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import org.junit.Assert;
import org.junit.Before;
@@ -45,7 +45,7 @@ import java.util.HashSet;
public class NotificationRoundnessManagerTest extends SysuiTestCase {
private NotificationRoundnessManager mRoundnessManager = new NotificationRoundnessManager();
private HashSet<View> mAnimatedChildren = new HashSet<>();
private HashSet<ExpandableView> mAnimatedChildren = new HashSet<>();
private Runnable mRoundnessCallback = mock(Runnable.class);
private ExpandableNotificationRow mFirst;
private ExpandableNotificationRow mSecond;