Zen: Improve zen mode panel condition selection.
- Decouple condition requests from expansion, now
pre-request when zen panel unhidden.
- Animate zen mode panel expansion.
- Improve default selection logic, ensure something
is selected as soon as we are in the expanded state.
- Tweak visual spacing.
- Map null condition to Indef properly when we start
out in zen.
- Avoid unnecessary condition teardown when the conditions
are updated but unchanged from current.
- Cap number of optional conditions to display, default=3.
Bug: 18335618
Change-Id: I007b7c3b2e75e2b42805af240684aa8581e9951a
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 3a91d1a..80bdbf1 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -160,7 +160,7 @@
}
public static boolean isValidId(Uri id, String pkg) {
- return id != null && id.getScheme().equals(SCHEME) && id.getAuthority().equals(pkg);
+ return id != null && SCHEME.equals(id.getScheme()) && pkg.equals(id.getAuthority());
}
public static final Parcelable.Creator<Condition> CREATOR
diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml
index a9ad1fc..0b91913 100644
--- a/packages/SystemUI/res/layout/zen_mode_condition.xml
+++ b/packages/SystemUI/res/layout/zen_mode_condition.xml
@@ -17,14 +17,15 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/qs_detail_item_height"
+ android:layout_marginBottom="@dimen/zen_mode_condition_detail_item_spacing"
android:layout_marginStart="@dimen/zen_mode_condition_detail_button_padding"
android:layout_marginEnd="@dimen/zen_mode_condition_detail_button_padding" >
<RadioButton
android:id="@android:id/checkbox"
android:layout_width="40dp"
- android:layout_marginStart="2dp"
- android:layout_marginEnd="1dp"
+ android:layout_marginStart="7dp"
+ android:layout_marginEnd="4dp"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:gravity="center" />
@@ -51,6 +52,7 @@
android:id="@android:id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/zen_mode_condition_detail_item_interline_spacing"
android:ellipsize="end"
android:textAlignment="viewStart"
android:maxLines="1"
@@ -64,7 +66,6 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerVertical="true"
- android:layout_marginEnd="@dimen/zen_mode_condition_detail_button_padding"
android:scaleType="center"
android:layout_toStartOf="@android:id/button2"
android:contentDescription="@string/accessibility_quick_settings_less_time"
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index f2dc402..922f90d 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -58,6 +58,8 @@
android:background="@drawable/btn_borderless_rect"
android:clickable="true"
android:drawableEnd="@drawable/qs_subhead_caret"
+ android:maxLines="2"
+ android:ellipsize="end"
android:textAppearance="@style/TextAppearance.QS.Subhead" />
<TextView
@@ -67,6 +69,8 @@
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:paddingLeft="8dp"
+ android:maxLines="2"
+ android:ellipsize="end"
android:textAppearance="@style/TextAppearance.QS.Subhead" />
<ImageView
@@ -87,6 +91,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingBottom="@dimen/qs_panel_padding" />
+ android:paddingBottom="@dimen/zen_mode_condition_detail_bottom_padding" />
</com.android.systemui.volume.ZenModePanel>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index b299f35..9a95b37 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -278,6 +278,9 @@
<!-- Number of times to show the strong alarm warning text in the volume dialog -->
<integer name="zen_mode_alarm_warning_threshold">5</integer>
+ <!-- Maximum number of optional conditions to display in the zen mode selection panel -->
+ <integer name="zen_mode_max_conditions">3</integer>
+
<!-- Enable the default volume dialog -->
<bool name="enable_volume_ui">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1143553..68a7622 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -197,8 +197,18 @@
<!-- How far the expanded QS panel peeks from the header in collapsed state. -->
<dimen name="qs_peek_height">8dp</dimen>
+ <!-- Zen mode panel: condition item button padding -->
<dimen name="zen_mode_condition_detail_button_padding">8dp</dimen>
+ <!-- Zen mode panel: spacing between condition items -->
+ <dimen name="zen_mode_condition_detail_item_spacing">12dp</dimen>
+
+ <!-- Zen mode panel: spacing between two-line condition upper and lower lines -->
+ <dimen name="zen_mode_condition_detail_item_interline_spacing">4dp</dimen>
+
+ <!-- Zen mode panel: bottom padding, a bit less than qs_panel_padding -->
+ <dimen name="zen_mode_condition_detail_bottom_padding">4dp</dimen>
+
<!-- used by DessertCase -->
<dimen name="dessert_case_cell_size">192dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index b84b138..6ed24e0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -16,6 +16,7 @@
package com.android.systemui.volume;
+import android.animation.LayoutTransition;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -36,6 +37,9 @@
import android.util.MathUtils;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
@@ -65,7 +69,6 @@
private static final int FOREVER_CONDITION_INDEX = 0;
private static final int TIME_CONDITION_INDEX = 1;
private static final int FIRST_CONDITION_INDEX = 2;
- private static final long SELECT_DEFAULT_DELAY = 300;
public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -76,6 +79,8 @@
private final IconPulser mIconPulser;
private final int mSubheadWarningColor;
private final int mSubheadColor;
+ private final Interpolator mInterpolator;
+ private final int mMaxConditions;
private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
@@ -96,6 +101,7 @@
private boolean mHidden = false;
private int mSessionZen;
private int mAttachedZen;
+ private boolean mAttached;
private Condition mSessionExitCondition;
private Condition[] mConditions;
private Condition mTimeCondition;
@@ -109,6 +115,10 @@
final Resources res = mContext.getResources();
mSubheadWarningColor = res.getColor(R.color.system_warning_color);
mSubheadColor = res.getColor(R.color.qs_subhead);
+ mInterpolator = AnimationUtils.loadInterpolator(mContext,
+ com.android.internal.R.interpolator.fast_out_slow_in);
+ mMaxConditions = MathUtils.constrain(res.getInteger(R.integer.zen_mode_max_conditions),
+ 1, 100);
if (DEBUG) Log.d(mTag, "new ZenModePanel");
}
@@ -149,17 +159,30 @@
Interaction.register(mMoreSettings, mInteractionCallback);
mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions);
+ setLayoutTransition(newLayoutTransition());
+ }
+
+ private LayoutTransition newLayoutTransition() {
+ final LayoutTransition transition = new LayoutTransition();
+ transition.disableTransitionType(LayoutTransition.DISAPPEARING);
+ transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
+ transition.setInterpolator(LayoutTransition.APPEARING, mInterpolator);
+ transition.setInterpolator(LayoutTransition.CHANGE_APPEARING, mInterpolator);
+ return transition;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (DEBUG) Log.d(mTag, "onAttachedToWindow");
+ ((ViewGroup) getParent()).setLayoutTransition(newLayoutTransition());
+ mAttached = true;
mAttachedZen = getSelectedZen(-1);
mSessionZen = mAttachedZen;
mSessionExitCondition = copy(mExitCondition);
refreshExitConditionText();
updateWidgets();
+ setRequestingConditions(!mHidden);
}
@Override
@@ -167,15 +190,19 @@
super.onDetachedFromWindow();
if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
checkForAttachedZenChange();
+ mAttached = false;
mAttachedZen = -1;
mSessionZen = -1;
mSessionExitCondition = null;
setExpanded(false);
+ setRequestingConditions(false);
}
public void setHidden(boolean hidden) {
if (mHidden == hidden) return;
+ if (DEBUG) Log.d(mTag, "hidden=" + hidden);
mHidden = hidden;
+ setRequestingConditions(mAttached && !mHidden);
updateWidgets();
}
@@ -193,8 +220,10 @@
private void setExpanded(boolean expanded) {
if (expanded == mExpanded) return;
mExpanded = expanded;
+ if (mExpanded) {
+ ensureSelection();
+ }
updateWidgets();
- setRequestingConditions(mExpanded);
fireExpanded();
}
@@ -331,10 +360,38 @@
}
private void handleUpdateConditions(Condition[] conditions) {
+ conditions = trimConditions(conditions);
+ if (Arrays.equals(conditions, mConditions)) {
+ final int count = mConditions == null ? 0 : mConditions.length;
+ if (DEBUG) Log.d(mTag, "handleUpdateConditions unchanged conditionCount=" + count);
+ return;
+ }
mConditions = conditions;
handleUpdateConditions();
}
+ private Condition[] trimConditions(Condition[] conditions) {
+ if (conditions == null || conditions.length <= mMaxConditions) {
+ // no need to trim
+ return conditions;
+ }
+ // look for current exit condition, ensure it is included if found
+ int found = -1;
+ for (int i = 0; i < conditions.length; i++) {
+ final Condition c = conditions[i];
+ if (mSessionExitCondition != null && sameConditionId(mSessionExitCondition, c)) {
+ found = i;
+ break;
+ }
+ }
+ final Condition[] rt = Arrays.copyOf(conditions, mMaxConditions);
+ if (found >= mMaxConditions) {
+ // found after the first N, promote to the end of the first N
+ rt[mMaxConditions - 1] = conditions[found];
+ }
+ return rt;
+ }
+
private void handleUpdateConditions() {
final int conditionCount = mConditions == null ? 0 : mConditions.length;
if (DEBUG) Log.d(mTag, "handleUpdateConditions conditionCount=" + conditionCount);
@@ -355,9 +412,10 @@
if (isDowntime(mSessionExitCondition) && !foundDowntime) {
bind(mSessionExitCondition, null);
}
- // ensure something is selected, after waiting for providers to respond
- mHandler.removeMessages(H.SELECT_DEFAULT);
- mHandler.sendEmptyMessageDelayed(H.SELECT_DEFAULT, SELECT_DEFAULT_DELAY);
+ // ensure something is selected
+ if (mExpanded) {
+ ensureSelection();
+ }
}
private static boolean isDowntime(Condition c) {
@@ -368,9 +426,9 @@
return (ConditionTag) mZenConditions.getChildAt(index).getTag();
}
- private void handleSelectDefault() {
- if (!mExpanded) return;
+ private void ensureSelection() {
// are we left without anything selected? if so, set a default
+ if (mZenConditions.getChildCount() == 0) return;
for (int i = 0; i < mZenConditions.getChildCount(); i++) {
if (getConditionTagAt(i).rb.isChecked()) {
if (DEBUG) Log.d(mTag, "Not selecting a default, checked="
@@ -419,7 +477,7 @@
}
tag.condition = condition;
tag.rb.setEnabled(enabled);
- if (mSessionExitCondition != null
+ if ((mSessionExitCondition != null || mAttachedZen != Global.ZEN_MODE_OFF)
&& sameConditionId(mSessionExitCondition, tag.condition)) {
tag.rb.setChecked(true);
}
@@ -623,7 +681,6 @@
private static final int UPDATE_CONDITIONS = 1;
private static final int EXIT_CONDITION_CHANGED = 2;
private static final int UPDATE_ZEN = 3;
- private static final int SELECT_DEFAULT = 4;
private H() {
super(Looper.getMainLooper());
@@ -637,8 +694,6 @@
handleExitConditionChanged((Condition) msg.obj);
} else if (msg.what == UPDATE_ZEN) {
handleUpdateZen(msg.arg1);
- } else if (msg.what == SELECT_DEFAULT) {
- handleSelectDefault();
}
}
}