Merge "Children should have backgrounds" into nyc-dev
This commit is contained in:
@@ -18,7 +18,11 @@ package android.view;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RemoteViews;
|
||||
@@ -47,6 +51,18 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
private int mOriginalNotificationColor;
|
||||
private boolean mExpanded;
|
||||
private boolean mShowWorkBadgeAtEnd;
|
||||
private Drawable mBackground;
|
||||
private int mHeaderBackgroundHeight;
|
||||
|
||||
ViewOutlineProvider mProvider = new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
if (mBackground != null) {
|
||||
outline.setRect(0, 0, getWidth(), mHeaderBackgroundHeight);
|
||||
outline.setAlpha(1f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public NotificationHeaderView(Context context) {
|
||||
this(context, null);
|
||||
@@ -66,6 +82,8 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
com.android.internal.R.dimen.notification_header_shrink_min_width);
|
||||
mContentEndMargin = getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.notification_content_margin_end);
|
||||
mHeaderBackgroundHeight = getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.notification_header_background_height);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,6 +183,43 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
return new ViewGroup.MarginLayoutParams(getContext(), attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a {@link Drawable} to be displayed as a background on the header.
|
||||
*/
|
||||
public void setHeaderBackgroundDrawable(Drawable drawable) {
|
||||
if (drawable != null) {
|
||||
setWillNotDraw(false);
|
||||
mBackground = drawable;
|
||||
mBackground.setCallback(this);
|
||||
setOutlineProvider(mProvider);
|
||||
} else {
|
||||
setWillNotDraw(true);
|
||||
mBackground = null;
|
||||
setOutlineProvider(null);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mBackground != null) {
|
||||
mBackground.setBounds(0, 0, getWidth(), mHeaderBackgroundHeight);
|
||||
mBackground.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean verifyDrawable(Drawable who) {
|
||||
return super.verifyDrawable(who) || who == mBackground;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged() {
|
||||
if (mBackground != null && mBackground.isStateful()) {
|
||||
mBackground.setState(getDrawableState());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTouchListener() {
|
||||
if (mExpandClickListener != null) {
|
||||
mTouchListener.bindTouchRects();
|
||||
|
||||
@@ -163,6 +163,9 @@
|
||||
<!-- height of the content margin on the bottom -->
|
||||
<dimen name="notification_content_margin_bottom">16dp</dimen>
|
||||
|
||||
<!-- The height of the background for a notification header on a group -->
|
||||
<dimen name="notification_header_background_height">45.5dp</dimen>
|
||||
|
||||
<!-- Height of a small notification in the status bar -->
|
||||
<dimen name="notification_min_height">92dp</dimen>
|
||||
|
||||
|
||||
@@ -2436,6 +2436,7 @@
|
||||
<java-symbol type="dimen" name="notification_content_picture_margin" />
|
||||
<java-symbol type="dimen" name="notification_content_margin_top" />
|
||||
<java-symbol type="dimen" name="notification_content_margin_bottom" />
|
||||
<java-symbol type="dimen" name="notification_header_background_height" />
|
||||
<java-symbol type="string" name="importance_from_user" />
|
||||
<java-symbol type="string" name="importance_from_person" />
|
||||
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
android:id="@+id/notification_more_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/notification_divider_height"
|
||||
android:background="#61000000" />
|
||||
android:background="#FF616161" />
|
||||
|
||||
@@ -248,6 +248,9 @@
|
||||
<!-- The height of the divider between the individual notifications. -->
|
||||
<dimen name="notification_divider_height">0.5dp</dimen>
|
||||
|
||||
<!-- The height of a notification header -->
|
||||
<dimen name="notification_header_height">53dp</dimen>
|
||||
|
||||
<!-- The height of the divider between the individual notifications when the notification wants it to be increased. This is currently the case for notification groups -->
|
||||
<dimen name="notification_divider_height_increased">6dp</dimen>
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ public class ExpandHelper implements Gefingerpoken {
|
||||
void setUserLockedChild(View v, boolean userLocked);
|
||||
void expansionStateChanged(boolean isExpanding);
|
||||
int getMaxExpandHeight(ExpandableView view);
|
||||
void setExpansionCancelled(View view);
|
||||
}
|
||||
|
||||
private static final String TAG = "ExpandHelper";
|
||||
@@ -558,6 +559,8 @@ public class ExpandHelper implements Gefingerpoken {
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (!mCancelled) {
|
||||
mCallback.setUserExpandedChild(scaledView, expand);
|
||||
} else {
|
||||
mCallback.setExpansionCancelled(scaledView);
|
||||
}
|
||||
mCallback.setUserLockedChild(scaledView, false);
|
||||
mScaleAnimation.removeListener(this);
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
@@ -31,6 +30,8 @@ import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.util.Property;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.NotificationHeaderView;
|
||||
@@ -39,13 +40,11 @@ import android.view.ViewStub;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.Chronometer;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.android.internal.util.NotificationColorUtil;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.classifier.FalsingManager;
|
||||
import com.android.systemui.statusbar.notification.HybridNotificationView;
|
||||
import com.android.systemui.statusbar.notification.NotificationViewWrapper;
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupManager;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
|
||||
@@ -65,6 +64,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
private int mMaxHeadsUpHeight;
|
||||
private int mNotificationMinHeight;
|
||||
private int mNotificationMaxHeight;
|
||||
private int mIncreasedPaddingBetweenElements;
|
||||
|
||||
/** Does this row contain layouts that can adapt to row expansion */
|
||||
private boolean mExpandable;
|
||||
@@ -97,7 +97,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
*/
|
||||
private boolean mOnKeyguard;
|
||||
|
||||
private AnimatorSet mTranslateAnim;
|
||||
private Animator mTranslateAnim;
|
||||
private ArrayList<View> mTranslateableViews;
|
||||
private NotificationContentView mPublicLayout;
|
||||
private NotificationContentView mPrivateLayout;
|
||||
@@ -115,8 +115,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
private String mAppName;
|
||||
private boolean mIsHeadsUp;
|
||||
private boolean mLastChronometerRunning = true;
|
||||
private NotificationHeaderView mNotificationHeader;
|
||||
private NotificationViewWrapper mNotificationHeaderWrapper;
|
||||
private ViewStub mChildrenContainerStub;
|
||||
private NotificationGroupManager mGroupManager;
|
||||
private boolean mChildrenExpanded;
|
||||
@@ -128,13 +126,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
private boolean mIsPinned;
|
||||
private FalsingManager mFalsingManager;
|
||||
private HeadsUpManager mHeadsUpManager;
|
||||
private NotificationHeaderUtil mHeaderUtil = new NotificationHeaderUtil(this);
|
||||
|
||||
private boolean mJustClicked;
|
||||
private boolean mIconAnimationRunning;
|
||||
private boolean mShowNoBackground;
|
||||
private ExpandableNotificationRow mNotificationParent;
|
||||
private OnExpandClickListener mOnExpandClickListener;
|
||||
private boolean mGroupExpansionChanging;
|
||||
|
||||
private OnClickListener mExpandClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -142,6 +141,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
mGroupManager.toggleGroupExpansion(mStatusBarNotification);
|
||||
mOnExpandClickListener.onExpandClicked(mEntry,
|
||||
mGroupManager.isGroupExpanded(mStatusBarNotification));
|
||||
mGroupExpansionChanging = true;
|
||||
updateBackgroundForGroupState();
|
||||
} else {
|
||||
boolean nowExpanded;
|
||||
if (isPinned()) {
|
||||
@@ -160,6 +161,29 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
private boolean mDismissed;
|
||||
private boolean mKeepInParent;
|
||||
private boolean mRemoved;
|
||||
private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
|
||||
new FloatProperty<ExpandableNotificationRow>("translate") {
|
||||
@Override
|
||||
public void setValue(ExpandableNotificationRow object, float value) {
|
||||
object.setTranslation(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(ExpandableNotificationRow object) {
|
||||
return object.getTranslation();
|
||||
}
|
||||
};
|
||||
|
||||
public boolean isGroupExpansionChanging() {
|
||||
if (isChildInGroup()) {
|
||||
return mNotificationParent.isGroupExpansionChanging();
|
||||
}
|
||||
return mGroupExpansionChanging;
|
||||
}
|
||||
|
||||
public void setGroupExpansionChanging(boolean changing) {
|
||||
mGroupExpansionChanging = changing;
|
||||
}
|
||||
|
||||
public NotificationContentView getPrivateLayout() {
|
||||
return mPrivateLayout;
|
||||
@@ -172,8 +196,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
public void setIconAnimationRunning(boolean running) {
|
||||
setIconAnimationRunning(running, mPublicLayout);
|
||||
setIconAnimationRunning(running, mPrivateLayout);
|
||||
setIconAnimationRunningForChild(running, mNotificationHeader);
|
||||
if (mIsSummaryWithChildren) {
|
||||
setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView());
|
||||
List<ExpandableNotificationRow> notificationChildren =
|
||||
mChildrenContainer.getNotificationChildren();
|
||||
for (int i = 0; i < notificationChildren.size(); i++) {
|
||||
@@ -235,7 +259,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
updateNotificationColor();
|
||||
updateClearability();
|
||||
if (mIsSummaryWithChildren) {
|
||||
recreateNotificationHeader();
|
||||
mChildrenContainer.recreateNotificationHeader(mExpandClickListener, mEntry.notification);
|
||||
mChildrenContainer.onNotificationUpdated();
|
||||
}
|
||||
if (mIconAnimationRunning) {
|
||||
@@ -329,9 +353,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
if (mChildrenContainer != null) {
|
||||
mChildrenContainer.removeNotification(row);
|
||||
}
|
||||
if (!row.isRemoved()) {
|
||||
mHeaderUtil.restoreNotificationHeader(row);
|
||||
}
|
||||
onChildrenCountChanged();
|
||||
row.setIsChildInGroup(false, null);
|
||||
}
|
||||
@@ -352,7 +373,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
|
||||
mNotificationParent = childInGroup ? parent : null;
|
||||
mPrivateLayout.setIsChildInGroup(childInGroup);
|
||||
updateNoBackgroundState();
|
||||
updateBackgroundForGroupState();
|
||||
if (mNotificationParent != null) {
|
||||
mNotificationParent.updateBackgroundForGroupState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -544,15 +568,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
}
|
||||
|
||||
public NotificationHeaderView getNotificationHeader() {
|
||||
if (mNotificationHeader != null) {
|
||||
return mNotificationHeader;
|
||||
if (mIsSummaryWithChildren) {
|
||||
return mChildrenContainer.getHeaderView();
|
||||
}
|
||||
return mPrivateLayout.getNotificationHeader();
|
||||
}
|
||||
|
||||
private NotificationHeaderView getVisibleNotificationHeader() {
|
||||
if (mNotificationHeader != null) {
|
||||
return mNotificationHeader;
|
||||
if (mIsSummaryWithChildren) {
|
||||
return mChildrenContainer.getHeaderView();
|
||||
}
|
||||
return getShowingLayout().getVisibleNotificationHeader();
|
||||
}
|
||||
@@ -568,11 +592,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
public void reInflateViews() {
|
||||
initDimens();
|
||||
if (mIsSummaryWithChildren) {
|
||||
removeView(mNotificationHeader);
|
||||
mNotificationHeader = null;
|
||||
recreateNotificationHeader();
|
||||
if (mChildrenContainer != null) {
|
||||
mChildrenContainer.reInflateViews();
|
||||
mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
|
||||
}
|
||||
}
|
||||
if (mGuts != null) {
|
||||
@@ -646,9 +667,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
continue;
|
||||
}
|
||||
mChildrenContainer.removeNotification(row);
|
||||
if (!row.isRemoved()) {
|
||||
mHeaderUtil.restoreNotificationHeader(row);
|
||||
}
|
||||
row.setIsChildInGroup(false, null);
|
||||
}
|
||||
onChildrenCountChanged();
|
||||
@@ -709,6 +727,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
mMaxHeadsUpHeightLegacy = getFontScaledHeight(
|
||||
R.dimen.notification_max_heads_up_height_legacy);
|
||||
mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height);
|
||||
mIncreasedPaddingBetweenElements = getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -804,17 +824,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
mTranslateableViews.remove(mGutsStub);
|
||||
}
|
||||
|
||||
private void setTranslationForOutline(float translationX) {
|
||||
setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
|
||||
}
|
||||
|
||||
public void resetTranslation() {
|
||||
if (mTranslateableViews != null) {
|
||||
for (int i = 0; i < mTranslateableViews.size(); i++) {
|
||||
mTranslateableViews.get(i).setTranslationX(0);
|
||||
}
|
||||
setTranslationForOutline(0);
|
||||
}
|
||||
invalidateOutline();
|
||||
if (mSettingsIconRow != null) {
|
||||
mSettingsIconRow.resetState();
|
||||
}
|
||||
@@ -824,8 +840,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
if (mTranslateAnim != null) {
|
||||
mTranslateAnim.cancel();
|
||||
}
|
||||
mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
|
||||
null /* updateListener */);
|
||||
mTranslateAnim = getTranslateViewAnimator(leftTarget, null /* updateListener */);
|
||||
if (mTranslateAnim != null) {
|
||||
mTranslateAnim.start();
|
||||
}
|
||||
@@ -843,7 +858,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
mTranslateableViews.get(i).setTranslationX(translationX);
|
||||
}
|
||||
}
|
||||
setTranslationForOutline(translationX);
|
||||
invalidateOutline();
|
||||
if (mSettingsIconRow != null) {
|
||||
mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
|
||||
}
|
||||
@@ -867,48 +882,29 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
// No translation if guts are exposed.
|
||||
return null;
|
||||
}
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
if (mTranslateableViews != null) {
|
||||
for (int i = 0; i < mTranslateableViews.size(); i++) {
|
||||
final View animView = mTranslateableViews.get(i);
|
||||
final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(
|
||||
animView, "translationX", leftTarget);
|
||||
if (i == 0) {
|
||||
translateAnim.addUpdateListener(new AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
setTranslationForOutline((float) animation.getAnimatedValue());
|
||||
if (mSettingsIconRow != null) {
|
||||
mSettingsIconRow.updateSettingsIcons(
|
||||
(float) animation.getAnimatedValue(), getMeasuredWidth());
|
||||
}
|
||||
}
|
||||
});
|
||||
if (listener != null) {
|
||||
translateAnim.addUpdateListener(listener);
|
||||
}
|
||||
translateAnim.addListener(new AnimatorListenerAdapter() {
|
||||
boolean cancelled = false;
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator anim) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator anim) {
|
||||
if (!cancelled && mSettingsIconRow != null && leftTarget == 0) {
|
||||
mSettingsIconRow.resetState();
|
||||
mTranslateAnim = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
set.play(translateAnim);
|
||||
}
|
||||
final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(this, TRANSLATE_CONTENT,
|
||||
leftTarget);
|
||||
if (listener != null) {
|
||||
translateAnim.addUpdateListener(listener);
|
||||
}
|
||||
mTranslateAnim = set;
|
||||
return set;
|
||||
translateAnim.addListener(new AnimatorListenerAdapter() {
|
||||
boolean cancelled = false;
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator anim) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator anim) {
|
||||
if (!cancelled && mSettingsIconRow != null && leftTarget == 0) {
|
||||
mSettingsIconRow.resetState();
|
||||
mTranslateAnim = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
mTranslateAnim = translateAnim;
|
||||
return translateAnim;
|
||||
}
|
||||
|
||||
public float getSpaceForGear() {
|
||||
@@ -937,9 +933,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
if (mChildrenContainer != null) {
|
||||
mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
|
||||
: INVISIBLE);
|
||||
}
|
||||
if (mNotificationHeader != null) {
|
||||
mNotificationHeader.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
|
||||
mChildrenContainer.updateHeaderVisibility(!mShowingPublic && mIsSummaryWithChildren
|
||||
? VISIBLE
|
||||
: INVISIBLE);
|
||||
}
|
||||
// The limits might have changed if the view suddenly became a group or vice versa
|
||||
@@ -969,7 +964,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
}
|
||||
if (mIsSummaryWithChildren) {
|
||||
mChildrenContainer.setDark(dark, fade, delay);
|
||||
mNotificationHeaderWrapper.setDark(dark, fade, delay);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1044,6 +1038,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
mPrivateLayout.setUserExpanding(userLocked);
|
||||
if (mIsSummaryWithChildren) {
|
||||
mChildrenContainer.setUserLocked(userLocked);
|
||||
if (userLocked) {
|
||||
updateBackgroundForGroupState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1123,30 +1120,28 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isGroupExpanded() {
|
||||
public boolean isGroupExpanded() {
|
||||
return mGroupManager.isGroupExpanded(mStatusBarNotification);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether this view has a header on the top of the content
|
||||
*/
|
||||
private boolean hasNotificationHeader() {
|
||||
return mIsSummaryWithChildren;
|
||||
}
|
||||
|
||||
private void onChildrenCountChanged() {
|
||||
mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
|
||||
&& mChildrenContainer != null && mChildrenContainer.getChildCount() > 0;
|
||||
if (mIsSummaryWithChildren) {
|
||||
if (mNotificationHeader == null) {
|
||||
recreateNotificationHeader();
|
||||
}
|
||||
&& mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0;
|
||||
if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
|
||||
mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
|
||||
mEntry.notification);
|
||||
}
|
||||
mPrivateLayout.updateExpandButtons(isExpandable());
|
||||
updateChildrenHeaderAppearance();
|
||||
updateChildrenVisibility();
|
||||
}
|
||||
|
||||
public void updateChildrenHeaderAppearance() {
|
||||
if (mChildrenContainer != null) {
|
||||
mChildrenContainer.updateChildrenHeaderAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the view state is currently expanded. This is given by the system in {@link
|
||||
* #setSystemExpanded(boolean)} and can be overridden by user expansion or
|
||||
@@ -1251,8 +1246,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
}
|
||||
|
||||
private void animateShowingPublic(long delay, long duration) {
|
||||
View[] privateViews = mIsSummaryWithChildren ?
|
||||
new View[] {mChildrenContainer, mNotificationHeader}
|
||||
View[] privateViews = mIsSummaryWithChildren
|
||||
? new View[] {mChildrenContainer}
|
||||
: new View[] {mPrivateLayout};
|
||||
View[] publicViews = new View[] {mPublicLayout};
|
||||
View[] hiddenChildren = mShowingPublic ? privateViews : publicViews;
|
||||
@@ -1302,9 +1297,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
|
||||
public void setChildrenExpanded(boolean expanded, boolean animate) {
|
||||
mChildrenExpanded = expanded;
|
||||
if (mNotificationHeader != null) {
|
||||
mNotificationHeader.setExpanded(expanded);
|
||||
}
|
||||
if (mChildrenContainer != null) {
|
||||
mChildrenContainer.setChildrenExpanded(expanded);
|
||||
}
|
||||
@@ -1348,6 +1340,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
return getShowingLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getExtraBottomPadding() {
|
||||
if (mIsSummaryWithChildren && isGroupExpanded()) {
|
||||
return mIncreasedPaddingBetweenElements;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActualHeight(int height, boolean notifyListeners) {
|
||||
super.setActualHeight(height, notifyListeners);
|
||||
@@ -1406,33 +1406,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
}
|
||||
}
|
||||
|
||||
private void recreateNotificationHeader() {
|
||||
final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
|
||||
getStatusBarNotification().getNotification());
|
||||
final RemoteViews header = builder.makeNotificationHeader();
|
||||
if (mNotificationHeader == null) {
|
||||
mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
|
||||
final View expandButton = mNotificationHeader.findViewById(
|
||||
com.android.internal.R.id.expand_button);
|
||||
expandButton.setVisibility(VISIBLE);
|
||||
mNotificationHeader.setOnClickListener(mExpandClickListener);
|
||||
mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
|
||||
mNotificationHeader, this);
|
||||
addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1);
|
||||
mTranslateableViews.add(mNotificationHeader);
|
||||
} else {
|
||||
header.reapply(getContext(), mNotificationHeader);
|
||||
mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
|
||||
}
|
||||
updateChildrenHeaderAppearance();
|
||||
}
|
||||
|
||||
public void updateChildrenHeaderAppearance() {
|
||||
if (mIsSummaryWithChildren) {
|
||||
mHeaderUtil.updateChildrenHeaderAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMaxExpandHeightInitialized() {
|
||||
return mMaxExpandHeight != 0;
|
||||
}
|
||||
@@ -1451,19 +1424,50 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
@Override
|
||||
protected void updateBackgroundTint() {
|
||||
super.updateBackgroundTint();
|
||||
updateNoBackgroundState();
|
||||
updateBackgroundForGroupState();
|
||||
if (mIsSummaryWithChildren) {
|
||||
List<ExpandableNotificationRow> notificationChildren =
|
||||
mChildrenContainer.getNotificationChildren();
|
||||
for (int i = 0; i < notificationChildren.size(); i++) {
|
||||
ExpandableNotificationRow child = notificationChildren.get(i);
|
||||
child.updateNoBackgroundState();
|
||||
child.updateBackgroundForGroupState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNoBackgroundState() {
|
||||
mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
|
||||
/**
|
||||
* Called when a group has finished animating from collapsed or expanded state.
|
||||
*/
|
||||
public void onFinishedExpansionChange() {
|
||||
mGroupExpansionChanging = false;
|
||||
updateBackgroundForGroupState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the parent and children backgrounds in a group based on the expansion state.
|
||||
*/
|
||||
public void updateBackgroundForGroupState() {
|
||||
if (mIsSummaryWithChildren) {
|
||||
// Only when the group has finished expanding do we hide its background.
|
||||
mShowNoBackground = isGroupExpanded() && !isGroupExpansionChanging() && !isUserLocked();
|
||||
mChildrenContainer.updateHeaderForExpansion(mShowNoBackground);
|
||||
List<ExpandableNotificationRow> children = mChildrenContainer.getNotificationChildren();
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
children.get(i).updateBackgroundForGroupState();
|
||||
}
|
||||
} else if (isChildInGroup()) {
|
||||
final int childColor = getShowingLayout().getBackgroundColorForExpansionState();
|
||||
// Only show a background if the group is expanded OR if it is expanding / collapsing
|
||||
// and has a custom background color
|
||||
final boolean showBackground = isGroupExpanded()
|
||||
|| ((mNotificationParent.isGroupExpansionChanging()
|
||||
|| mNotificationParent.isUserLocked()) && childColor != 0);
|
||||
mShowNoBackground = !showBackground;
|
||||
} else {
|
||||
// Only children or parents ever need no background.
|
||||
mShowNoBackground = false;
|
||||
}
|
||||
updateOutline();
|
||||
updateBackground();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,22 +33,25 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
private boolean mCustomOutline;
|
||||
private float mOutlineAlpha = -1f;
|
||||
|
||||
ViewOutlineProvider mProvider = new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
int translation = (int) getTranslation();
|
||||
if (!mCustomOutline) {
|
||||
outline.setRect(translation,
|
||||
mClipTopAmount,
|
||||
getWidth() + translation,
|
||||
Math.max(getActualHeight(), mClipTopAmount));
|
||||
} else {
|
||||
outline.setRect(mOutlineRect);
|
||||
}
|
||||
outline.setAlpha(mOutlineAlpha);
|
||||
}
|
||||
};
|
||||
|
||||
public ExpandableOutlineView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
if (!mCustomOutline) {
|
||||
outline.setRect(0,
|
||||
mClipTopAmount,
|
||||
getWidth(),
|
||||
Math.max(getActualHeight(), mClipTopAmount));
|
||||
} else {
|
||||
outline.setRect(mOutlineRect);
|
||||
}
|
||||
outline.setAlpha(mOutlineAlpha);
|
||||
}
|
||||
});
|
||||
setOutlineProvider(mProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,17 +90,30 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
|
||||
@Override
|
||||
public int getOutlineTranslation() {
|
||||
return mCustomOutline ? mOutlineRect.left : 0;
|
||||
return mCustomOutline ? mOutlineRect.left : (int) getTranslation();
|
||||
}
|
||||
|
||||
public void updateOutline() {
|
||||
if (mCustomOutline) {
|
||||
return;
|
||||
}
|
||||
boolean hasOutline = true;
|
||||
if (isChildInGroup()) {
|
||||
hasOutline = isGroupExpanded() && !isGroupExpansionChanging();
|
||||
} else if (isSummaryWithChildren()) {
|
||||
hasOutline = !isGroupExpanded() || isGroupExpansionChanging();
|
||||
}
|
||||
setOutlineProvider(hasOutline ? mProvider : null);
|
||||
}
|
||||
|
||||
public boolean isOutlineShowing() {
|
||||
ViewOutlineProvider op = getOutlineProvider();
|
||||
return op != null;
|
||||
}
|
||||
|
||||
protected void setOutlineRect(float left, float top, float right, float bottom) {
|
||||
setOutlineRect(true, left, top, right, bottom);
|
||||
}
|
||||
|
||||
protected void setOutlineRect(boolean clipToOutline, float left, float top, float right,
|
||||
float bottom) {
|
||||
mCustomOutline = true;
|
||||
setClipToOutline(clipToOutline);
|
||||
setClipToOutline(true);
|
||||
|
||||
mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom);
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ public abstract class ExpandableView extends FrameLayout {
|
||||
if (top >= getActualHeight()) {
|
||||
top = getActualHeight() - 1;
|
||||
}
|
||||
mClipRect.set(0, top, getWidth(), getActualHeight());
|
||||
mClipRect.set(0, top, getWidth(), getActualHeight() + getExtraBottomPadding());
|
||||
setClipBounds(mClipRect);
|
||||
} else {
|
||||
setClipBounds(null);
|
||||
@@ -410,6 +410,28 @@ public abstract class ExpandableView extends FrameLayout {
|
||||
return mTransientContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return padding used to alter how much of the view is clipped.
|
||||
*/
|
||||
public int getExtraBottomPadding() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the group's expansion state is changing, false otherwise.
|
||||
*/
|
||||
public boolean isGroupExpansionChanging() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isGroupExpanded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isChildInGroup() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A listener notifying when {@link #getActualHeight} changes.
|
||||
*/
|
||||
|
||||
@@ -71,7 +71,6 @@ public class NotificationContentView extends FrameLayout {
|
||||
private HybridGroupManager mHybridGroupManager;
|
||||
private int mClipTopAmount;
|
||||
private int mContentHeight;
|
||||
private int mUnrestrictedContentHeight;
|
||||
private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
|
||||
private boolean mDark;
|
||||
private boolean mAnimate;
|
||||
@@ -371,8 +370,7 @@ public class NotificationContentView extends FrameLayout {
|
||||
}
|
||||
|
||||
public void setContentHeight(int contentHeight) {
|
||||
mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());;
|
||||
mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
|
||||
mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());
|
||||
selectLayout(mAnimate /* animate */, false /* force */);
|
||||
|
||||
int minHeightHint = getMinContentHeightHint();
|
||||
@@ -591,7 +589,21 @@ public class NotificationContentView extends FrameLayout {
|
||||
mContainingNotification.setContentBackground(customBackgroundColor, animate, this);
|
||||
}
|
||||
|
||||
private int getBackgroundColor(int visibleType) {
|
||||
public int getVisibleType() {
|
||||
return mVisibleType;
|
||||
}
|
||||
|
||||
public int getBackgroundColorForExpansionState() {
|
||||
// When expanding or user locked we want the new type, when collapsing we want
|
||||
// the original type
|
||||
final int visibleType = (mContainingNotification.isGroupExpanded()
|
||||
|| mContainingNotification.isUserLocked())
|
||||
? calculateVisibleType()
|
||||
: getVisibleType();
|
||||
return getBackgroundColor(visibleType);
|
||||
}
|
||||
|
||||
public int getBackgroundColor(int visibleType) {
|
||||
NotificationViewWrapper currentVisibleWrapper = getVisibleWrapper(visibleType);
|
||||
int customBackgroundColor = 0;
|
||||
if (currentVisibleWrapper != null) {
|
||||
@@ -699,7 +711,7 @@ public class NotificationContentView extends FrameLayout {
|
||||
/**
|
||||
* @return one of the static enum types in this view, calculated form the current state
|
||||
*/
|
||||
private int calculateVisibleType() {
|
||||
public int calculateVisibleType() {
|
||||
if (mUserExpanding) {
|
||||
int height = !mIsChildInGroup || isGroupExpanded()
|
||||
|| mContainingNotification.isExpanded(true /* allowOnKeyguard */)
|
||||
|
||||
@@ -90,7 +90,7 @@ public class NotificationHeaderUtil {
|
||||
private final ArrayList<HeaderProcessor> mComparators = new ArrayList<>();
|
||||
private final HashSet<Integer> mDividers = new HashSet<>();
|
||||
|
||||
NotificationHeaderUtil(ExpandableNotificationRow row) {
|
||||
public NotificationHeaderUtil(ExpandableNotificationRow row) {
|
||||
mRow = row;
|
||||
// To hide the icons if they are the same and the color is the same
|
||||
mComparators.add(new HeaderProcessor(mRow,
|
||||
|
||||
@@ -4335,6 +4335,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
if (expandView instanceof ExpandableNotificationRow) {
|
||||
row = (ExpandableNotificationRow) expandView;
|
||||
row.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */);
|
||||
// Indicate that the group expansion is changing at this time -- this way the group
|
||||
// and children backgrounds / divider animations will look correct.
|
||||
row.setGroupExpansionChanging(true);
|
||||
}
|
||||
boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
|
||||
|| !mShowLockscreenNotifications || mFalsingManager.shouldEnforceBouncer();
|
||||
|
||||
@@ -16,21 +16,28 @@
|
||||
|
||||
package com.android.systemui.statusbar.stack;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.NotificationHeaderView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.ViewInvertHelper;
|
||||
import com.android.systemui.statusbar.CrossFadeHelper;
|
||||
import com.android.systemui.statusbar.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.NotificationHeaderUtil;
|
||||
import com.android.systemui.statusbar.notification.HybridGroupManager;
|
||||
import com.android.systemui.statusbar.notification.HybridNotificationView;
|
||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
import com.android.systemui.statusbar.notification.NotificationViewWrapper;
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -51,7 +58,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
private int mChildPadding;
|
||||
private int mDividerHeight;
|
||||
private int mMaxNotificationHeight;
|
||||
private int mNotificationHeaderHeight;
|
||||
private int mNotificationHeaderMargin;
|
||||
private int mNotificatonTopPadding;
|
||||
private float mCollapsedBottompadding;
|
||||
private ViewInvertHelper mOverflowInvertHelper;
|
||||
@@ -63,6 +70,12 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
private boolean mUserLocked;
|
||||
private int mActualHeight;
|
||||
private boolean mNeverAppliedGroupState;
|
||||
private int mHeaderHeight;
|
||||
|
||||
private NotificationHeaderView mNotificationHeader;
|
||||
private NotificationViewWrapper mNotificationHeaderWrapper;
|
||||
private NotificationHeaderUtil mHeaderUtil;
|
||||
private ViewState mHeaderViewState;
|
||||
|
||||
public NotificationChildrenContainer(Context context) {
|
||||
this(context, null);
|
||||
@@ -88,9 +101,10 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
R.dimen.notification_children_padding);
|
||||
mDividerHeight = Math.max(1, getResources().getDimensionPixelSize(
|
||||
R.dimen.notification_divider_height));
|
||||
mHeaderHeight = getResources().getDimensionPixelSize(R.dimen.notification_header_height);
|
||||
mMaxNotificationHeight = getResources().getDimensionPixelSize(
|
||||
R.dimen.notification_max_height);
|
||||
mNotificationHeaderHeight = getResources().getDimensionPixelSize(
|
||||
mNotificationHeaderMargin = getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.notification_content_margin_top);
|
||||
mNotificatonTopPadding = getResources().getDimensionPixelSize(
|
||||
R.dimen.notification_children_container_top_padding);
|
||||
@@ -112,6 +126,10 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
mOverflowNumber.layout(getWidth() - mOverflowNumber.getMeasuredWidth(), 0, getWidth(),
|
||||
mOverflowNumber.getMeasuredHeight());
|
||||
}
|
||||
if (mNotificationHeader != null) {
|
||||
mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(),
|
||||
mNotificationHeader.getMeasuredHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,7 +149,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
newHeightSpec);
|
||||
}
|
||||
int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY);
|
||||
int height = mNotificationHeaderHeight + mNotificatonTopPadding;
|
||||
int height = mNotificationHeaderMargin + mNotificatonTopPadding;
|
||||
int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
|
||||
int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
|
||||
int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1;
|
||||
@@ -155,6 +173,12 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
if (heightMode != MeasureSpec.UNSPECIFIED) {
|
||||
height = Math.min(height, size);
|
||||
}
|
||||
|
||||
if (mNotificationHeader != null) {
|
||||
int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
|
||||
mNotificationHeader.measure(widthMeasureSpec, headerHeightSpec);
|
||||
}
|
||||
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
||||
@@ -201,6 +225,41 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
row.setSystemChildExpanded(false);
|
||||
row.setUserLocked(false);
|
||||
updateGroupOverflow();
|
||||
if (!row.isRemoved()) {
|
||||
mHeaderUtil.restoreNotificationHeader(row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of notification children in the container.
|
||||
*/
|
||||
public int getNotificationChildCount() {
|
||||
return mChildren.size();
|
||||
}
|
||||
|
||||
public void recreateNotificationHeader(OnClickListener listener, StatusBarNotification notification) {
|
||||
final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
|
||||
mNotificationParent.getStatusBarNotification().getNotification());
|
||||
final RemoteViews header = builder.makeNotificationHeader();
|
||||
if (mNotificationHeader == null) {
|
||||
mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
|
||||
final View expandButton = mNotificationHeader.findViewById(
|
||||
com.android.internal.R.id.expand_button);
|
||||
expandButton.setVisibility(VISIBLE);
|
||||
mNotificationHeader.setOnClickListener(listener);
|
||||
mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
|
||||
mNotificationHeader, mNotificationParent);
|
||||
addView(mNotificationHeader, 0);
|
||||
invalidate();
|
||||
} else {
|
||||
header.reapply(getContext(), mNotificationHeader);
|
||||
mNotificationHeaderWrapper.notifyContentUpdated(notification);
|
||||
}
|
||||
updateChildrenHeaderAppearance();
|
||||
}
|
||||
|
||||
public void updateChildrenHeaderAppearance() {
|
||||
mHeaderUtil.updateChildrenHeaderAppearance();
|
||||
}
|
||||
|
||||
public void updateGroupOverflow() {
|
||||
@@ -210,7 +269,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
mOverflowNumber = mHybridGroupManager.bindOverflowNumber(
|
||||
mOverflowNumber, childCount - maxAllowedVisibleChildren);
|
||||
if (mOverflowInvertHelper == null) {
|
||||
mOverflowInvertHelper= new ViewInvertHelper(mOverflowNumber,
|
||||
mOverflowInvertHelper = new ViewInvertHelper(mOverflowNumber,
|
||||
NotificationPanelView.DOZE_ANIMATION_DURATION);
|
||||
}
|
||||
if (mGroupOverFlowState == null) {
|
||||
@@ -300,7 +359,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
* in @param maxAllowedVisibleChildren
|
||||
*/
|
||||
private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
|
||||
int intrinsicHeight = mNotificationHeaderHeight;
|
||||
int intrinsicHeight = mNotificationHeaderMargin;
|
||||
int visibleChildren = 0;
|
||||
int childCount = mChildren.size();
|
||||
boolean firstChild = true;
|
||||
@@ -353,7 +412,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
*/
|
||||
public void getState(StackScrollState resultState, StackViewState parentState) {
|
||||
int childCount = mChildren.size();
|
||||
int yPosition = mNotificationHeaderHeight;
|
||||
int yPosition = mNotificationHeaderMargin;
|
||||
boolean firstChild = true;
|
||||
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
|
||||
int lastVisibleIndex = maxAllowedVisibleChildren - 1;
|
||||
@@ -363,12 +422,16 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
expandFactor = getGroupExpandFraction();
|
||||
firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
|
||||
}
|
||||
|
||||
boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging()
|
||||
&& mChildrenExpanded;
|
||||
int parentHeight = parentState.height;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
ExpandableNotificationRow child = mChildren.get(i);
|
||||
if (!firstChild) {
|
||||
if (mUserLocked) {
|
||||
yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
|
||||
expandFactor);
|
||||
yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
|
||||
expandFactor);
|
||||
} else {
|
||||
yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
|
||||
}
|
||||
@@ -383,11 +446,28 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
}
|
||||
firstChild = false;
|
||||
}
|
||||
|
||||
StackViewState childState = resultState.getViewStateForView(child);
|
||||
int intrinsicHeight = child.getIntrinsicHeight();
|
||||
if (childrenExpanded) {
|
||||
// When a group is expanded and moving into bottom stack, the bottom visible child
|
||||
// adjusts its height to move into it. Children after it are hidden.
|
||||
if (updateChildStateForExpandedGroup(child, parentHeight, childState, yPosition)) {
|
||||
// Clipping might be deactivated if the view is transforming, however, clipping
|
||||
// the child into the bottom stack should take precedent over this.
|
||||
childState.isBottomClipped = true;
|
||||
}
|
||||
} else {
|
||||
childState.hidden = false;
|
||||
childState.height = intrinsicHeight;
|
||||
childState.isBottomClipped = false;
|
||||
}
|
||||
childState.yTranslation = yPosition;
|
||||
childState.zTranslation = 0;
|
||||
childState.height = intrinsicHeight;
|
||||
// When the group is expanded, the children cast the shadows rather than the parent
|
||||
// so use the parent's elevation here.
|
||||
childState.zTranslation = childrenExpanded
|
||||
? mNotificationParent.getTranslationZ()
|
||||
: 0;
|
||||
childState.dimmed = parentState.dimmed;
|
||||
childState.dark = parentState.dark;
|
||||
childState.hideSensitive = parentState.hideSensitive;
|
||||
@@ -422,10 +502,44 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
mGroupOverFlowState.alpha = mirrorView.getAlpha();
|
||||
}
|
||||
} else {
|
||||
mGroupOverFlowState.yTranslation += mNotificationHeaderHeight;
|
||||
mGroupOverFlowState.yTranslation += mNotificationHeaderMargin;
|
||||
mGroupOverFlowState.alpha = 0.0f;
|
||||
}
|
||||
}
|
||||
if (mNotificationHeader != null) {
|
||||
if (mHeaderViewState == null) {
|
||||
mHeaderViewState = new ViewState();
|
||||
}
|
||||
mHeaderViewState.initFrom(mNotificationHeader);
|
||||
mHeaderViewState.zTranslation = childrenExpanded
|
||||
? mNotificationParent.getTranslationZ()
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When moving into the bottom stack, the bottom visible child in an expanded group adjusts its
|
||||
* height, children in the group after this are gone.
|
||||
*
|
||||
* @param child the child who's height to adjust.
|
||||
* @param parentHeight the height of the parent.
|
||||
* @param childState the state to update.
|
||||
* @param yPosition the yPosition of the view.
|
||||
* @return true if children after this one should be hidden.
|
||||
*/
|
||||
private boolean updateChildStateForExpandedGroup(ExpandableNotificationRow child,
|
||||
int parentHeight, StackViewState childState, int yPosition) {
|
||||
final int top = yPosition + child.getClipTopAmount();
|
||||
final int intrinsicHeight = child.getIntrinsicHeight();
|
||||
final int bottom = top + intrinsicHeight;
|
||||
int newHeight = intrinsicHeight;
|
||||
if (bottom >= parentHeight) {
|
||||
// Child is either clipped or gone
|
||||
newHeight = Math.max((parentHeight - top), 0);
|
||||
}
|
||||
childState.hidden = newHeight == 0;
|
||||
childState.height = newHeight;
|
||||
return childState.height != intrinsicHeight && !childState.hidden;
|
||||
}
|
||||
|
||||
private int getMaxAllowedVisibleChildren() {
|
||||
@@ -450,6 +564,8 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
if (mUserLocked) {
|
||||
expandFraction = getGroupExpandFraction();
|
||||
}
|
||||
final boolean dividersVisible = mUserLocked
|
||||
|| mNotificationParent.isGroupExpansionChanging();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
ExpandableNotificationRow child = mChildren.get(i);
|
||||
StackViewState viewState = state.getViewStateForView(child);
|
||||
@@ -464,6 +580,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
alpha = NotificationUtils.interpolate(0, 0.5f,
|
||||
Math.min(viewState.alpha, expandFraction));
|
||||
}
|
||||
tmpState.hidden = !dividersVisible;
|
||||
tmpState.alpha = alpha;
|
||||
state.applyViewState(divider, tmpState);
|
||||
// There is no fake shadow to be drawn on the children
|
||||
@@ -473,6 +590,9 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
state.applyViewState(mOverflowNumber, mGroupOverFlowState);
|
||||
mNeverAppliedGroupState = false;
|
||||
}
|
||||
if (mNotificationHeader != null) {
|
||||
state.applyViewState(mNotificationHeader, mHeaderViewState);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -491,6 +611,8 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
int childCount = mChildren.size();
|
||||
ViewState tmpState = new ViewState();
|
||||
float expandFraction = getGroupExpandFraction();
|
||||
final boolean dividersVisible = mUserLocked
|
||||
|| mNotificationParent.isGroupExpansionChanging();
|
||||
for (int i = childCount - 1; i >= 0; i--) {
|
||||
ExpandableNotificationRow child = mChildren.get(i);
|
||||
StackViewState viewState = state.getViewStateForView(child);
|
||||
@@ -505,6 +627,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
alpha = NotificationUtils.interpolate(0, 0.5f,
|
||||
Math.min(viewState.alpha, expandFraction));
|
||||
}
|
||||
tmpState.hidden = !dividersVisible;
|
||||
tmpState.alpha = alpha;
|
||||
stateAnimator.startViewAnimations(divider, tmpState, baseDelay, duration);
|
||||
// There is no fake shadow to be drawn on the children
|
||||
@@ -521,6 +644,9 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
stateAnimator.startViewAnimations(mOverflowNumber, mGroupOverFlowState,
|
||||
baseDelay, duration);
|
||||
}
|
||||
if (mNotificationHeader != null) {
|
||||
state.applyViewState(mNotificationHeader, mHeaderViewState);
|
||||
}
|
||||
}
|
||||
|
||||
public ExpandableNotificationRow getViewAtPosition(float y) {
|
||||
@@ -541,14 +667,45 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
public void setChildrenExpanded(boolean childrenExpanded) {
|
||||
mChildrenExpanded = childrenExpanded;
|
||||
updateExpansionStates();
|
||||
if (mNotificationHeader != null) {
|
||||
mNotificationHeader.setExpanded(childrenExpanded);
|
||||
}
|
||||
}
|
||||
|
||||
public void setNotificationParent(ExpandableNotificationRow parent) {
|
||||
mNotificationParent = parent;
|
||||
mHeaderUtil = new NotificationHeaderUtil(mNotificationParent);
|
||||
}
|
||||
|
||||
public NotificationHeaderView getHeaderView() {
|
||||
return mNotificationHeader;
|
||||
}
|
||||
|
||||
public void updateHeaderVisibility(int visiblity) {
|
||||
if (mNotificationHeader != null) {
|
||||
mNotificationHeader.setVisibility(visiblity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a groups expansion changes to adjust the background of the header view.
|
||||
*
|
||||
* @param expanded whether the group is expanded.
|
||||
*/
|
||||
public void updateHeaderForExpansion(boolean expanded) {
|
||||
if (mNotificationHeader != null) {
|
||||
if (expanded) {
|
||||
ColorDrawable cd = new ColorDrawable();
|
||||
cd.setColor(mNotificationParent.calculateBgColor());
|
||||
mNotificationHeader.setHeaderBackgroundDrawable(cd);
|
||||
} else {
|
||||
mNotificationHeader.setHeaderBackgroundDrawable(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxContentHeight() {
|
||||
int maxContentHeight = mNotificationHeaderHeight + mNotificatonTopPadding;
|
||||
int maxContentHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
|
||||
int visibleChildren = 0;
|
||||
int childCount = mChildren.size();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
@@ -601,7 +758,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
}
|
||||
|
||||
private int getVisibleChildrenExpandHeight() {
|
||||
int intrinsicHeight = mNotificationHeaderHeight + mNotificatonTopPadding + mDividerHeight;
|
||||
int intrinsicHeight = mNotificationHeaderMargin + mNotificatonTopPadding + mDividerHeight;
|
||||
int visibleChildren = 0;
|
||||
int childCount = mChildren.size();
|
||||
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
|
||||
@@ -628,7 +785,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
}
|
||||
|
||||
private int getMinHeight(int maxAllowedVisibleChildren) {
|
||||
int minExpandHeight = mNotificationHeaderHeight;
|
||||
int minExpandHeight = mNotificationHeaderMargin;
|
||||
int visibleChildren = 0;
|
||||
boolean firstChild = true;
|
||||
int childCount = mChildren.size();
|
||||
@@ -653,9 +810,13 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
if (mOverflowNumber != null) {
|
||||
mOverflowInvertHelper.setInverted(dark, fade, delay);
|
||||
}
|
||||
mNotificationHeaderWrapper.setDark(dark, fade, delay);
|
||||
}
|
||||
|
||||
public void reInflateViews() {
|
||||
public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
|
||||
removeView(mNotificationHeader);
|
||||
mNotificationHeader = null;
|
||||
recreateNotificationHeader(listener, notification);
|
||||
initDimens();
|
||||
for (int i = 0; i < mDividers.size(); i++) {
|
||||
View prevDivider = mDividers.get(i);
|
||||
|
||||
@@ -733,6 +733,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
mQsContainer = qsContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildDismissed(View v) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) v;
|
||||
if (!row.isDismissed()) {
|
||||
@@ -820,6 +821,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
return true; // Don't fade out the notification
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeginDrag(View v) {
|
||||
mFalsingManager.onNotificatonStartDismissing();
|
||||
setSwipingInProgress(true);
|
||||
@@ -848,6 +850,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragCancelled(View v) {
|
||||
mFalsingManager.onNotificatonStopDismissing();
|
||||
setSwipingInProgress(false);
|
||||
@@ -906,11 +909,13 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
return closestChild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpandableView getChildAtRawPosition(float touchX, float touchY) {
|
||||
getLocationOnScreen(mTempInt2);
|
||||
return getChildAtPosition(touchX - mTempInt2[0], touchY - mTempInt2[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpandableView getChildAtPosition(float touchX, float touchY) {
|
||||
// find the view under the pointer, accounting for GONE views
|
||||
final int count = getChildCount();
|
||||
@@ -947,12 +952,14 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChildBeExpanded(View v) {
|
||||
return v instanceof ExpandableNotificationRow
|
||||
&& ((ExpandableNotificationRow) v).isExpandable()
|
||||
&& (mIsExpanded || !((ExpandableNotificationRow) v).isPinned());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserExpandedChild(View v, boolean userExpanded) {
|
||||
if (v instanceof ExpandableNotificationRow) {
|
||||
((ExpandableNotificationRow) v).setUserExpanded(userExpanded,
|
||||
@@ -960,6 +967,14 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpansionCancelled(View v) {
|
||||
if (v instanceof ExpandableNotificationRow) {
|
||||
((ExpandableNotificationRow) v).setGroupExpansionChanging(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserLockedChild(View v, boolean userLocked) {
|
||||
if (v instanceof ExpandableNotificationRow) {
|
||||
((ExpandableNotificationRow) v).setUserLocked(userLocked);
|
||||
@@ -1070,6 +1085,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
return mScrollingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChildBeDismissed(View v) {
|
||||
return StackScrollAlgorithm.canChildBeDismissed(v);
|
||||
}
|
||||
@@ -1927,7 +1943,8 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
// we're ending up at the same location as we are now, lets just skip the animation
|
||||
bottom = finalBottom;
|
||||
} else {
|
||||
bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight());
|
||||
bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()
|
||||
- lastView.getExtraBottomPadding());
|
||||
bottom = Math.min(bottom, getHeight());
|
||||
}
|
||||
} else {
|
||||
@@ -3153,8 +3170,9 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
expandableView.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
|
||||
} else {
|
||||
float yLocation = previous.getTranslationY() + previous.getActualHeight() -
|
||||
expandableView.getTranslationY();
|
||||
expandableView.setFakeShadowIntensity(diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
|
||||
expandableView.getTranslationY() - previous.getExtraBottomPadding();
|
||||
expandableView.setFakeShadowIntensity(
|
||||
diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
|
||||
previous.getOutlineAlpha(), (int) yLocation,
|
||||
previous.getOutlineTranslation());
|
||||
}
|
||||
@@ -3525,6 +3543,12 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
if (!mGroupExpandedForMeasure) {
|
||||
onHeightChanged(changedRow, false /* needsAnimation */);
|
||||
}
|
||||
runAfterAnimationFinished(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
changedRow.onFinishedExpansionChange();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -173,6 +173,9 @@ public class StackScrollState {
|
||||
}
|
||||
if (view instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
|
||||
if (state.isBottomClipped) {
|
||||
row.setClipToActualHeight(true);
|
||||
}
|
||||
row.applyChildrenState(this);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -223,7 +223,7 @@ public class StackStateAnimator {
|
||||
startViewAnimations(child, viewState, delay, duration);
|
||||
|
||||
// start height animation
|
||||
if (heightChanging && child.getActualHeight() != 0) {
|
||||
if (heightChanging) {
|
||||
startHeightAnimation(child, viewState, duration, delay);
|
||||
}
|
||||
|
||||
@@ -270,7 +270,8 @@ public class StackStateAnimator {
|
||||
public void startViewAnimations(View child, ViewState viewState, long delay, long duration) {
|
||||
boolean wasVisible = child.getVisibility() == View.VISIBLE;
|
||||
final float alpha = viewState.alpha;
|
||||
if (!wasVisible && alpha != 0 && !viewState.gone && !viewState.hidden) {
|
||||
if (!wasVisible && (alpha != 0 || child.getAlpha() != 0)
|
||||
&& !viewState.gone && !viewState.hidden) {
|
||||
child.setVisibility(View.VISIBLE);
|
||||
}
|
||||
boolean yTranslationChanging = child.getTranslationY() != viewState.yTranslation;
|
||||
@@ -477,11 +478,27 @@ public class StackStateAnimator {
|
||||
animator.addListener(getGlobalAnimationFinishedListener());
|
||||
// remove the tag when the animation is finished
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
boolean mWasCancelled;
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
child.setTag(TAG_ANIMATOR_HEIGHT, null);
|
||||
child.setTag(TAG_START_HEIGHT, null);
|
||||
child.setTag(TAG_END_HEIGHT, null);
|
||||
if (!mWasCancelled && child instanceof ExpandableNotificationRow) {
|
||||
((ExpandableNotificationRow) child).setGroupExpansionChanging(
|
||||
false /* isExpansionChanging */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mWasCancelled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
mWasCancelled = true;
|
||||
}
|
||||
});
|
||||
startAnimator(animator);
|
||||
|
||||
@@ -57,6 +57,11 @@ public class StackViewState extends ViewState {
|
||||
*/
|
||||
public int location;
|
||||
|
||||
/**
|
||||
* Whether a child in a group is being clipped at the bottom.
|
||||
*/
|
||||
public boolean isBottomClipped;
|
||||
|
||||
@Override
|
||||
public void copyFrom(ViewState viewState) {
|
||||
super.copyFrom(viewState);
|
||||
@@ -71,6 +76,7 @@ public class StackViewState extends ViewState {
|
||||
clipTopAmount = svs.clipTopAmount;
|
||||
notGoneIndex = svs.notGoneIndex;
|
||||
location = svs.location;
|
||||
isBottomClipped = svs.isBottomClipped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user