Add visual feedback for notification expandability.

Change-Id: I0b82a465a126a6d0ec6cf6af87dc56817765b995
This commit is contained in:
Chris Wren
2012-04-18 10:52:18 -04:00
parent cd3e6e2264
commit 80a76276dc
10 changed files with 110 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -4,6 +4,15 @@
android:background="@*android:drawable/notification_bg"
>
<View
android:id="@+id/top_glow"
android:alpha="0"
android:layout_width="match_parent"
android:layout_height="@dimen/notification_divider_height"
android:layout_gravity="top|center_horizontal"
android:background="@drawable/top_divider_glow"
/>
<Button
android:id="@+id/veto"
android:layout_width="48dp"
@@ -19,6 +28,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/notification_divider_height"
android:layout_marginTop="@dimen/notification_divider_height"
android:focusable="true"
android:clickable="true"
>
@@ -31,10 +41,12 @@
</com.android.systemui.statusbar.LatestItemView>
<View
android:id="@+id/bottom_glow"
android:alpha="0"
android:layout_width="match_parent"
android:layout_height="@dimen/notification_divider_height"
android:gravity="bottom"
android:background="@*android:drawable/notification_bg"
android:layout_gravity="bottom|center_horizontal"
android:background="@drawable/bottom_divider_glow"
/>
</FrameLayout>

View File

@@ -18,9 +18,9 @@
<resources>
<!-- thickness (height) of each notification row, including any separators or padding -->
<!-- Note: this is 64dip + 1px divider = 97px. -->
<dimen name="notification_height">97px</dimen>
<dimen name="notification_height">99px</dimen>
<!-- thickness (height) of dividers between each notification row; see math for
notification_height above -->
<dimen name="notification_divider_height">1px</dimen>
<dimen name="notification_divider_height">4px</dimen>
</resources>

View File

@@ -19,9 +19,9 @@
<!-- thickness (height) of each notification row, including any separators or padding -->
<!-- note: this is the same value as in values/dimens.xml; the value is overridden in
values-hdpi/dimens.xml and so we need to re-assert the general value here -->
<dimen name="notification_height">65dp</dimen>
<dimen name="notification_height">68dp</dimen>
<!-- thickness (height) of dividers between each notification row -->
<!-- same as in values/dimens.xml; see note at notification_height -->
<dimen name="notification_divider_height">1dp</dimen>
<dimen name="notification_divider_height">2dp</dimen>
</resources>

View File

@@ -50,7 +50,7 @@
<dimen name="navigation_bar_deadzone_size">12dp</dimen>
<!-- thickness (height) of each notification row, including any separators or padding -->
<dimen name="notification_height">65dp</dimen>
<dimen name="notification_height">68dp</dimen>
<!-- Height of notification icons in the status bar -->
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
@@ -72,7 +72,7 @@
<dimen name="status_bar_icon_padding">0dp</dimen>
<!-- thickness (height) of dividers between each notification row -->
<dimen name="notification_divider_height">1dp</dimen>
<dimen name="notification_divider_height">4dp</dimen>
<!-- Notification drawer tuning parameters (phone UI) -->
<!-- Initial velocity of the shade when expanding on its own -->

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012 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.
-->
<resources>
<item type="id" name="expandable_tag" />
</resources>

View File

