Follow up CL for heads up notification refactoring
Change-Id: Iaf286dfd30a86d3d7d6dd947d3c10ac9eb8c2b1e
This commit is contained in:
@@ -150,7 +150,7 @@
|
||||
<integer name="heads_up_notification_minimum_time">2000</integer>
|
||||
|
||||
<!-- milliseconds before the heads up notification accepts touches. -->
|
||||
<integer name="heads_up_sensitivity_delay">700</integer>
|
||||
<integer name="touch_acceptance_delay">700</integer>
|
||||
|
||||
<!-- The duration in seconds to wait before the dismiss buttons are shown. -->
|
||||
<integer name="recents_task_bar_dismiss_delay_seconds">1</integer>
|
||||
|
||||
@@ -783,7 +783,8 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
|
||||
NotificationData.Entry entry) {
|
||||
|
||||
if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
|
||||
if (entry.getContentView().getId()
|
||||
!= com.android.internal.R.id.status_bar_latest_event_content) {
|
||||
// Using custom RemoteViews
|
||||
if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
|
||||
&& entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) {
|
||||
@@ -808,8 +809,9 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
|
||||
public boolean isMediaNotification(NotificationData.Entry entry) {
|
||||
// TODO: confirm that there's a valid media key
|
||||
return entry.expandedBig != null &&
|
||||
entry.expandedBig.findViewById(com.android.internal.R.id.media_actions) != null;
|
||||
return entry.getExpandedContentView() != null &&
|
||||
entry.getExpandedContentView()
|
||||
.findViewById(com.android.internal.R.id.media_actions) != null;
|
||||
}
|
||||
|
||||
// The gear button in the guts that links to the app's own notification settings
|
||||
@@ -1133,9 +1135,9 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
}
|
||||
|
||||
/**
|
||||
* if the interrupting notification had a fullscreen intent, fire it now.
|
||||
* If there is an active heads-up notification and it has a fullscreen intent, fire it now.
|
||||
*/
|
||||
public abstract void escalateHeadsUp();
|
||||
public abstract void maybeEscalateHeadsUp();
|
||||
|
||||
/**
|
||||
* Save the current "public" (locked and secure) state of the lockscreen.
|
||||
@@ -1336,8 +1338,8 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
View publicViewLocal = null;
|
||||
if (publicNotification != null) {
|
||||
try {
|
||||
publicViewLocal = publicNotification.contentView.apply(mContext, contentContainerPublic,
|
||||
mOnClickHandler);
|
||||
publicViewLocal = publicNotification.contentView.apply(mContext,
|
||||
contentContainerPublic, mOnClickHandler);
|
||||
|
||||
if (publicViewLocal != null) {
|
||||
publicViewLocal.setIsRootNamespace(true);
|
||||
@@ -1444,9 +1446,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
entry.row = row;
|
||||
entry.row.setHeightRange(mRowMinHeight, maxHeight);
|
||||
entry.row.setOnActivatedListener(this);
|
||||
entry.expanded = contentViewLocal;
|
||||
entry.expandedPublic = publicViewLocal;
|
||||
entry.setBigContentView(bigContentViewLocal);
|
||||
entry.row.setExpandable(bigContentViewLocal != null);
|
||||
|
||||
applyColorsAndBackgrounds(sbn, entry);
|
||||
|
||||
@@ -1535,12 +1535,13 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
|
||||
// See if we have somewhere to put that remote input
|
||||
if (remoteInput != null) {
|
||||
if (entry.expandedBig != null) {
|
||||
inflateRemoteInput(entry.expandedBig, remoteInput, actions);
|
||||
View bigContentView = entry.getExpandedContentView();
|
||||
if (bigContentView != null) {
|
||||
inflateRemoteInput(bigContentView, remoteInput, actions);
|
||||
}
|
||||
View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild();
|
||||
if (headsUpChild != null) {
|
||||
inflateRemoteInput(headsUpChild, remoteInput, actions);
|
||||
View headsUpContentView = entry.getHeadsUpContentView();
|
||||
if (headsUpContentView != null) {
|
||||
inflateRemoteInput(headsUpContentView, remoteInput, actions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1882,15 +1883,14 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
logUpdate(entry, n);
|
||||
}
|
||||
boolean applyInPlace = shouldApplyInPlace(entry, n);
|
||||
final boolean shouldInterrupt = shouldInterrupt(notification);
|
||||
final boolean alertAgain = alertAgain(entry, n);
|
||||
boolean shouldInterrupt = shouldInterrupt(notification);
|
||||
boolean alertAgain = alertAgain(entry, n);
|
||||
|
||||
entry.notification = notification;
|
||||
mGroupManager.onEntryUpdated(entry, entry.notification);
|
||||
|
||||
boolean updateSuccessful = false;
|
||||
if (applyInPlace) {
|
||||
// We can just reapply the notifications in place
|
||||
if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
|
||||
try {
|
||||
if (entry.icon != null) {
|
||||
@@ -1911,7 +1911,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
updateSuccessful = true;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
// It failed to add cleanly. Log, and remove the view from the panel.
|
||||
// It failed to apply cleanly.
|
||||
Log.w(TAG, "Couldn't reapply views for package " + n.contentView.getPackage(), e);
|
||||
}
|
||||
}
|
||||
@@ -1935,11 +1935,12 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
// swipe-dismissable)
|
||||
updateNotificationVetoButton(entry.row, notification);
|
||||
|
||||
// Is this for you?
|
||||
boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
|
||||
if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
|
||||
if (DEBUG) {
|
||||
// Is this for you?
|
||||
boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
|
||||
Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
|
||||
}
|
||||
|
||||
// Recalculate the position of the sliding windows and the titles.
|
||||
setAreThereNotifications();
|
||||
}
|
||||
|
||||
@@ -1950,7 +1951,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
StatusBarNotification oldNotification = oldEntry.notification;
|
||||
Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when
|
||||
+ " ongoing=" + oldNotification.isOngoing()
|
||||
+ " expanded=" + oldEntry.expanded
|
||||
+ " expanded=" + oldEntry.getContentView()
|
||||
+ " contentView=" + oldNotification.getNotification().contentView
|
||||
+ " bigContentView=" + oldNotification.getNotification().bigContentView
|
||||
+ " publicView=" + oldNotification.getNotification().publicVersion
|
||||
@@ -1963,7 +1964,8 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether we can just reapply the RemoteViews in place when it is updated
|
||||
* @return whether we can just reapply the RemoteViews from a notification in-place when it is
|
||||
* updated
|
||||
*/
|
||||
private boolean shouldApplyInPlace(Entry entry, Notification n) {
|
||||
StatusBarNotification oldNotification = entry.notification;
|
||||
@@ -1981,15 +1983,15 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
final Notification publicNotification = n.publicVersion;
|
||||
final RemoteViews publicContentView = publicNotification != null
|
||||
? publicNotification.contentView : null;
|
||||
boolean contentsUnchanged = entry.expanded != null
|
||||
boolean contentsUnchanged = entry.getContentView() != null
|
||||
&& contentView.getPackage() != null
|
||||
&& oldContentView.getPackage() != null
|
||||
&& oldContentView.getPackage().equals(contentView.getPackage())
|
||||
&& oldContentView.getLayoutId() == contentView.getLayoutId();
|
||||
// large view may be null
|
||||
boolean bigContentsUnchanged =
|
||||
(entry.getBigContentView() == null && bigContentView == null)
|
||||
|| ((entry.getBigContentView() != null && bigContentView != null)
|
||||
(entry.getExpandedContentView() == null && bigContentView == null)
|
||||
|| ((entry.getExpandedContentView() != null && bigContentView != null)
|
||||
&& bigContentView.getPackage() != null
|
||||
&& oldBigContentView.getPackage() != null
|
||||
&& oldBigContentView.getPackage().equals(bigContentView.getPackage())
|
||||
@@ -2021,12 +2023,12 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
: null;
|
||||
|
||||
// Reapply the RemoteViews
|
||||
contentView.reapply(mContext, entry.expanded, mOnClickHandler);
|
||||
if (bigContentView != null && entry.getBigContentView() != null) {
|
||||
bigContentView.reapply(mContext, entry.getBigContentView(),
|
||||
contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
|
||||
if (bigContentView != null && entry.getExpandedContentView() != null) {
|
||||
bigContentView.reapply(mContext, entry.getExpandedContentView(),
|
||||
mOnClickHandler);
|
||||
}
|
||||
View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild();
|
||||
View headsUpChild = entry.getHeadsUpContentView();
|
||||
if (headsUpContentView != null && headsUpChild != null) {
|
||||
headsUpContentView.reapply(mContext, headsUpChild, mOnClickHandler);
|
||||
}
|
||||
@@ -2049,7 +2051,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
}
|
||||
|
||||
protected void notifyHeadsUpScreenOff() {
|
||||
escalateHeadsUp();
|
||||
maybeEscalateHeadsUp();
|
||||
}
|
||||
|
||||
private boolean alertAgain(Entry oldEntry, Notification newNotification) {
|
||||
|
||||
@@ -84,7 +84,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
private ExpansionLogger mLogger;
|
||||
private String mLoggingKey;
|
||||
private boolean mWasReset;
|
||||
|
||||
private NotificationGuts mGuts;
|
||||
private StatusBarNotification mStatusBarNotification;
|
||||
private boolean mIsHeadsUp;
|
||||
@@ -102,6 +101,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
private ViewStub mGutsStub;
|
||||
private boolean mHasExpandAction;
|
||||
private boolean mIsSystemChildExpanded;
|
||||
private boolean mIsPinned;
|
||||
private OnClickListener mExpandClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -109,7 +109,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
!mChildrenExpanded);
|
||||
}
|
||||
};
|
||||
private boolean mInShade;
|
||||
|
||||
public NotificationContentView getPrivateLayout() {
|
||||
return mPrivateLayout;
|
||||
@@ -284,12 +283,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
return realActualHeight;
|
||||
}
|
||||
|
||||
public void setInShade(boolean inShade) {
|
||||
mInShade = inShade;
|
||||
/**
|
||||
* Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
|
||||
* the notification will be rendered on top of the screen.
|
||||
*
|
||||
* @param pinned whether it is pinned
|
||||
*/
|
||||
public void setPinned(boolean pinned) {
|
||||
mIsPinned = pinned;
|
||||
}
|
||||
|
||||
public boolean isInShade() {
|
||||
return mInShade;
|
||||
public boolean isPinned() {
|
||||
return mIsPinned;
|
||||
}
|
||||
|
||||
public int getHeadsUpHeight() {
|
||||
|
||||
@@ -32,37 +32,34 @@ import android.widget.FrameLayout;
|
||||
import com.android.systemui.R;
|
||||
|
||||
/**
|
||||
* A frame layout containing the actual payload of the notification, including the contracted and
|
||||
* expanded layout. This class is responsible for clipping the content and and switching between the
|
||||
* expanded and contracted view depending on its clipped size.
|
||||
* A frame layout containing the actual payload of the notification, including the contracted,
|
||||
* expanded and heads up layout. This class is responsible for clipping the content and and
|
||||
* switching between the expanded, contracted and the heads up view depending on its clipped size.
|
||||
*/
|
||||
public class NotificationContentView extends FrameLayout {
|
||||
|
||||
private static final long ANIMATION_DURATION_LENGTH = 170;
|
||||
private static final int CONTRACTED = 1;
|
||||
private static final int EXPANDED = 2;
|
||||
private static final int HEADSUP = 3;
|
||||
private static final int VISIBLE_TYPE_CONTRACTED = 0;
|
||||
private static final int VISIBLE_TYPE_EXPANDED = 1;
|
||||
private static final int VISIBLE_TYPE_HEADSUP = 2;
|
||||
|
||||
private final Rect mClipBounds = new Rect();
|
||||
private final int mSmallHeight;
|
||||
private final int mHeadsUpHeight;
|
||||
private final Interpolator mLinearInterpolator = new LinearInterpolator();
|
||||
|
||||
private View mContractedChild;
|
||||
private View mExpandedChild;
|
||||
private View mHeadsUpChild;
|
||||
|
||||
private NotificationViewWrapper mContractedWrapper;
|
||||
|
||||
private final int mSmallHeight;
|
||||
private final int mHeadsUpHeight;
|
||||
private int mClipTopAmount;
|
||||
|
||||
private int mContentHeight;
|
||||
|
||||
private final Interpolator mLinearInterpolator = new LinearInterpolator();
|
||||
private int mVisibleView = CONTRACTED;
|
||||
|
||||
private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
|
||||
private boolean mDark;
|
||||
private final Paint mFadePaint = new Paint();
|
||||
private boolean mAnimate;
|
||||
private boolean mIsHeadsUp;
|
||||
private ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
|
||||
= new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
@@ -72,7 +69,6 @@ public class NotificationContentView extends FrameLayout {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
private boolean mIsHeadsUp;
|
||||
|
||||
public NotificationContentView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -105,9 +101,9 @@ public class NotificationContentView extends FrameLayout {
|
||||
// An actual height is set
|
||||
size = Math.min(maxSize, layoutParams.height);
|
||||
}
|
||||
int spec = size == Integer.MAX_VALUE ?
|
||||
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) :
|
||||
MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
|
||||
int spec = size == Integer.MAX_VALUE
|
||||
? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
|
||||
: MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
|
||||
mExpandedChild.measure(widthMeasureSpec, spec);
|
||||
maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
|
||||
}
|
||||
@@ -153,7 +149,7 @@ public class NotificationContentView extends FrameLayout {
|
||||
mContractedChild = null;
|
||||
mExpandedChild = null;
|
||||
mHeadsUpChild = null;
|
||||
mVisibleView = CONTRACTED;
|
||||
mVisibleType = VISIBLE_TYPE_CONTRACTED;
|
||||
if (resetActualHeight) {
|
||||
mContentHeight = mSmallHeight;
|
||||
}
|
||||
@@ -263,30 +259,32 @@ public class NotificationContentView extends FrameLayout {
|
||||
if (mContractedChild == null) {
|
||||
return;
|
||||
}
|
||||
int visibleView = calculateVisibleView();
|
||||
if (visibleView != mVisibleView || force) {
|
||||
if (animate && mExpandedChild != null) {
|
||||
runSwitchAnimation(visibleView);
|
||||
int visibleType = calculateVisibleType();
|
||||
if (visibleType != mVisibleType || force) {
|
||||
if (animate && (visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
|
||||
|| (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
|
||||
|| visibleType == VISIBLE_TYPE_CONTRACTED) {
|
||||
runSwitchAnimation(visibleType);
|
||||
} else {
|
||||
updateViewVisibilities(visibleView);
|
||||
updateViewVisibilities(visibleType);
|
||||
}
|
||||
mVisibleView = visibleView;
|
||||
mVisibleType = visibleType;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateViewVisibilities(int visibleView) {
|
||||
boolean contractedVisible = visibleView == CONTRACTED;
|
||||
private void updateViewVisibilities(int visibleType) {
|
||||
boolean contractedVisible = visibleType == VISIBLE_TYPE_CONTRACTED;
|
||||
mContractedChild.setVisibility(contractedVisible ? View.VISIBLE : View.INVISIBLE);
|
||||
mContractedChild.setAlpha(contractedVisible ? 1f : 0f);
|
||||
mContractedChild.setLayerType(LAYER_TYPE_NONE, null);
|
||||
if (mExpandedChild != null) {
|
||||
boolean expandedVisible = visibleView == EXPANDED;
|
||||
boolean expandedVisible = visibleType == VISIBLE_TYPE_EXPANDED;
|
||||
mExpandedChild.setVisibility(expandedVisible ? View.VISIBLE : View.INVISIBLE);
|
||||
mExpandedChild.setAlpha(expandedVisible ? 1f : 0f);
|
||||
mExpandedChild.setLayerType(LAYER_TYPE_NONE, null);
|
||||
}
|
||||
if (mHeadsUpChild != null) {
|
||||
boolean headsUpVisible = visibleView == HEADSUP;
|
||||
boolean headsUpVisible = visibleType == VISIBLE_TYPE_HEADSUP;
|
||||
mHeadsUpChild.setVisibility(headsUpVisible ? View.VISIBLE : View.INVISIBLE);
|
||||
mHeadsUpChild.setAlpha(headsUpVisible ? 1f : 0f);
|
||||
mHeadsUpChild.setLayerType(LAYER_TYPE_NONE, null);
|
||||
@@ -294,9 +292,9 @@ public class NotificationContentView extends FrameLayout {
|
||||
setLayerType(LAYER_TYPE_NONE, null);
|
||||
}
|
||||
|
||||
private void runSwitchAnimation(int visibleView) {
|
||||
View shownView = getViewFromFlag(visibleView);
|
||||
View hiddenView = getViewFromFlag(mVisibleView);
|
||||
private void runSwitchAnimation(int visibleType) {
|
||||
View shownView = getViewForVisibleType(visibleType);
|
||||
View hiddenView = getViewForVisibleType(mVisibleType);
|
||||
shownView.setVisibility(View.VISIBLE);
|
||||
hiddenView.setVisibility(View.VISIBLE);
|
||||
shownView.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
|
||||
@@ -314,34 +312,42 @@ public class NotificationContentView extends FrameLayout {
|
||||
.withEndAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateViewVisibilities(mVisibleView);
|
||||
updateViewVisibilities(mVisibleType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private View getViewFromFlag(int visibleView) {
|
||||
switch (visibleView) {
|
||||
case EXPANDED:
|
||||
/**
|
||||
* @param visibleType one of the static enum types in this view
|
||||
* @return the corresponding view according to the given visible type
|
||||
*/
|
||||
private View getViewForVisibleType(int visibleType) {
|
||||
switch (visibleType) {
|
||||
case VISIBLE_TYPE_EXPANDED:
|
||||
return mExpandedChild;
|
||||
case HEADSUP:
|
||||
case VISIBLE_TYPE_HEADSUP:
|
||||
return mHeadsUpChild;
|
||||
default:
|
||||
return mContractedChild;
|
||||
}
|
||||
return mContractedChild;
|
||||
}
|
||||
|
||||
private int calculateVisibleView() {
|
||||
/**
|
||||
* @return one of the static enum types in this view, calculated form the current state
|
||||
*/
|
||||
private int calculateVisibleType() {
|
||||
boolean noExpandedChild = mExpandedChild == null;
|
||||
if (mIsHeadsUp && mHeadsUpChild != null) {
|
||||
if (mContentHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
|
||||
return HEADSUP;
|
||||
return VISIBLE_TYPE_HEADSUP;
|
||||
} else {
|
||||
return EXPANDED;
|
||||
return VISIBLE_TYPE_EXPANDED;
|
||||
}
|
||||
} else {
|
||||
if (mContentHeight <= mSmallHeight || noExpandedChild) {
|
||||
return CONTRACTED;
|
||||
return VISIBLE_TYPE_CONTRACTED;
|
||||
} else {
|
||||
return EXPANDED;
|
||||
return VISIBLE_TYPE_EXPANDED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,6 @@ public class NotificationData {
|
||||
public StatusBarNotification notification;
|
||||
public StatusBarIconView icon;
|
||||
public ExpandableNotificationRow row; // the outer expanded view
|
||||
public View expanded; // the inflated RemoteViews
|
||||
public View expandedPublic; // for insecure lockscreens
|
||||
public View expandedBig;
|
||||
private boolean interruption;
|
||||
public boolean autoRedacted; // whether the redacted notification was generated by us
|
||||
public boolean legacy; // whether the notification has a legacy, dark background
|
||||
@@ -58,14 +55,6 @@ public class NotificationData {
|
||||
this.notification = n;
|
||||
this.icon = ic;
|
||||
}
|
||||
public void setBigContentView(View bigContentView) {
|
||||
this.expandedBig = bigContentView;
|
||||
row.setExpandable(bigContentView != null);
|
||||
}
|
||||
public View getBigContentView() {
|
||||
return expandedBig;
|
||||
}
|
||||
public View getPublicContentView() { return expandedPublic; }
|
||||
|
||||
public void setInterruption() {
|
||||
interruption = true;
|
||||
@@ -81,15 +70,28 @@ public class NotificationData {
|
||||
public void reset() {
|
||||
// NOTE: Icon needs to be preserved for now.
|
||||
// We should fix this at some point.
|
||||
expanded = null;
|
||||
expandedPublic = null;
|
||||
expandedBig = null;
|
||||
autoRedacted = false;
|
||||
legacy = false;
|
||||
if (row != null) {
|
||||
row.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public View getContentView() {
|
||||
return row.getPrivateLayout().getContractedChild();
|
||||
}
|
||||
|
||||
public View getExpandedContentView() {
|
||||
return row.getPrivateLayout().getExpandedChild();
|
||||
}
|
||||
|
||||
public View getHeadsUpContentView() {
|
||||
return row.getPrivateLayout().getHeadsUpChild();
|
||||
}
|
||||
|
||||
public View getPublicContentView() {
|
||||
return row.getPublicLayout().getContractedChild();
|
||||
}
|
||||
}
|
||||
|
||||
private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
|
||||
@@ -258,7 +260,7 @@ public class NotificationData {
|
||||
*/
|
||||
public boolean hasActiveClearableNotifications() {
|
||||
for (Entry e : mSortedAndFiltered) {
|
||||
if (e.expanded != null) { // the view successfully inflated
|
||||
if (e.getContentView() != null) { // the view successfully inflated
|
||||
if (e.notification.isClearable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
|
||||
|
||||
/**
|
||||
* A Helper class to handle touches on the heads-up views
|
||||
* A helper class to handle touches on the heads-up views.
|
||||
*/
|
||||
public class HeadsUpTouchHelper implements Gefingerpoken {
|
||||
|
||||
@@ -37,19 +37,30 @@ public class HeadsUpTouchHelper implements Gefingerpoken {
|
||||
private float mTouchSlop;
|
||||
private float mInitialTouchX;
|
||||
private float mInitialTouchY;
|
||||
private boolean mMotionOnHeadsUpView;
|
||||
private boolean mTouchingHeadsUpView;
|
||||
private boolean mTrackingHeadsUp;
|
||||
private boolean mCollapseSnoozes;
|
||||
private NotificationPanelView mPanel;
|
||||
private ExpandableNotificationRow mPickedChild;
|
||||
|
||||
public HeadsUpTouchHelper(HeadsUpManager headsUpManager,
|
||||
NotificationStackScrollLayout stackScroller,
|
||||
NotificationPanelView notificationPanelView) {
|
||||
mHeadsUpManager = headsUpManager;
|
||||
mStackScroller = stackScroller;
|
||||
mPanel = notificationPanelView;
|
||||
Context context = stackScroller.getContext();
|
||||
final ViewConfiguration configuration = ViewConfiguration.get(context);
|
||||
mTouchSlop = configuration.getScaledTouchSlop();
|
||||
}
|
||||
|
||||
public boolean isTrackingHeadsUp() {
|
||||
return mTrackingHeadsUp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||
if (!mMotionOnHeadsUpView && event.getActionMasked() != MotionEvent.ACTION_DOWN) {
|
||||
if (!mTouchingHeadsUpView && event.getActionMasked() != MotionEvent.ACTION_DOWN) {
|
||||
return false;
|
||||
}
|
||||
int pointerIndex = event.findPointerIndex(mTrackingPointer);
|
||||
@@ -65,10 +76,10 @@ public class HeadsUpTouchHelper implements Gefingerpoken {
|
||||
mInitialTouchX = x;
|
||||
setTrackingHeadsUp(false);
|
||||
ExpandableView child = mStackScroller.getChildAtPosition(x, y);
|
||||
mMotionOnHeadsUpView = false;
|
||||
mTouchingHeadsUpView = false;
|
||||
if (child instanceof ExpandableNotificationRow) {
|
||||
mPickedChild = (ExpandableNotificationRow) child;
|
||||
mMotionOnHeadsUpView = mPickedChild.isHeadsUp() && !mPickedChild.isInShade();
|
||||
mTouchingHeadsUpView = mPickedChild.isHeadsUp() && mPickedChild.isPinned();
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
@@ -97,7 +108,8 @@ public class HeadsUpTouchHelper implements Gefingerpoken {
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (mPickedChild != null && mMotionOnHeadsUpView) {
|
||||
if (mPickedChild != null && mTouchingHeadsUpView) {
|
||||
// We may swallow this click if the heads up just came in.
|
||||
if (mHeadsUpManager.shouldSwallowClick(
|
||||
mPickedChild.getStatusBarNotification().getKey())) {
|
||||
endMotion();
|
||||
@@ -141,20 +153,6 @@ public class HeadsUpTouchHelper implements Gefingerpoken {
|
||||
private void endMotion() {
|
||||
mTrackingPointer = -1;
|
||||
mPickedChild = null;
|
||||
mMotionOnHeadsUpView = false;
|
||||
}
|
||||
|
||||
public ExpandableView getPickedChild() {
|
||||
return mPickedChild;
|
||||
}
|
||||
|
||||
public void bind(HeadsUpManager headsUpManager, NotificationStackScrollLayout stackScroller,
|
||||
NotificationPanelView notificationPanelView) {
|
||||
mHeadsUpManager = headsUpManager;
|
||||
mStackScroller = stackScroller;
|
||||
mPanel = notificationPanelView;
|
||||
Context context = stackScroller.getContext();
|
||||
final ViewConfiguration configuration = ViewConfiguration.get(context);
|
||||
mTouchSlop = configuration.getScaledTouchSlop();
|
||||
mTouchingHeadsUpView = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,11 +182,11 @@ public class NotificationPanelView extends PanelView implements
|
||||
|
||||
private float mKeyguardStatusBarAnimateAlpha = 1f;
|
||||
private int mOldLayoutDirection;
|
||||
private HeadsUpTouchHelper mHeadsUpTouchHelper = new HeadsUpTouchHelper();
|
||||
private boolean mPinnedHeadsUpExist;
|
||||
private boolean mExpansionIsFromHeadsUp;
|
||||
private int mBottomBarHeight;
|
||||
private HeadsUpTouchHelper mHeadsUpTouchHelper;
|
||||
private boolean mIsExpansionFromHeadsUp;
|
||||
private int mNavigationBarBottomHeight;
|
||||
private boolean mExpandingFromHeadsUp;
|
||||
private boolean mCollapsedOnDown;
|
||||
private int mPositionMinSideMargin;
|
||||
private int mLastOrientation = -1;
|
||||
|
||||
@@ -534,17 +534,16 @@ public class NotificationPanelView extends PanelView implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
onInterceptTouchEvent(MotionEvent event) {
|
||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||
if (mBlockTouches) {
|
||||
return false;
|
||||
}
|
||||
initDownStates(event);
|
||||
if (mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
|
||||
mExpansionIsFromHeadsUp = true;
|
||||
mIsExpansionFromHeadsUp = true;
|
||||
return true;
|
||||
}
|
||||
if (!isShadeCollapsed() && onQsIntercept(event)) {
|
||||
if (!isFullyCollapsed() && onQsIntercept(event)) {
|
||||
return true;
|
||||
}
|
||||
return super.onInterceptTouchEvent(event);
|
||||
@@ -641,6 +640,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
mOnlyAffordanceInThisMotion = false;
|
||||
mQsTouchAboveFalsingThreshold = mQsFullyExpanded;
|
||||
mDozingOnDown = isDozing();
|
||||
mCollapsedOnDown = isFullyCollapsed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,7 +695,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
return true;
|
||||
}
|
||||
mHeadsUpTouchHelper.onTouchEvent(event);
|
||||
if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQSTouch(event)) {
|
||||
if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) {
|
||||
return true;
|
||||
}
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
|
||||
@@ -705,7 +705,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleQSTouch(MotionEvent event) {
|
||||
private boolean handleQsTouch(MotionEvent event) {
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
|
||||
&& mStatusBar.getBarState() != StatusBarState.KEYGUARD && !mQsExpanded
|
||||
&& mQsExpansionEnabled) {
|
||||
@@ -718,7 +718,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
mInitialTouchY = event.getX();
|
||||
mInitialTouchX = event.getY();
|
||||
}
|
||||
if (!isShadeCollapsed()) {
|
||||
if (!isFullyCollapsed()) {
|
||||
handleQsDown(event);
|
||||
}
|
||||
if (!mQsExpandImmediate && mQsTracking) {
|
||||
@@ -731,7 +731,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
|| event.getActionMasked() == MotionEvent.ACTION_UP) {
|
||||
mConflictingQsExpansionGesture = false;
|
||||
}
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isShadeCollapsed()
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()
|
||||
&& mQsExpansionEnabled) {
|
||||
mTwoFingerQsExpandPossible = true;
|
||||
}
|
||||
@@ -1191,8 +1191,8 @@ public class NotificationPanelView extends PanelView implements
|
||||
updateEmptyShadeView();
|
||||
mQsNavbarScrim.setVisibility(mStatusBarState == StatusBarState.SHADE && mQsExpanded
|
||||
&& !mStackScrollerOverscrolling && mQsScrimEnabled
|
||||
? View.VISIBLE
|
||||
: View.INVISIBLE);
|
||||
? View.VISIBLE
|
||||
: View.INVISIBLE);
|
||||
if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
|
||||
mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
|
||||
}
|
||||
@@ -1386,7 +1386,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
* @return Whether we should intercept a gesture to open Quick Settings.
|
||||
*/
|
||||
private boolean shouldQuickSettingsIntercept(float x, float y, float yDiff) {
|
||||
if (!mQsExpansionEnabled) {
|
||||
if (!mQsExpansionEnabled || mCollapsedOnDown) {
|
||||
return false;
|
||||
}
|
||||
View header = mKeyguardShowing ? mKeyguardStatusBar : mHeader;
|
||||
@@ -1461,8 +1461,8 @@ public class NotificationPanelView extends PanelView implements
|
||||
updateHeader();
|
||||
updateUnlockIcon();
|
||||
updateNotificationTranslucency();
|
||||
mHeadsUpManager.setIsExpanded(!isShadeCollapsed());
|
||||
mNotificationStackScroller.setShadeExpanded(!isShadeCollapsed());
|
||||
mHeadsUpManager.setIsExpanded(!isFullyCollapsed());
|
||||
mNotificationStackScroller.setShadeExpanded(!isFullyCollapsed());
|
||||
if (DEBUG) {
|
||||
invalidate();
|
||||
}
|
||||
@@ -1535,21 +1535,19 @@ public class NotificationPanelView extends PanelView implements
|
||||
float alpha;
|
||||
if (mExpandingFromHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) {
|
||||
alpha = 1f;
|
||||
if (mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) {
|
||||
mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null);
|
||||
}
|
||||
} else {
|
||||
alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight())
|
||||
/ (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
|
||||
- mNotificationStackScroller.getCollapseSecondCardPadding());
|
||||
alpha = Math.max(0, Math.min(alpha, 1));
|
||||
alpha = (float) Math.pow(alpha, 0.75);
|
||||
if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) {
|
||||
mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
} else if (alpha == 1f
|
||||
&& mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) {
|
||||
mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) {
|
||||
mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
} else if (alpha == 1f
|
||||
&& mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) {
|
||||
mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null);
|
||||
}
|
||||
mNotificationStackScroller.setAlpha(alpha);
|
||||
}
|
||||
@@ -1615,7 +1613,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
}
|
||||
float stackTranslation = mNotificationStackScroller.getStackTranslation();
|
||||
float translation = stackTranslation / HEADER_RUBBERBAND_FACTOR;
|
||||
if (mHeadsUpManager.hasPinnedHeadsUp() || mExpansionIsFromHeadsUp) {
|
||||
if (mHeadsUpManager.hasPinnedHeadsUp() || mIsExpansionFromHeadsUp) {
|
||||
translation = mNotificationStackScroller.getTopPadding() + stackTranslation
|
||||
- mNotificationTopPadding - mQsMinExpansionHeight;
|
||||
}
|
||||
@@ -1683,16 +1681,16 @@ public class NotificationPanelView extends PanelView implements
|
||||
mHeadsUpManager.onExpandingFinished();
|
||||
mIsExpanding = false;
|
||||
mScrollYOverride = -1;
|
||||
if (isShadeCollapsed()) {
|
||||
if (isFullyCollapsed()) {
|
||||
setListening(false);
|
||||
} else {
|
||||
setListening(true);
|
||||
}
|
||||
mQsExpandImmediate = false;
|
||||
mTwoFingerQsExpandPossible = false;
|
||||
mExpansionIsFromHeadsUp = false;
|
||||
mNotificationStackScroller.setTrackingHeadsUp(mHeadsUpTouchHelper.isTrackingHeadsUp());
|
||||
mExpandingFromHeadsUp = mHeadsUpTouchHelper.isTrackingHeadsUp();
|
||||
mIsExpansionFromHeadsUp = false;
|
||||
mNotificationStackScroller.setTrackingHeadsUp(false);
|
||||
mExpandingFromHeadsUp = false;
|
||||
}
|
||||
|
||||
private void setListening(boolean listening) {
|
||||
@@ -1793,13 +1791,13 @@ public class NotificationPanelView extends PanelView implements
|
||||
|
||||
@Override
|
||||
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
|
||||
mBottomBarHeight = insets.getSystemWindowInsetBottom();
|
||||
mNavigationBarBottomHeight = insets.getSystemWindowInsetBottom();
|
||||
updateMaxHeadsUpTranslation();
|
||||
return insets;
|
||||
}
|
||||
|
||||
private void updateMaxHeadsUpTranslation() {
|
||||
mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mBottomBarHeight);
|
||||
mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mNavigationBarBottomHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2160,48 +2158,43 @@ public class NotificationPanelView extends PanelView implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnPinnedHeadsUpExistChanged(final boolean exist, boolean changeImmediatly) {
|
||||
if (exist != mPinnedHeadsUpExist) {
|
||||
mPinnedHeadsUpExist = exist;
|
||||
if (exist) {
|
||||
mHeadsUpExistenceChangedRunnable.run();
|
||||
updateNotificationTranslucency();
|
||||
} else {
|
||||
mNotificationStackScroller.performOnAnimationFinished(
|
||||
mHeadsUpExistenceChangedRunnable);
|
||||
}
|
||||
public void onPinnedModeChanged(final boolean inPinnedMode) {
|
||||
if (inPinnedMode) {
|
||||
mHeadsUpExistenceChangedRunnable.run();
|
||||
updateNotificationTranslucency();
|
||||
} else {
|
||||
mNotificationStackScroller.runAfterAnimationFinished(
|
||||
mHeadsUpExistenceChangedRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) {
|
||||
if (isHeadsUp) {
|
||||
mNotificationStackScroller.generateHeadsUpAnimation(headsUp, true);
|
||||
}
|
||||
public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
|
||||
mNotificationStackScroller.generateHeadsUpAnimation(headsUp, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
|
||||
public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
|
||||
mNotificationStackScroller.generateHeadsUpAnimation(entry.row, isHeadsUp);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShadeCollapsed() {
|
||||
return mExpandedHeight == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeadsUpManager(HeadsUpManager headsUpManager) {
|
||||
super.setHeadsUpManager(headsUpManager);
|
||||
mHeadsUpTouchHelper.bind(headsUpManager, mNotificationStackScroller, this);
|
||||
mHeadsUpTouchHelper = new HeadsUpTouchHelper(headsUpManager, mNotificationStackScroller,
|
||||
this);
|
||||
}
|
||||
|
||||
public void setTrackingHeadsUp(boolean tracking) {
|
||||
if (tracking) {
|
||||
// otherwise we update the state when the expansion is finished
|
||||
mNotificationStackScroller.setTrackingHeadsUp(true);
|
||||
mExpandingFromHeadsUp = true;
|
||||
}
|
||||
// otherwise we update the state when the expansion is finished
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -46,13 +46,13 @@ import java.io.PrintWriter;
|
||||
public abstract class PanelView extends FrameLayout {
|
||||
public static final boolean DEBUG = PanelBar.DEBUG;
|
||||
public static final String TAG = PanelView.class.getSimpleName();
|
||||
protected HeadsUpManager mHeadsUpManager;
|
||||
|
||||
private final void logf(String fmt, Object... args) {
|
||||
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
|
||||
}
|
||||
|
||||
protected PhoneStatusBar mStatusBar;
|
||||
protected HeadsUpManager mHeadsUpManager;
|
||||
|
||||
private float mPeekHeight;
|
||||
private float mHintDistance;
|
||||
private int mEdgeTapAreaWidth;
|
||||
@@ -242,15 +242,15 @@ public abstract class PanelView extends FrameLayout {
|
||||
final float y = event.getY(pointerIndex);
|
||||
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
mGestureWaitForTouchSlop = isShadeCollapsed() || hasConflictingGestures();
|
||||
mIgnoreXTouchSlop = isShadeCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
|
||||
mGestureWaitForTouchSlop = isFullyCollapsed() || hasConflictingGestures();
|
||||
mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
|
||||
}
|
||||
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
|
||||
mJustPeeked = false;
|
||||
mPanelClosedOnDown = isShadeCollapsed();
|
||||
mPanelClosedOnDown = isFullyCollapsed();
|
||||
mHasLayoutedSinceDown = false;
|
||||
mUpdateFlingOnLayout = false;
|
||||
mMotionAborted = false;
|
||||
@@ -268,7 +268,7 @@ public abstract class PanelView extends FrameLayout {
|
||||
|| mPeekPending || mPeekAnimator != null;
|
||||
onTrackingStarted();
|
||||
}
|
||||
if (isShadeCollapsed()) {
|
||||
if (isFullyCollapsed()) {
|
||||
schedulePeek();
|
||||
}
|
||||
break;
|
||||
@@ -472,7 +472,7 @@ public abstract class PanelView extends FrameLayout {
|
||||
mTouchSlopExceeded = false;
|
||||
mJustPeeked = false;
|
||||
mMotionAborted = false;
|
||||
mPanelClosedOnDown = isShadeCollapsed();
|
||||
mPanelClosedOnDown = isFullyCollapsed();
|
||||
mHasLayoutedSinceDown = false;
|
||||
mUpdateFlingOnLayout = false;
|
||||
mTouchAboveFalsingThreshold = false;
|
||||
@@ -707,7 +707,7 @@ public abstract class PanelView extends FrameLayout {
|
||||
// If the user isn't actively poking us, let's update the height
|
||||
if ((!mTracking || isTrackingBlocked())
|
||||
&& mHeightAnimator == null
|
||||
&& !isShadeCollapsed()
|
||||
&& !isFullyCollapsed()
|
||||
&& currentMaxPanelHeight != mExpandedHeight
|
||||
&& !mPeekPending
|
||||
&& mPeekAnimator == null
|
||||
@@ -1057,8 +1057,6 @@ public abstract class PanelView extends FrameLayout {
|
||||
*/
|
||||
protected abstract int getClearAllHeight();
|
||||
|
||||
protected abstract boolean isShadeCollapsed();
|
||||
|
||||
public void setHeadsUpManager(HeadsUpManager headsUpManager) {
|
||||
mHeadsUpManager = headsUpManager;
|
||||
}
|
||||
|
||||
@@ -1152,11 +1152,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
|
||||
@Override
|
||||
public void removeNotification(String key, RankingMap ranking) {
|
||||
boolean defferRemoval = false;
|
||||
boolean deferRemoval = false;
|
||||
if (mHeadsUpManager.isHeadsUp(key)) {
|
||||
defferRemoval = !mHeadsUpManager.removeNotification(key);
|
||||
deferRemoval = !mHeadsUpManager.removeNotification(key);
|
||||
}
|
||||
if (defferRemoval) {
|
||||
if (deferRemoval) {
|
||||
mLatestRankingMap = ranking;
|
||||
mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key));
|
||||
return;
|
||||
@@ -1838,8 +1838,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly) {
|
||||
if (exist) {
|
||||
public void onPinnedModeChanged(boolean inPinnedMode) {
|
||||
if (inPinnedMode) {
|
||||
mStatusBarWindowManager.setHeadsUpShowing(true);
|
||||
} else {
|
||||
Runnable endRunnable = new Runnable() {
|
||||
@@ -1850,20 +1850,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
}
|
||||
}
|
||||
};
|
||||
if (changeImmediatly) {
|
||||
if (!mNotificationPanel.isFullyCollapsed()) {
|
||||
endRunnable.run();
|
||||
} else {
|
||||
mStackScroller.performOnAnimationFinished(endRunnable);
|
||||
mStackScroller.runAfterAnimationFinished(endRunnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) {
|
||||
public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnHeadsUpStateChanged(Entry entry, boolean isHeadsUp) {
|
||||
public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) {
|
||||
if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) {
|
||||
removeNotification(entry.key, mLatestRankingMap);
|
||||
mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
|
||||
@@ -1880,10 +1884,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
boolean alertAgain) {
|
||||
final boolean wasHeadsUp = isHeadsUp(key);
|
||||
if (wasHeadsUp) {
|
||||
mHeadsUpManager.updateNotification(entry, alertAgain);
|
||||
if (!shouldInterrupt) {
|
||||
// We don't want this to be interrupting anymore, lets remove it
|
||||
mHeadsUpManager.removeNotification(key);
|
||||
} else {
|
||||
mHeadsUpManager.updateNotification(entry, alertAgain);
|
||||
}
|
||||
} else if (shouldInterrupt && alertAgain) {
|
||||
// This notification was updated to be a heads-up, show it!
|
||||
@@ -1929,7 +1934,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void escalateHeadsUp() {
|
||||
public void maybeEscalateHeadsUp() {
|
||||
TreeSet<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getSortedEntries();
|
||||
for (HeadsUpManager.HeadsUpEntry entry : entries) {
|
||||
final StatusBarNotification sbn = entry.entry.notification;
|
||||
|
||||
@@ -80,7 +80,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
private float mCurrentInFrontAlpha;
|
||||
private float mCurrentBehindAlpha;
|
||||
private float mCurrentHeadsUpAlpha = 1;
|
||||
private int mAmountOfPinnedHeadsUps;
|
||||
private int mPinnedHeadsUpCount;
|
||||
private float mTopHeadsUpDragAmount;
|
||||
private View mDraggedHeadsUpView;
|
||||
|
||||
@@ -347,25 +347,27 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly) {
|
||||
public void onPinnedModeChanged(boolean inPinnedMode) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) {
|
||||
if (isHeadsUp) {
|
||||
mAmountOfPinnedHeadsUps++;
|
||||
} else {
|
||||
mAmountOfPinnedHeadsUps--;
|
||||
if (headsUp == mDraggedHeadsUpView) {
|
||||
mDraggedHeadsUpView = null;
|
||||
mTopHeadsUpDragAmount = 0.0f;
|
||||
}
|
||||
public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
|
||||
mPinnedHeadsUpCount++;
|
||||
updateHeadsUpScrim(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
|
||||
mPinnedHeadsUpCount--;
|
||||
if (headsUp == mDraggedHeadsUpView) {
|
||||
mDraggedHeadsUpView = null;
|
||||
mTopHeadsUpDragAmount = 0.0f;
|
||||
}
|
||||
updateHeadsUpScrim(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
|
||||
public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
|
||||
}
|
||||
|
||||
private void updateHeadsUpScrim(boolean animate) {
|
||||
@@ -374,12 +376,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
TAG_KEY_ANIM);
|
||||
float animEndValue = -1;
|
||||
if (previousAnimator != null) {
|
||||
if ((animate || alpha == mCurrentHeadsUpAlpha)) {
|
||||
// lets cancel any running animators
|
||||
if (animate || alpha == mCurrentHeadsUpAlpha) {
|
||||
previousAnimator.cancel();
|
||||
}
|
||||
animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim,
|
||||
TAG_HUN_START_ALPHA);
|
||||
animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, TAG_HUN_START_ALPHA);
|
||||
}
|
||||
if (alpha != mCurrentHeadsUpAlpha && alpha != animEndValue) {
|
||||
if (animate) {
|
||||
@@ -390,7 +390,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
if (previousAnimator != null) {
|
||||
float previousStartValue = StackStateAnimator.getChildTag(mHeadsUpScrim,
|
||||
TAG_HUN_START_ALPHA);
|
||||
float previousEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim,
|
||||
float previousEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim,
|
||||
TAG_HUN_END_ALPHA);
|
||||
// we need to increase all animation keyframes of the previous animator by the
|
||||
// relative change to the end value
|
||||
@@ -410,6 +410,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount the current top heads up view is dragged. The range is from 0 to 1 and 0 means
|
||||
* the heads up is in its resting space and 1 means it's fully dragged out.
|
||||
*
|
||||
* @param draggedHeadsUpView the dragged view
|
||||
* @param topHeadsUpDragAmount how far is it dragged
|
||||
*/
|
||||
public void setTopHeadsUpDragAmount(View draggedHeadsUpView, float topHeadsUpDragAmount) {
|
||||
mTopHeadsUpDragAmount = topHeadsUpDragAmount;
|
||||
mDraggedHeadsUpView = draggedHeadsUpView;
|
||||
@@ -417,9 +424,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
}
|
||||
|
||||
private float calculateHeadsUpAlpha() {
|
||||
if (mAmountOfPinnedHeadsUps >= 2) {
|
||||
if (mPinnedHeadsUpCount >= 2) {
|
||||
return 1.0f;
|
||||
} else if (mAmountOfPinnedHeadsUps == 0) {
|
||||
} else if (mPinnedHeadsUpCount == 0) {
|
||||
return 0.0f;
|
||||
} else {
|
||||
return 1.0f - mTopHeadsUpDragAmount;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
* Copyright (C) 2015 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.
|
||||
@@ -35,11 +35,16 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* A manager which handles heads up notifications which is a special mode where
|
||||
* they simply peek from the top of the screen.
|
||||
*/
|
||||
public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsListener {
|
||||
private static final String TAG = "HeadsUpManager";
|
||||
private static final boolean DEBUG = false;
|
||||
@@ -48,7 +53,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
private final int mHeadsUpNotificationDecay;
|
||||
private final int mMinimumDisplayTime;
|
||||
|
||||
private final int mTouchSensitivityDelay;
|
||||
private final int mTouchAcceptanceDelay;
|
||||
private final ArrayMap<String, Long> mSnoozedPackages;
|
||||
private final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>();
|
||||
private final int mDefaultSnoozeLengthMs;
|
||||
@@ -67,13 +72,12 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
|
||||
@Override
|
||||
public boolean release(HeadsUpEntry instance) {
|
||||
instance.removeAutoCancelCallbacks();
|
||||
instance.reset();
|
||||
mPoolObjects.push(instance);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private PhoneStatusBar mBar;
|
||||
private int mSnoozeLengthMs;
|
||||
private ContentObserver mSettingsObserver;
|
||||
@@ -86,13 +90,12 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
private boolean mTrackingHeadsUp;
|
||||
private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
|
||||
private boolean mIsExpanded;
|
||||
private boolean mHasPinnedHeadsUp;
|
||||
private boolean mHasPinnedNotification;
|
||||
private int[] mTmpTwoArray = new int[2];
|
||||
|
||||
public HeadsUpManager(final Context context, ViewTreeObserver observer) {
|
||||
Resources resources = context.getResources();
|
||||
mTouchSensitivityDelay = resources.getInteger(R.integer.heads_up_sensitivity_delay);
|
||||
if (DEBUG) Log.v(TAG, "create() " + mTouchSensitivityDelay);
|
||||
mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
|
||||
mSnoozedPackages = new ArrayMap<>();
|
||||
mDefaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms);
|
||||
mSnoozeLengthMs = mDefaultSnoozeLengthMs;
|
||||
@@ -116,7 +119,6 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
context.getContentResolver().registerContentObserver(
|
||||
Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false,
|
||||
mSettingsObserver);
|
||||
if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs);
|
||||
observer.addOnComputeInternalInsetsListener(this);
|
||||
}
|
||||
|
||||
@@ -154,7 +156,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
if (alert) {
|
||||
HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key);
|
||||
headsUpEntry.updateEntry();
|
||||
setEntryToShade(headsUpEntry, mIsExpanded, false /* justAdded */, false);
|
||||
setEntryPinned(headsUpEntry, !mIsExpanded /* isPinned */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,22 +167,23 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
headsUpEntry.setEntry(entry);
|
||||
mHeadsUpEntries.put(entry.key, headsUpEntry);
|
||||
entry.row.setHeadsUp(true);
|
||||
setEntryToShade(headsUpEntry, mIsExpanded /* inShade */, true /* justAdded */, false);
|
||||
setEntryPinned(headsUpEntry, !mIsExpanded /* isPinned */);
|
||||
for (OnHeadsUpChangedListener listener : mListeners) {
|
||||
listener.OnHeadsUpStateChanged(entry, true);
|
||||
listener.onHeadsUpStateChanged(entry, true);
|
||||
}
|
||||
entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
||||
}
|
||||
|
||||
private void setEntryToShade(HeadsUpEntry headsUpEntry, boolean inShade, boolean justAdded,
|
||||
boolean forceImmediate) {
|
||||
private void setEntryPinned(HeadsUpEntry headsUpEntry, boolean isPinned) {
|
||||
ExpandableNotificationRow row = headsUpEntry.entry.row;
|
||||
if (row.isInShade() != inShade || justAdded) {
|
||||
row.setInShade(inShade);
|
||||
if (!justAdded || !inShade) {
|
||||
updatePinnedHeadsUpState(forceImmediate);
|
||||
for (OnHeadsUpChangedListener listener : mListeners) {
|
||||
listener.OnHeadsUpPinnedChanged(row, !inShade);
|
||||
if (row.isPinned() != isPinned) {
|
||||
row.setPinned(isPinned);
|
||||
updatePinnedMode();
|
||||
for (OnHeadsUpChangedListener listener : mListeners) {
|
||||
if (isPinned) {
|
||||
listener.onHeadsUpPinned(row);
|
||||
} else {
|
||||
listener.onHeadsUpUnPinned(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,24 +192,23 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
private void removeHeadsUpEntry(NotificationData.Entry entry) {
|
||||
HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key);
|
||||
mSortedEntries.remove(remove);
|
||||
mEntryPool.release(remove);
|
||||
entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
||||
entry.row.setHeadsUp(false);
|
||||
setEntryToShade(remove, true /* inShade */, false /* justAdded */,
|
||||
false /* forceImmediate */);
|
||||
setEntryPinned(remove, false /* isPinned */);
|
||||
for (OnHeadsUpChangedListener listener : mListeners) {
|
||||
listener.OnHeadsUpStateChanged(entry, false);
|
||||
listener.onHeadsUpStateChanged(entry, false);
|
||||
}
|
||||
mEntryPool.release(remove);
|
||||
}
|
||||
|
||||
private void updatePinnedHeadsUpState(boolean forceImmediate) {
|
||||
boolean hasPinnedHeadsUp = hasPinnedHeadsUpInternal();
|
||||
if (hasPinnedHeadsUp == mHasPinnedHeadsUp) {
|
||||
private void updatePinnedMode() {
|
||||
boolean hasPinnedNotification = hasPinnedNotificationInternal();
|
||||
if (hasPinnedNotification == mHasPinnedNotification) {
|
||||
return;
|
||||
}
|
||||
mHasPinnedHeadsUp = hasPinnedHeadsUp;
|
||||
for (OnHeadsUpChangedListener listener :mListeners) {
|
||||
listener.OnPinnedHeadsUpExistChanged(hasPinnedHeadsUp, forceImmediate);
|
||||
mHasPinnedNotification = hasPinnedNotification;
|
||||
for (OnHeadsUpChangedListener listener : mListeners) {
|
||||
listener.onPinnedModeChanged(hasPinnedNotification);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +224,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
releaseImmediately(key);
|
||||
return true;
|
||||
} else {
|
||||
getHeadsUpEntry(key).hideAsSoonAsPossible();
|
||||
getHeadsUpEntry(key).removeAsSoonAsPossible();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -245,14 +247,13 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
return mHeadsUpEntries.containsKey(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Push any current Heads Up notification down into the shade.
|
||||
*/
|
||||
public void releaseAllImmediately() {
|
||||
if (DEBUG) Log.v(TAG, "releaseAllImmediately");
|
||||
HashSet<String> keys = new HashSet<>(mHeadsUpEntries.keySet());
|
||||
for (String key: keys) {
|
||||
ArrayList<String> keys = new ArrayList<>(mHeadsUpEntries.keySet());
|
||||
for (String key : keys) {
|
||||
releaseImmediately(key);
|
||||
}
|
||||
}
|
||||
@@ -280,7 +281,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
}
|
||||
|
||||
public void snooze() {
|
||||
for (String key: mHeadsUpEntries.keySet()) {
|
||||
for (String key : mHeadsUpEntries.keySet()) {
|
||||
HeadsUpEntry entry = mHeadsUpEntries.get(key);
|
||||
String packageName = entry.entry.notification.getPackageName();
|
||||
mSnoozedPackages.put(snoozeKey(packageName, mUser),
|
||||
@@ -310,8 +311,11 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides whether a click is invalid for a notification, i.e it has not been shown long enough
|
||||
* that a user might have consciously clicked on it.
|
||||
*
|
||||
* @param key the key of the touched notification
|
||||
* @return whether the touch is valid and should not be discarded
|
||||
* @return whether the touch is invalid and should be discarded
|
||||
*/
|
||||
public boolean shouldSwallowClick(String key) {
|
||||
HeadsUpEntry entry = mHeadsUpEntries.get(key);
|
||||
@@ -322,14 +326,14 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
}
|
||||
|
||||
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
|
||||
if (!mIsExpanded && mHasPinnedHeadsUp) {
|
||||
if (!mIsExpanded && mHasPinnedNotification) {
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int maxX = 0;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int maxY = 0;
|
||||
for (HeadsUpEntry entry: mSortedEntries) {
|
||||
for (HeadsUpEntry entry : mSortedEntries) {
|
||||
ExpandableNotificationRow row = entry.entry.row;
|
||||
if (!row.isInShade()) {
|
||||
if (row.isPinned()) {
|
||||
row.getLocationOnScreen(mTmpTwoArray);
|
||||
minX = Math.min(minX, mTmpTwoArray[0]);
|
||||
minY = Math.min(minY, 0);
|
||||
@@ -349,7 +353,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println("HeadsUpManager state:");
|
||||
pw.print(" mTouchSensitivityDelay="); pw.println(mTouchSensitivityDelay);
|
||||
pw.print(" mTouchAcceptanceDelay="); pw.println(mTouchAcceptanceDelay);
|
||||
pw.print(" mSnoozeLengthMs="); pw.println(mSnoozeLengthMs);
|
||||
pw.print(" now="); pw.println(SystemClock.elapsedRealtime());
|
||||
pw.print(" mUser="); pw.println(mUser);
|
||||
@@ -365,38 +369,32 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
}
|
||||
|
||||
public boolean hasPinnedHeadsUp() {
|
||||
return mHasPinnedHeadsUp;
|
||||
return mHasPinnedNotification;
|
||||
}
|
||||
|
||||
private boolean hasPinnedHeadsUpInternal() {
|
||||
for (String key: mHeadsUpEntries.keySet()) {
|
||||
private boolean hasPinnedNotificationInternal() {
|
||||
for (String key : mHeadsUpEntries.keySet()) {
|
||||
HeadsUpEntry entry = mHeadsUpEntries.get(key);
|
||||
if (!entry.entry.row.isInShade()) {
|
||||
if (entry.entry.row.isPinned()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addSwipedOutKey(String key) {
|
||||
/**
|
||||
* Notifies that a notification was swiped out and will be removed.
|
||||
*
|
||||
* @param key the notification key
|
||||
*/
|
||||
public void addSwipedOutNotification(String key) {
|
||||
mSwipedOutKeys.add(key);
|
||||
}
|
||||
|
||||
public float getHighestPinnedHeadsUp() {
|
||||
float max = 0;
|
||||
for (HeadsUpEntry entry: mSortedEntries) {
|
||||
if (!entry.entry.row.isInShade()) {
|
||||
max = Math.max(max, entry.entry.row.getActualHeight());
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public void releaseAllToShade() {
|
||||
for (String key: mHeadsUpEntries.keySet()) {
|
||||
public void unpinAll() {
|
||||
for (String key : mHeadsUpEntries.keySet()) {
|
||||
HeadsUpEntry entry = mHeadsUpEntries.get(key);
|
||||
setEntryToShade(entry, true /* toShade */, false /* justAdded */,
|
||||
true /* forceImmediate */);
|
||||
setEntryPinned(entry, false /* isPinned */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +418,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
if (isExpanded != mIsExpanded) {
|
||||
mIsExpanded = isExpanded;
|
||||
if (isExpanded) {
|
||||
releaseAllToShade();
|
||||
unpinAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,6 +428,12 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
return topEntry != null ? topEntry.entry.row.getHeadsUpHeight() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two entries and decide how they should be ranked.
|
||||
*
|
||||
* @return -1 if the first argument should be ranked higher than the second, 1 if the second
|
||||
* one should be ranked higher and 0 if they are equal.
|
||||
*/
|
||||
public int compare(NotificationData.Entry a, NotificationData.Entry b) {
|
||||
HeadsUpEntry aEntry = getHeadsUpEntry(a.key);
|
||||
HeadsUpEntry bEntry = getHeadsUpEntry(b.key);
|
||||
@@ -439,6 +443,11 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
return aEntry.compareTo(bEntry);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This represents a notification and how long it is in a heads up mode. It also manages its
|
||||
* lifecycle automatically when created.
|
||||
*/
|
||||
public class HeadsUpEntry implements Comparable<HeadsUpEntry> {
|
||||
public NotificationData.Entry entry;
|
||||
public long postTime;
|
||||
@@ -449,7 +458,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
this.entry = entry;
|
||||
|
||||
// The actual post time will be just after the heads-up really slided in
|
||||
postTime = mClock.currentTimeMillis() + mTouchSensitivityDelay;
|
||||
postTime = mClock.currentTimeMillis() + mTouchAcceptanceDelay;
|
||||
mRemoveHeadsUpRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -467,7 +476,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
long currentTime = mClock.currentTimeMillis();
|
||||
earliestRemovaltime = currentTime + mMinimumDisplayTime;
|
||||
postTime = Math.max(postTime, currentTime);
|
||||
removeAutoCancelCallbacks();
|
||||
removeAutoRemovalCallbacks();
|
||||
if (canEntryDecay()) {
|
||||
long finishTime = postTime + mHeadsUpNotificationDecay;
|
||||
long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime);
|
||||
@@ -487,7 +496,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
: -1;
|
||||
}
|
||||
|
||||
public void removeAutoCancelCallbacks() {
|
||||
public void removeAutoRemovalCallbacks() {
|
||||
mHandler.removeCallbacks(mRemoveHeadsUpRunnable);
|
||||
}
|
||||
|
||||
@@ -495,11 +504,17 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
return earliestRemovaltime < mClock.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void hideAsSoonAsPossible() {
|
||||
removeAutoCancelCallbacks();
|
||||
public void removeAsSoonAsPossible() {
|
||||
removeAutoRemovalCallbacks();
|
||||
mHandler.postDelayed(mRemoveHeadsUpRunnable,
|
||||
earliestRemovaltime - mClock.currentTimeMillis());
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
removeAutoRemovalCallbacks();
|
||||
entry = null;
|
||||
mRemoveHeadsUpRunnable = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -519,8 +534,29 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
|
||||
}
|
||||
|
||||
public interface OnHeadsUpChangedListener {
|
||||
void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly);
|
||||
void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp);
|
||||
void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp);
|
||||
/**
|
||||
* The state whether there exist pinned heads-ups or not changed.
|
||||
*
|
||||
* @param inPinnedMode whether there are any pinned heads-ups
|
||||
*/
|
||||
void onPinnedModeChanged(boolean inPinnedMode);
|
||||
|
||||
/**
|
||||
* A notification was just pinned to the top.
|
||||
*/
|
||||
void onHeadsUpPinned(ExpandableNotificationRow headsUp);
|
||||
|
||||
/**
|
||||
* A notification was just unpinned from the top.
|
||||
*/
|
||||
void onHeadsUpUnPinned(ExpandableNotificationRow headsUp);
|
||||
|
||||
/**
|
||||
* A notification just became a heads up or turned back to its normal state.
|
||||
*
|
||||
* @param entry the entry of the changed notification
|
||||
* @param isHeadsUp whether the notification is now a headsUp notification
|
||||
*/
|
||||
void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.stack;
|
||||
|
||||
import android.graphics.Path;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
/**
|
||||
* An interpolator specifically designed for the appear animation of heads up notifications.
|
||||
*/
|
||||
public class HeadsUpAppearInterpolator extends PathInterpolator {
|
||||
public HeadsUpAppearInterpolator() {
|
||||
super(getAppearPath());
|
||||
}
|
||||
|
||||
private static Path getAppearPath() {
|
||||
Path path = new Path();
|
||||
path.moveTo(0, 0);
|
||||
float x1 = 250f;
|
||||
float x2 = 150f;
|
||||
float x3 = 100f;
|
||||
float y1 = 90f;
|
||||
float y2 = 78f;
|
||||
float y3 = 80f;
|
||||
float xTot = (x1 + x2 + x3);
|
||||
path.cubicTo(x1 * 0.9f / xTot, 0f,
|
||||
x1 * 0.8f / xTot, y1 / y3,
|
||||
x1 / xTot , y1 / y3);
|
||||
path.cubicTo((x1 + x2 * 0.4f) / xTot, y1 / y3,
|
||||
(x1 + x2 * 0.2f) / xTot, y2 / y3,
|
||||
(x1 + x2) / xTot, y2 / y3);
|
||||
path.cubicTo((x1 + x2 + x3 * 0.4f) / xTot, y2 / y3,
|
||||
(x1 + x2 + x3 * 0.2f) / xTot, 1f,
|
||||
1f, 1f);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -204,7 +204,6 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
private ViewGroup mScrollView;
|
||||
private boolean mInterceptDelegateEnabled;
|
||||
private boolean mDelegateToScrollView;
|
||||
|
||||
private boolean mDisallowScrollingInThisMotion;
|
||||
private long mGoToFullShadeDelay;
|
||||
private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
|
||||
@@ -487,9 +486,9 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
int stackHeight;
|
||||
float paddingOffset;
|
||||
boolean trackingHeadsUp = mTrackingHeadsUp;
|
||||
int normalExpandPositionStart = trackingHeadsUp ? mHeadsUpManager.getTopHeadsUpHeight()
|
||||
int normalUnfoldPositionStart = trackingHeadsUp ? mHeadsUpManager.getTopHeadsUpHeight()
|
||||
: minStackHeight;
|
||||
if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalExpandPositionStart
|
||||
if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalUnfoldPositionStart
|
||||
|| getNotGoneChildCount() == 0) {
|
||||
paddingOffset = mTopPaddingOverflow;
|
||||
stackHeight = newStackHeight;
|
||||
@@ -582,7 +581,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
if (v instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) v;
|
||||
if (row.isHeadsUp()) {
|
||||
mHeadsUpManager.addSwipedOutKey(row.getStatusBarNotification().getKey());
|
||||
mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey());
|
||||
}
|
||||
}
|
||||
final View veto = v.findViewById(R.id.veto);
|
||||
@@ -626,10 +625,10 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
requestChildrenUpdate();
|
||||
}
|
||||
|
||||
public boolean isPinnedHeadsUp(View v) {
|
||||
public static boolean isPinnedHeadsUp(View v) {
|
||||
if (v instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) v;
|
||||
return row.isHeadsUp() && !row.isInShade();
|
||||
return row.isHeadsUp() && row.isPinned();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -711,7 +710,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
if (touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
|
||||
if (slidingChild instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
|
||||
if (row.isHeadsUp() && !row.isInShade()
|
||||
if (row.isHeadsUp() && row.isPinned()
|
||||
&& mHeadsUpManager.getTopEntry().entry.row != row) {
|
||||
continue;
|
||||
}
|
||||
@@ -812,7 +811,8 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
}
|
||||
handleEmptySpaceClick(ev);
|
||||
boolean expandWantsIt = false;
|
||||
if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) {
|
||||
if (mIsExpanded && !mSwipingInProgress && !mOnlyScrollingInThisMotion
|
||||
&& isScrollingEnabled()) {
|
||||
if (isCancelOrUp) {
|
||||
mExpandHelper.onlyObserveMovements(false);
|
||||
}
|
||||
@@ -824,7 +824,8 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
}
|
||||
}
|
||||
boolean scrollerWantsIt = false;
|
||||
if (!mSwipingInProgress && !mExpandingNotification && !mDisallowScrollingInThisMotion) {
|
||||
if (mIsExpanded && !mSwipingInProgress && !mExpandingNotification
|
||||
&& !mDisallowScrollingInThisMotion) {
|
||||
scrollerWantsIt = onScrollTouch(ev);
|
||||
}
|
||||
boolean horizontalSwipeWantsIt = false;
|
||||
@@ -1872,15 +1873,15 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
boolean onBottom = false;
|
||||
if (!mIsExpanded && !isHeadsUp) {
|
||||
type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
|
||||
} else if (mAddedHeadsUpChildren.contains(row) || (!row.isInShade() && !mIsExpanded)) {
|
||||
if (!row.isInShade() || shouldHunAppearFromBottom(row)) {
|
||||
} else if (mAddedHeadsUpChildren.contains(row) || (row.isPinned() && !mIsExpanded)) {
|
||||
if (row.isPinned() || shouldHunAppearFromBottom(row)) {
|
||||
// Our custom add animation
|
||||
type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR;
|
||||
} else {
|
||||
// Normal add animation
|
||||
type = AnimationEvent.ANIMATION_TYPE_ADD;
|
||||
}
|
||||
onBottom = row.isInShade();
|
||||
onBottom = !row.isPinned();
|
||||
}
|
||||
AnimationEvent event = new AnimationEvent(row, type);
|
||||
event.headsUpFromBottom = onBottom;
|
||||
@@ -2670,7 +2671,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
}
|
||||
}
|
||||
|
||||
public void performOnAnimationFinished(Runnable runnable) {
|
||||
public void runAfterAnimationFinished(Runnable runnable) {
|
||||
mAnimationFinishedRunnables.add(runnable);
|
||||
}
|
||||
|
||||
|
||||
@@ -311,7 +311,8 @@ public class StackScrollAlgorithm {
|
||||
StackViewState viewState = resultState.getViewStateForView(
|
||||
nextChild);
|
||||
// The child below the dragged one must be fully visible
|
||||
if (!isPinnedHeadsUpView(draggedView) || isPinnedHeadsUpView(nextChild)) {
|
||||
if (!NotificationStackScrollLayout.isPinnedHeadsUp(draggedView)
|
||||
|| NotificationStackScrollLayout.isPinnedHeadsUp(nextChild)) {
|
||||
viewState.alpha = 1;
|
||||
}
|
||||
}
|
||||
@@ -324,14 +325,6 @@ public class StackScrollAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPinnedHeadsUpView(View view) {
|
||||
if (view instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
|
||||
return row.isHeadsUp() && !row.isInShade();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the visible children on the state.
|
||||
*/
|
||||
@@ -380,7 +373,7 @@ 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 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
|
||||
*/
|
||||
@@ -515,11 +508,12 @@ public class StackScrollAlgorithm {
|
||||
}
|
||||
StackViewState childState = resultState.getViewStateForView(row);
|
||||
boolean isTopEntry = topHeadsUpEntry == row;
|
||||
if (!row.isInShade()) {
|
||||
if (row.isPinned()) {
|
||||
childState.yTranslation = 0;
|
||||
childState.height = row.getHeadsUpHeight();
|
||||
if (!isTopEntry) {
|
||||
// Ensure that a headsUp is never below the topmost headsUp
|
||||
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
|
||||
// the top most z-position
|
||||
StackViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
|
||||
childState.height = row.getHeadsUpHeight();
|
||||
childState.yTranslation = topState.yTranslation + topState.height
|
||||
|
||||
@@ -21,11 +21,9 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.graphics.Path;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.ExpandableNotificationRow;
|
||||
@@ -78,6 +76,7 @@ public class StackStateAnimator {
|
||||
private final Interpolator mFastOutSlowInInterpolator;
|
||||
private final Interpolator mHeadsUpAppearInterpolator;
|
||||
private final int mGoToFullShadeAppearingTranslation;
|
||||
private final StackViewState mTmpState = new StackViewState();
|
||||
public NotificationStackScrollLayout mHostLayout;
|
||||
private ArrayList<NotificationStackScrollLayout.AnimationEvent> mNewEvents =
|
||||
new ArrayList<>();
|
||||
@@ -95,7 +94,6 @@ public class StackStateAnimator {
|
||||
private ValueAnimator mTopOverScrollAnimator;
|
||||
private ValueAnimator mBottomOverScrollAnimator;
|
||||
private ExpandableNotificationRow mChildExpandingView;
|
||||
private StackViewState mTmpState = new StackViewState();
|
||||
private int mHeadsUpAppearHeightBottom;
|
||||
private boolean mShadeExpanded;
|
||||
|
||||
@@ -106,25 +104,7 @@ public class StackStateAnimator {
|
||||
mGoToFullShadeAppearingTranslation =
|
||||
hostLayout.getContext().getResources().getDimensionPixelSize(
|
||||
R.dimen.go_to_full_shade_appearing_translation);
|
||||
Path path = new Path();
|
||||
path.moveTo(0, 0);
|
||||
float x1 = 250f;
|
||||
float x2 = 150f;
|
||||
float x3 = 100f;
|
||||
float y1 = 90f;
|
||||
float y2 = 78f;
|
||||
float y3 = 80f;
|
||||
float xTot = (x1 + x2 + x3);
|
||||
path.cubicTo(x1 * 0.9f / xTot, 0f,
|
||||
x1 * 0.8f / xTot, y1 / y3,
|
||||
x1 / xTot , y1 / y3);
|
||||
path.cubicTo((x1 + x2 * 0.4f) / xTot, y1 / y3,
|
||||
(x1 + x2 * 0.2f) / xTot, y2 / y3,
|
||||
(x1 + x2) / xTot, y2 / y3);
|
||||
path.cubicTo((x1 + x2 + x3 * 0.4f) / xTot, y2 / y3,
|
||||
(x1 + x2 + x3 * 0.2f) / xTot, 1f,
|
||||
1f, 1f);
|
||||
mHeadsUpAppearInterpolator = new PathInterpolator(path);
|
||||
mHeadsUpAppearInterpolator = new HeadsUpAppearInterpolator();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
|
||||
@@ -121,7 +121,7 @@ public class TvStatusBar extends BaseStatusBar {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void escalateHeadsUp() {
|
||||
public void maybeEscalateHeadsUp() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user