Update snooze visuals to match latest design
Also updates it so that the height animates going from collapsed / expanded
Test: manual / runtest systemui
Bug: 36249479
Change-Id: Ice10e42986eddc9b87ba79cd00dfc59fefef5464
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 677642e..f6e79be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1490,7 +1490,7 @@
return getActualHeight();
}
if (mGuts != null && mGuts.isExposed()) {
- return mGuts.getHeight();
+ return mGuts.getIntrinsicHeight();
} else if ((isChildInGroup() && !isGroupExpanded())) {
return mPrivateLayout.getMinHeight();
} else if (mShowAmbient) {
@@ -1831,7 +1831,9 @@
@Override
public int getMinHeight() {
- if (!mOnKeyguard && mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
+ if (mGuts != null && mGuts.isExposed()) {
+ return mGuts.getIntrinsicHeight();
+ } else if (!mOnKeyguard && mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
} else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
return mChildrenContainer.getMinHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 2713f58..daad2c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -73,7 +73,8 @@
private Handler mHandler;
private Runnable mFalsingCheck;
private boolean mNeedsFalsingProtection;
- private OnGutsClosedListener mListener;
+ private OnGutsClosedListener mClosedListener;
+ private OnHeightChangedListener mHeightListener;
private GutsContent mGutsContent;
@@ -87,6 +88,11 @@
public View getContentView();
/**
+ * @return the actual height of the content.
+ */
+ public int getActualHeight();
+
+ /**
* Called when the guts view have been told to close, typically after an outside
* interaction. Returning {@code true} here will prevent the guts view to close.
*/
@@ -102,6 +108,10 @@
public void onGutsClosed(NotificationGuts guts);
}
+ public interface OnHeightChangedListener {
+ public void onHeightChanged(NotificationGuts guts);
+ }
+
interface OnSettingsClickListener {
void onClick(View v, int appUid);
}
@@ -125,7 +135,6 @@
public NotificationGuts(Context context) {
this(context, null);
-
}
public void setGutsContent(GutsContent content) {
@@ -189,8 +198,8 @@
public void closeControls(int x, int y, boolean save) {
if (getWindowToken() == null) {
- if (mListener != null) {
- mListener.onGutsClosed(this);
+ if (mClosedListener != null) {
+ mClosedListener.onGutsClosed(this);
}
return;
}
@@ -198,8 +207,8 @@
animateClose(x, y);
}
setExposed(false, mNeedsFalsingProtection);
- if (mListener != null) {
- mListener.onGutsClosed(this);
+ if (mClosedListener != null) {
+ mClosedListener.onGutsClosed(this);
}
}
@@ -234,6 +243,10 @@
return mActualHeight;
}
+ public int getIntrinsicHeight() {
+ return mGutsContent != null && mExposed ? mGutsContent.getActualHeight() : getHeight();
+ }
+
public void setClipTopAmount(int clipTopAmount) {
mClipTopAmount = clipTopAmount;
invalidate();
@@ -251,7 +264,17 @@
}
public void setClosedListener(OnGutsClosedListener listener) {
- mListener = listener;
+ mClosedListener = listener;
+ }
+
+ public void setHeightChangedListener(OnHeightChangedListener listener) {
+ mHeightListener = listener;
+ }
+
+ protected void onHeightChanged() {
+ if (mHeightListener != null) {
+ mHeightListener.onHeightChanged(this);
+ }
}
public void setExposed(boolean exposed, boolean needsFalsingProtection) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 7928575..c1c5714 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -386,4 +386,9 @@
}
return false;
}
+
+ @Override
+ public int getActualHeight() {
+ return getHeight();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
index 4a3f112..ccc99c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
@@ -21,35 +21,47 @@
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Color;
+import android.graphics.Typeface;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
+import android.text.SpannableString;
+import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.TypedValue;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
public class NotificationSnooze extends LinearLayout
implements NotificationGuts.GutsContent, View.OnClickListener {
- private static final int MAX_ASSISTANT_SUGGESTIONS = 2;
+ private static final int MAX_ASSISTANT_SUGGESTIONS = 1;
private NotificationGuts mGutsContainer;
private NotificationSwipeActionHelper mSnoozeListener;
private StatusBarNotification mSbn;
private TextView mSelectedOptionText;
private TextView mUndoButton;
- private ViewGroup mSnoozeOptionView;
+ private ImageView mExpandButton;
+ private View mDivider;
+ private ViewGroup mSnoozeOptionContainer;
private List<SnoozeOption> mSnoozeOptions;
- private boolean mSnoozing;
+ private int mCollapsedHeight;
private SnoozeOption mSelectedOption;
+ private boolean mSnoozing;
+ private boolean mExpanded;
+ private AnimatorSet mExpandAnimation;
public NotificationSnooze(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -58,16 +70,21 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.snooze_snackbar_min_height);
+ findViewById(R.id.notification_snooze).setOnClickListener(this);
+ mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
+ mUndoButton = (TextView) findViewById(R.id.undo);
+ mUndoButton.setOnClickListener(this);
+ mExpandButton = (ImageView) findViewById(R.id.expand_button);
+ mDivider = findViewById(R.id.divider);
+ mDivider.setAlpha(0f);
+ mSnoozeOptionContainer = (ViewGroup) findViewById(R.id.snooze_options);
+ mSnoozeOptionContainer.setAlpha(0f);
+
// Create the different options based on list
mSnoozeOptions = getDefaultSnoozeOptions();
createOptionViews();
- // Snackbar
- mSelectedOptionText = findViewById(R.id.snooze_option_default);
- mSelectedOptionText.setOnClickListener(this);
- mUndoButton = findViewById(R.id.undo);
- mUndoButton.setOnClickListener(this);
-
// Default to first option in list
setSelected(mSnoozeOptions.get(0));
}
@@ -96,52 +113,68 @@
private SnoozeOption createOption(int descriptionResId, int minutes) {
Resources res = getResources();
- String resultText = String.format(
- res.getString(R.string.snoozed_for_time), res.getString(descriptionResId));
- return new SnoozeOption(null, minutes, res.getString(descriptionResId), resultText);
+ final String description = res.getString(descriptionResId);
+ String resultText = String.format(res.getString(R.string.snoozed_for_time), description);
+ SpannableString string = new SpannableString(resultText);
+ string.setSpan(new StyleSpan(Typeface.BOLD),
+ resultText.length() - description.length(), resultText.length(), 0 /* flags */);
+ return new SnoozeOption(null, minutes, res.getString(descriptionResId), string);
}
private void createOptionViews() {
- mSnoozeOptionView = findViewById(R.id.snooze_options);
- mSnoozeOptionView.removeAllViews();
- mSnoozeOptionView.setVisibility(View.GONE);
- final Resources res = getResources();
- final int textSize = res.getDimensionPixelSize(R.dimen.snooze_option_text_size);
- final int p = res.getDimensionPixelSize(R.dimen.snooze_option_padding);
-
- // Add all the options
+ mSnoozeOptionContainer.removeAllViews();
+ LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
for (int i = 0; i < mSnoozeOptions.size(); i++) {
SnoozeOption option = mSnoozeOptions.get(i);
- TextView tv = new TextView(getContext());
- tv.setTextColor(Color.WHITE);
- tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
- tv.setPadding(p, p, p, p);
- mSnoozeOptionView.addView(tv);
+ TextView tv = (TextView) inflater.inflate(R.layout.notification_snooze_option,
+ mSnoozeOptionContainer, false);
+ mSnoozeOptionContainer.addView(tv);
tv.setText(option.description);
tv.setTag(option);
tv.setOnClickListener(this);
}
+ }
- // Add the undo option as final item
- TextView tv = new TextView(getContext());
- tv.setTextColor(Color.WHITE);
- tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
- tv.setPadding(p, p, p, p);
- mSnoozeOptionView.addView(tv);
- tv.setText(R.string.snooze_option_dont_snooze);
- tv.setOnClickListener(this);
+ private void hideSelectedOption() {
+ final int childCount = mSnoozeOptionContainer.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = mSnoozeOptionContainer.getChildAt(i);
+ child.setVisibility(child.getTag() == mSelectedOption ? View.GONE : View.VISIBLE);
+ }
}
private void showSnoozeOptions(boolean show) {
- mSelectedOptionText.setVisibility(show ? View.GONE : View.VISIBLE);
- mUndoButton.setVisibility(show ? View.GONE : View.VISIBLE);
- mSnoozeOptionView.setVisibility(show ? View.VISIBLE : View.GONE);
+ mExpanded = show;
+ animateSnoozeOptions(show);
+ int drawableId = show ? com.android.internal.R.drawable.ic_collapse_notification
+ : com.android.internal.R.drawable.ic_expand_notification;
+ mExpandButton.setImageResource(drawableId);
+ if (mGutsContainer != null) {
+ mGutsContainer.onHeightChanged();
+ }
+ }
+
+ private void animateSnoozeOptions(boolean show) {
+ if (mExpandAnimation != null) {
+ mExpandAnimation.cancel();
+ }
+ ObjectAnimator dividerAnim = ObjectAnimator.ofFloat(mDivider, View.ALPHA,
+ mDivider.getAlpha(), show ? 1f : 0f);
+ ObjectAnimator optionAnim = ObjectAnimator.ofFloat(mSnoozeOptionContainer, View.ALPHA,
+ mSnoozeOptionContainer.getAlpha(), show ? 1f : 0f);
+ mExpandAnimation = new AnimatorSet();
+ mExpandAnimation.playTogether(dividerAnim, optionAnim);
+ mExpandAnimation.setDuration(150);
+ mExpandAnimation.setInterpolator(show ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+ mExpandAnimation.start();
}
private void setSelected(SnoozeOption option) {
mSelectedOption = option;
mSelectedOptionText.setText(option.confirmation);
showSnoozeOptions(false);
+ hideSelectedOption();
}
@Override
@@ -153,17 +186,28 @@
final SnoozeOption tag = (SnoozeOption) v.getTag();
if (tag != null) {
setSelected(tag);
- } else if (id == R.id.snooze_option_default) {
- // Show more snooze options
- showSnoozeOptions(true);
+ } else if (id == R.id.notification_snooze) {
+ // Toggle snooze options
+ showSnoozeOptions(!mExpanded);
} else {
- undoSnooze();
+ // Undo snooze was selected
+ mSelectedOption = null;
+ int[] parentLoc = new int[2];
+ int[] targetLoc = new int[2];
+ mGutsContainer.getLocationOnScreen(parentLoc);
+ v.getLocationOnScreen(targetLoc);
+ final int centerX = v.getWidth() / 2;
+ final int centerY = v.getHeight() / 2;
+ final int x = targetLoc[0] - parentLoc[0] + centerX;
+ final int y = targetLoc[1] - parentLoc[1] + centerY;
+ showSnoozeOptions(false);
+ mGutsContainer.closeControls(x, y, false /* save */);
}
}
- private void undoSnooze() {
- mSelectedOption = null;
- mGutsContainer.closeControls(-1 /* x */, -1 /* y */, true /* notify */);
+ @Override
+ public int getActualHeight() {
+ return mExpanded ? getHeight() : mCollapsedHeight;
}
@Override
@@ -173,6 +217,8 @@
@Override
public View getContentView() {
+ // Reset the view before use
+ setSelected(mSnoozeOptions.get(0));
return this;
}
@@ -197,11 +243,8 @@
mSnoozing = true;
mSnoozeListener.snooze(mSbn, mSelectedOption);
return true;
- } else {
- // Reset the view once it's closed
- setSelected(mSnoozeOptions.get(0));
- showSnoozeOptions(false);
}
+ // The view should be closed
return false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index fbf53e3..3acd009 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5774,6 +5774,9 @@
snoozeGuts.setSnoozeListener(mStackScroller.getSwipeActionHelper());
snoozeGuts.setStatusBarNotification(sbn);
snoozeGuts.setSnoozeOptions(row.getEntry().snoozeCriteria);
+ guts.setHeightChangedListener((NotificationGuts g) -> {
+ mStackScroller.onHeightChanged(row, row.isShown() /* needsAnimation */);
+ });
}
if (gutsView instanceof NotificationInfo) {