@@ -32,17 +32,28 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
public interface Callback {
View getChildAtPosition(MotionEvent ev);
View getChildAtPosition(float x, float y);
boolean canChildBeExpanded(View v);
}
private static final String TAG = "ExpandHelper";
protected static final boolean DEBUG = false;
private static final long EXPAND_DURATION = 250;
// amount of overstretch for maximum brightness expressed in U
// 2f: maximum brightness is stretching a 1U to 3U, or a 4U to 6U
private static final float STRETCH_INTERVAL = 2f;
// level of glow for a touch, without overstretch
// overstretch fills the range (GLOW_BASE, 1.0]
private static final float GLOW_BASE = 0.5f;
@SuppressWarnings("unused")
private Context mContext;
private boolean mStretching;
private View mCurrView;
private View mCurrViewTopGlow;
private View mCurrViewBottomGlow;
private float mOldHeight;
private float mNaturalHeight;
private float mInitialTouchSpan;
@@ -53,7 +64,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
private int mSmallSize;
private int mLargeSize;
private float mMaximumStretch;
private class ViewScaler {
View mView;
@@ -62,7 +73,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
mView = v;
}
public void setHeight(float h) {
Log.v(TAG, "SetHeight: setting to " + h);
if (DEBUG) Log.v(TAG, "SetHeight: setting to " + h);
ViewGroup.LayoutParams lp = mView.getLayoutParams();
lp.height = (int)h;
mView.setLayoutParams(lp);
@@ -94,6 +105,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
public ExpandHelper(Context context, Callback callback, int small, int large) {
mSmallSize = small;
mMaximumStretch = mSmallSize * STRETCH_INTERVAL;
mLargeSize = large;
mContext = context;
mCallback = callback;
@@ -120,10 +132,16 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
float h = Math.abs(detector.getCurrentSpanY());
if (DEBUG) Log.d(TAG, "current span is: " + h);
h = h + mOldHeight - mInitialTouchSpan;
float target = h;
if (DEBUG) Log.d(TAG, "target is: " + target);
h = h<mSmallSize?mSmallSize:(h>mLargeSize?mLargeSize:h);
h = h>mNaturalHeight?mNaturalHeight:h;
if (DEBUG) Log.d(TAG, "scale continues: h=" + h);
mScaler.setHeight(h);
float stretch = (float) Math.abs((target - h) / mMaximumStretch);
float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
if (DEBUG) Log.d(TAG, "stretch: " + stretch + " strength: " + strength);
setGlow(GLOW_BASE + strength * (1f - GLOW_BASE));
return true;
}
@@ -136,6 +154,14 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
}
});
}
public void setGlow(float glow) {
if (mCurrViewTopGlow != null) {
mCurrViewTopGlow.setAlpha(glow);
}
if (mCurrViewBottomGlow != null) {
mCurrViewBottomGlow.setAlpha(glow);
}
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (DEBUG) Log.d(TAG, "interceptTouch: act=" + (ev.getAction()) +
@@ -154,7 +180,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mStretching = false;
mCurrView = null;
clearView();
break;
}
return true;
@@ -163,14 +189,20 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
if (v != null) {
if (DEBUG) Log.d(TAG, "scale begins on view: " + v);
mStretching = true;
mCurrView = v;
setView(v);
setGlow(GLOW_BASE);
mScaler.setView(v);
mOldHeight = mScaler.getHeight();
mNaturalHeight = mScaler.getNaturalHeight(mLargeSize);
if (mCallback.canChildBeExpanded(v)) {
if (DEBUG) Log.d(TAG, "working on an expandable child");
mNaturalHeight = mScaler.getNaturalHeight(mLargeSize);
} else {
if (DEBUG) Log.d(TAG, "working on a non-expandable child");
mNaturalHeight = mOldHeight;
}
if (DEBUG) Log.d(TAG, "got mOldHeight: " + mOldHeight +
" mNaturalHeight: " + mNaturalHeight);
v.getParent().requestDisallowInterceptTouchEvent(true);
if (DEBUG) v.setBackgroundColor(0xFFFFFF00);
}
return mStretching;
}
@@ -183,11 +215,33 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
} else {
h = (force || h < mNaturalHeight) ? mSmallSize : mNaturalHeight;
}
if (DEBUG) mCurrView.setBackgroundColor(0);
if (DEBUG && mCurrView != null) mCurrView.setBackgroundColor(0);
mAnimation = ObjectAnimator.ofFloat(mScaler, "height", h).setDuration(EXPAND_DURATION);
mAnimation.start();
mStretching = false;
setGlow(0f);
clearView();
}
private void clearView() {
mCurrView = null;
mCurrViewTopGlow = null;
mCurrViewBottomGlow = null;
}
private void setView(View v) {
mCurrView = null;
if (v instanceof ViewGroup) {
ViewGroup g = (ViewGroup) v;
mCurrViewTopGlow = g.findViewById(R.id.top_glow);
mCurrViewBottomGlow = g.findViewById(R.id.bottom_glow);
if (DEBUG) {
String debugLog = "Looking for glows: " +
(mCurrViewTopGlow != null ? "found top " : "didn't find top") +
(mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom");
Log.v(TAG, debugLog);
}
}
}
@Override

View File

@@ -397,12 +397,15 @@ public abstract class BaseStatusBar extends SystemUI implements
// XXX: temporary: while testing big notifications, auto-expand all of them
ViewGroup.LayoutParams lp = row.getLayoutParams();
Boolean expandable = Boolean.FALSE;
if (large != null) {
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
expandable = Boolean.TRUE;
} else {
lp.height = minHeight;
}
row.setLayoutParams(lp);
row.setTag(R.id.expandable_tag, expandable);
workAroundBadLayerDrawableOpacity(row);
View vetoButton = updateNotificationVetoButton(row, sbn);
vetoButton.setContentDescription(mContext.getString(

View File

@@ -165,6 +165,12 @@ public class NotificationRowLayout
return (veto != null && veto.getVisibility() != View.GONE);
}
public boolean canChildBeExpanded(View v) {
Object isExpandable = v.getTag(R.id.expandable_tag);
return isExpandable != null && isExpandable instanceof Boolean &&
((Boolean)isExpandable).booleanValue();
}
public void onChildDismissed(View v) {
final View veto = v.findViewById(R.id.veto);
if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {