Improve motion when expanding/collapsing status bar.

- Don't fade the whole panel anymore.
- Parallax effect for QS header translation, fade on keyguard.
- Improve fling curve for dismissing the panel.
- Improve peeking behavior.

Bug: 14804452
Bug: 15407838
Change-Id: I34b7bcd457cb8a037e0bb06e9802ec66d2b39b73
This commit is contained in:
Jorim Jaggi
2014-06-25 03:08:25 +02:00
parent 605f190202
commit 2580a976ec
17 changed files with 292 additions and 154 deletions

View File

@@ -48,28 +48,36 @@
android:orientation="horizontal"
>
<LinearLayout
<com.android.systemui.statusbar.AlphaOptimizedLinearLayout
android:id="@+id/notification_icon_area"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
>
<com.android.systemui.statusbar.StatusBarIconView android:id="@+id/moreIcon"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
android:src="@drawable/stat_notify_more"
android:visibility="gone"
/>
<com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
<!-- The alpha of this area is both controlled from PhoneStatusBarTransitions and
PhoneStatusBar (DISABLE_NOTIFICATION_ICONS), so we need two views here. -->
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/notification_icon_area_inner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:gravity="center_vertical"
android:orientation="horizontal"/>
</LinearLayout>
>
<com.android.systemui.statusbar.StatusBarIconView android:id="@+id/moreIcon"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
android:src="@drawable/stat_notify_more"
android:visibility="gone"
/>
<com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:gravity="center_vertical"
android:orientation="horizontal"/>
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
</com.android.systemui.statusbar.AlphaOptimizedLinearLayout>
<LinearLayout android:id="@+id/system_icon_area"
<com.android.systemui.statusbar.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
@@ -109,7 +117,7 @@
android:paddingStart="6dip"
android:gravity="center_vertical|start"
/>
</LinearLayout>
</com.android.systemui.statusbar.AlphaOptimizedLinearLayout>
</LinearLayout>
<ViewStub

View File

@@ -56,6 +56,12 @@
android:clipToPadding="false"
android:clipChildren="false">
<com.android.systemui.statusbar.stack.NotificationStackScrollLayout
android:id="@+id/notification_stack_scroller"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="@dimen/close_handle_underlap"/>
<com.android.systemui.statusbar.phone.ObservableScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
@@ -82,12 +88,6 @@
</LinearLayout>
</com.android.systemui.statusbar.phone.ObservableScrollView>
<com.android.systemui.statusbar.stack.NotificationStackScrollLayout
android:id="@+id/notification_stack_scroller"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="@dimen/close_handle_underlap"/>
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
<include layout="@layout/status_bar_expanded_header" />

View File

@@ -155,10 +155,6 @@
<!-- The size of the gesture span needed to activate the "pull" notification expansion -->
<dimen name="pull_span_min">25dp</dimen>
<!-- How far to slide the panel out when you touch it -->
<!-- For phones, this is close_handle_height + header_height -->
<dimen name="peek_height">84dp</dimen>
<dimen name="qs_tile_height">88dp</dimen>
<dimen name="qs_tile_icon_size">28dp</dimen>
<dimen name="qs_tile_text_size">12sp</dimen>

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2014 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;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
/**
* A frame layout which does not have overlapping renderings commands and therefore does not need a
* layer when alpha is changed.
*/
public class AlphaOptimizedFrameLayout extends FrameLayout
{
public AlphaOptimizedFrameLayout(Context context) {
super(context);
}
public AlphaOptimizedFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AlphaOptimizedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public AlphaOptimizedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2014 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;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
/**
* A linear layout which does not have overlapping renderings commands and therefore does not need a
* layer when alpha is changed.
*/
public class AlphaOptimizedLinearLayout extends LinearLayout
{
public AlphaOptimizedLinearLayout(Context context) {
super(context);
}
public AlphaOptimizedLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AlphaOptimizedLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public AlphaOptimizedLinearLayout(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
}

View File

@@ -425,7 +425,7 @@ public abstract class BaseStatusBar extends SystemUI implements
createAndAddWindows();
disable(switches[0]);
disable(switches[0], false /* animate */);
setSystemUiVisibility(switches[1], 0xffffffff);
topAppWindowChanged(switches[2] != 0);
// StatusBarManagerService has a back up of IME token and it's restored here.

View File

@@ -19,7 +19,6 @@ package com.android.systemui.statusbar;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.service.notification.StatusBarNotification;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -77,7 +76,7 @@ public class CommandQueue extends IStatusBar.Stub {
public void updateIcon(String slot, int index, int viewIndex,
StatusBarIcon old, StatusBarIcon icon);
public void removeIcon(String slot, int index, int viewIndex);
public void disable(int state);
public void disable(int state, boolean animate);
public void animateExpandNotificationsPanel();
public void animateCollapsePanels(int flags);
public void animateExpandSettingsPanel();
@@ -254,7 +253,7 @@ public class CommandQueue extends IStatusBar.Stub {
break;
}
case MSG_DISABLE:
mCallbacks.disable(msg.arg1);
mCallbacks.disable(msg.arg1, true /* animate */);
break;
case MSG_EXPAND_NOTIFICATIONS:
mCallbacks.animateExpandNotificationsPanel();

View File

@@ -123,6 +123,7 @@ public abstract class ExpandableView extends FrameLayout {
* @param notifyListeners Whether the listener should be informed about the change.
*/
public void setActualHeight(int actualHeight, boolean notifyListeners) {
mActualHeightInitialized = true;
mActualHeight = actualHeight;
if (notifyListeners) {
notifyHeightChanged();
@@ -130,7 +131,6 @@ public abstract class ExpandableView extends FrameLayout {
}
public void setActualHeight(int actualHeight) {
mActualHeightInitialized = true;
setActualHeight(actualHeight, true);
}

View File

@@ -29,8 +29,9 @@ import android.view.animation.PathInterpolator;
public class FlingAnimationUtils {
private static final float LINEAR_OUT_SLOW_IN_X2 = 0.35f;
private static final float LINEAR_OUT_FASTER_IN_Y2_MIN = 0.7f;
private static final float LINEAR_OUT_FASTER_IN_Y2_MAX = 1f;
private static final float LINEAR_OUT_FASTER_IN_X2 = 0.5f;
private static final float LINEAR_OUT_FASTER_IN_Y2_MIN = 0.4f;
private static final float LINEAR_OUT_FASTER_IN_Y2_MAX = 0.5f;
private static final float MIN_VELOCITY_DP_PER_SECOND = 250;
private static final float HIGH_VELOCITY_DP_PER_SECOND = 3000;
@@ -203,9 +204,8 @@ public class FlingAnimationUtils {
float velAbs = Math.abs(velocity);
float y2 = calculateLinearOutFasterInY2(velAbs);
// The gradient at the start of the curve is just y2.
float startGradient = y2;
Interpolator mLinearOutFasterIn = new PathInterpolator(0, 0, 1, y2);
float startGradient = y2 / LINEAR_OUT_FASTER_IN_X2;
Interpolator mLinearOutFasterIn = new PathInterpolator(0, 0, LINEAR_OUT_FASTER_IN_X2, y2);
float durationSeconds = startGradient * diff / velAbs;
if (durationSeconds <= maxLengthSeconds) {
mAnimatorProperties.interpolator = mLinearOutFasterIn;

View File

@@ -237,6 +237,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
return mIndicationText;
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
@Override
public void onMethodSecureChanged(boolean methodSecure) {
updateTrust();

View File

@@ -55,6 +55,7 @@ public class NotificationPanelView extends PanelView implements
private static final int CAP_HEIGHT = 1456;
private static final int FONT_HEIGHT = 2163;
private static final float HEADER_RUBBERBAND_FACTOR = 2.15f;
private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
private KeyguardPageSwipeHelper mPageSwiper;
@@ -97,7 +98,6 @@ public class NotificationPanelView extends PanelView implements
private ValueAnimator mQsExpansionAnimator;
private FlingAnimationUtils mFlingAnimationUtils;
private int mStatusBarMinHeight;
private boolean mHeaderHidden;
private boolean mUnlockIconActive;
private int mNotificationsHeaderCollideDistance;
private int mUnlockMoveDistance;
@@ -207,9 +207,7 @@ public class NotificationPanelView extends PanelView implements
boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
int stackScrollerPadding;
if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
int bottom = mStackScrollerOverscrolling
? mHeader.getCollapsedHeight()
: mHeader.getBottom();
int bottom = mHeader.getCollapsedHeight();
stackScrollerPadding = bottom + mQsPeekHeight
+ mNotificationTopPadding;
mTopPaddingAdjustment = 0;
@@ -562,6 +560,10 @@ public class NotificationPanelView extends PanelView implements
}
public void setKeyguardShowing(boolean keyguardShowing) {
if (!mKeyguardShowing && keyguardShowing) {
setQsTranslation(mQsExpansionHeight);
mHeader.setTranslationY(0f);
}
mKeyguardShowing = keyguardShowing;
updateQsState();
}
@@ -602,10 +604,9 @@ public class NotificationPanelView extends PanelView implements
}
private void setQsTranslation(float height) {
mQsContainer.setY(height - mQsContainer.getHeight());
mQsContainer.setY(height - mQsContainer.getHeight() + getHeaderTranslation());
}
private void requestScrollerTopPaddingUpdate(boolean animate) {
mNotificationStackScroller.updateTopPadding(mQsExpansionHeight,
mScrollView.getScrollY(),
@@ -728,6 +729,11 @@ public class NotificationPanelView extends PanelView implements
@Override
protected int getMaxPanelHeight() {
if (mStatusBar.getBarState() != StatusBarState.KEYGUARD
&& mNotificationStackScroller.getNotGoneChildCount() == 0) {
return (int) ((mQsMinExpansionHeight + getOverExpansionAmount())
* HEADER_RUBBERBAND_FACTOR);
}
// TODO: Figure out transition for collapsing when QS is open, adjust height here.
int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
int maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin
@@ -746,8 +752,22 @@ public class NotificationPanelView extends PanelView implements
positionClockAndNotifications();
}
mNotificationStackScroller.setStackHeight(expandedHeight);
updateKeyguardHeaderVisibility();
updateHeader();
updateUnlockIcon();
updateNotificationTranslucency();
}
private void updateNotificationTranslucency() {
float alpha = (mNotificationStackScroller.getNotificationsTopY()
+ mNotificationStackScroller.getItemHeight())
/ (mQsMinExpansionHeight
+ mNotificationStackScroller.getItemHeight() / 2);
alpha = Math.max(0, Math.min(alpha, 1));
alpha = (float) Math.pow(alpha, 0.75);
// TODO: Draw a rect with DST_OUT over the notifications to achieve the same effect -
// this would be much more efficient.
mNotificationStackScroller.setAlpha(alpha);
}
@Override
@@ -786,51 +806,61 @@ public class NotificationPanelView extends PanelView implements
/**
* Hides the header when notifications are colliding with it.
*/
private void updateKeyguardHeaderVisibility() {
private void updateHeader() {
if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
|| mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
boolean hidden;
if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
// When on Keyguard, we hide the header as soon as the top card of the notification
// stack scroller is close enough (collision distance) to the bottom of the header.
hidden = mNotificationStackScroller.getNotificationsTopY()
<= mHeader.getBottom() + mNotificationsHeaderCollideDistance;
} else {
// In SHADE_LOCKED, the top card is already really close to the header. Hide it as
// soon as we start translating the stack.
hidden = mNotificationStackScroller.getTranslationY() < 0;
}
if (hidden && !mHeaderHidden) {
mHeader.animate()
.alpha(0f)
.withLayer()
.translationY(-mHeader.getHeight()/2)
.setInterpolator(mFastOutLinearInterpolator)
.setDuration(200);
} else if (!hidden && mHeaderHidden) {
mHeader.animate()
.alpha(1f)
.withLayer()
.translationY(0)
.setInterpolator(mLinearOutSlowInInterpolator)
.setDuration(200);
}
mHeaderHidden = hidden;
updateHeaderKeyguard();
} else {
mHeader.animate().cancel();
mHeader.setAlpha(1f);
mHeader.setTranslationY(0f);
if (mHeader.getLayerType() != LAYER_TYPE_NONE) {
mHeader.setLayerType(LAYER_TYPE_NONE, null);
}
mHeaderHidden = false;
updateHeaderShade();
}
}
private void updateHeaderShade() {
mHeader.setAlpha(1f);
mHeader.setTranslationY(getHeaderTranslation());
setQsTranslation(mQsExpansionHeight);
}
private float getHeaderTranslation() {
if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
|| mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
return 0;
}
if (mNotificationStackScroller.getNotGoneChildCount() == 0) {
if (mExpandedHeight / HEADER_RUBBERBAND_FACTOR >= mQsMinExpansionHeight) {
return 0;
} else {
return mExpandedHeight / HEADER_RUBBERBAND_FACTOR - mQsMinExpansionHeight;
}
}
return Math.min(0, mNotificationStackScroller.getTranslationY()) / HEADER_RUBBERBAND_FACTOR;
}
private void updateHeaderKeyguard() {
mHeader.setTranslationY(0f);
float alpha;
if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
// When on Keyguard, we hide the header as soon as the top card of the notification
// stack scroller is close enough (collision distance) to the bottom of the header.
alpha = mNotificationStackScroller.getNotificationsTopY()
/
(mQsMinExpansionHeight + mNotificationsHeaderCollideDistance);
} else {
// In SHADE_LOCKED, the top card is already really close to the header. Hide it as
// soon as we start translating the stack.
alpha = mNotificationStackScroller.getNotificationsTopY() / mQsMinExpansionHeight;
}
alpha = Math.max(0, Math.min(alpha, 1));
alpha = (float) Math.pow(alpha, 0.75);
mHeader.setAlpha(alpha);
mKeyguardBottomArea.setAlpha(alpha);
setQsTranslation(mQsExpansionHeight);
}
@Override
protected void onExpandingStarted() {
super.onExpandingStarted();
@@ -1007,4 +1037,13 @@ public class NotificationPanelView extends PanelView implements
? mKeyguardBottomArea.getPhoneImageView()
: mKeyguardBottomArea.getCameraImageView();
}
@Override
protected float getPeekHeight() {
if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
return mNotificationStackScroller.getPeekHeight();
} else {
return mQsMinExpansionHeight;
}
}
}

View File

@@ -93,15 +93,14 @@ public abstract class PanelView extends FrameLayout {
}
private void runPeekAnimation() {
mPeekHeight = getPeekHeight();
if (DEBUG) logf("peek to height=%.1f", mPeekHeight);
if (mHeightAnimator != null) {
return;
}
if (mPeekAnimator == null) {
mPeekAnimator = ObjectAnimator.ofFloat(this,
"expandedHeight", mPeekHeight)
.setDuration(250);
}
mPeekAnimator = ObjectAnimator.ofFloat(this,
"expandedHeight", mPeekHeight)
.setDuration(250);
mPeekAnimator.start();
}
@@ -115,9 +114,6 @@ public abstract class PanelView extends FrameLayout {
protected void loadDimens() {
final Resources res = getContext().getResources();
mPeekHeight = res.getDimension(R.dimen.peek_height)
+ getPaddingBottom(); // our window might have a dropshadow
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mHintDistance = res.getDimension(R.dimen.hint_move_distance);
@@ -758,4 +754,6 @@ public abstract class PanelView extends FrameLayout {
}
public abstract void resetViews();
protected abstract float getPeekHeight();
}

View File

@@ -31,6 +31,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
@@ -221,6 +222,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
LinearLayout mStatusIcons;
// the icons themselves
IconMerger mNotificationIcons;
View mNotificationIconArea;
// [+>
View mMoreIcon;
@@ -300,16 +303,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
: null;
private int mNavigationIconHints = 0;
private final Animator.AnimatorListener mMakeIconsInvisible = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// double-check to avoid races
if (mStatusBarContents.getAlpha() == 0) {
if (DEBUG) Log.d(TAG, "makeIconsInvisible");
mStatusBarContents.setVisibility(View.INVISIBLE);
}
}
};
// ensure quick settings is disabled until the current user makes it through the setup wizard
private boolean mUserSetup = false;
@@ -383,8 +376,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private boolean mDozing;
private Interpolator mLinearOutSlowIn;
private Interpolator mAlphaOut = new PathInterpolator(0f, 0.4f, 1f, 1f);
private Interpolator mAlphaIn = new PathInterpolator(0f, 0f, 0.8f, 1f);
private Interpolator mAlphaIn = new PathInterpolator(0f, 0.2f, 1f, 1f);
private Interpolator mAlphaOut = new PathInterpolator(0f, 0f, 0.8f, 1f);
private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
new OnChildLocationsChangedListener() {
@@ -608,6 +601,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);
mSystemIcons = (LinearLayout) mStatusBarView.findViewById(R.id.system_icons);
mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
mNotificationIconArea = mStatusBarView.findViewById(R.id.notification_icon_area_inner);
mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
@@ -1423,7 +1417,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
/**
* State is one or more of the DISABLE constants from StatusBarManager.
*/
public void disable(int state) {
public void disable(int state, boolean animate) {
mDisabledUnmodified = state;
state = adjustDisableFlags(state);
final int old = mDisabled;
@@ -1461,9 +1455,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
mSystemIconArea.animate().cancel();
if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
animateStatusBarHide(mSystemIconArea);
animateStatusBarHide(mSystemIconArea, animate);
} else {
animateStatusBarShow(mSystemIconArea);
animateStatusBarShow(mSystemIconArea, animate);
}
}
@@ -1496,9 +1490,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mTicking) {
haltTicker();
}
animateStatusBarHide(mNotificationIcons);
animateStatusBarHide(mNotificationIconArea, animate);
} else {
animateStatusBarShow(mNotificationIcons);
animateStatusBarShow(mNotificationIconArea, animate);
}
}
}
@@ -1506,35 +1500,49 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
/**
* Animates {@code v}, a view that is part of the status bar, out.
*/
private void animateStatusBarHide(View v) {
private void animateStatusBarHide(final View v, boolean animate) {
v.animate().cancel();
if (!animate) {
v.setAlpha(0f);
v.setVisibility(View.INVISIBLE);
return;
}
v.animate()
.alpha(0f)
.withLayer()
.setDuration(160)
.setInterpolator(mAlphaIn)
.setStartDelay(0)
.setListener(mMakeIconsInvisible)
.start();
.setInterpolator(mAlphaOut)
.withEndAction(new Runnable() {
@Override
public void run() {
v.setVisibility(View.INVISIBLE);
}
});
}
/**
* Animates {@code v}, a view that is part of the status bar, in.
*/
private void animateStatusBarShow(View v) {
private void animateStatusBarShow(View v, boolean animate) {
v.animate().cancel();
v.setVisibility(View.VISIBLE);
if (!animate) {
v.setAlpha(1f);
return;
}
v.animate()
.alpha(1f)
.withLayer()
.setInterpolator(mAlphaOut)
.setDuration(320)
.setStartDelay(0);
.setInterpolator(mAlphaIn)
.setStartDelay(50);
// Synchronize the motion with the Keyguard fading if necessary.
if (mKeyguardFadingAway) {
v.animate()
.setDuration(mKeyguardFadingAwayDuration)
.setInterpolator(mLinearOutSlowIn)
.setStartDelay(mKeyguardFadingAwayDelay);
.setStartDelay(mKeyguardFadingAwayDelay)
.start();
}
}
@@ -1636,7 +1644,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
visibilityChanged(true);
mWaitingForKeyguardExit = false;
disable(mDisabledUnmodified);
disable(mDisabledUnmodified, !force /* animate */);
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
}
@@ -1810,10 +1818,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// Shrink the window to the size of the status bar only
mStatusBarWindowManager.setStatusBarExpanded(false);
if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
}
// Close any "App info" popups that might have snuck on-screen
dismissPopups();
@@ -1824,7 +1828,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
showBouncer();
disable(mDisabledUnmodified);
disable(mDisabledUnmodified, true /* animate */);
}
public boolean interceptTouchEvent(MotionEvent event) {
@@ -2337,15 +2341,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
void setNotificationIconVisibility(boolean visible, int anim) {
int old = mNotificationIcons.getVisibility();
int v = visible ? View.VISIBLE : View.INVISIBLE;
if (old != v) {
mNotificationIcons.setVisibility(v);
mNotificationIcons.startAnimation(loadAnim(anim, null));
}
}
static final float saturate(float a) {
return a < 0f ? 0f : (a > 1f ? 1f : a);
}
@@ -2835,7 +2830,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
mWaitingForKeyguardExit = false;
disable(mDisabledUnmodified);
disable(mDisabledUnmodified, true /* animate */);
}
/**
@@ -3093,7 +3088,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void setBouncerShowing(boolean bouncerShowing) {
super.setBouncerShowing(bouncerShowing);
disable(mDisabledUnmodified);
disable(mDisabledUnmodified, true /* animate */);
}
public void onScreenTurnedOff() {

View File

@@ -111,7 +111,14 @@ public class PhoneStatusBarView extends PanelBar {
@Override
public void onAllPanelsCollapsed() {
super.onAllPanelsCollapsed();
mBar.makeExpandedInvisible();
// Close the status bar in the next frame so we can show the end of the animation.
postOnAnimation(new Runnable() {
@Override
public void run() {
mBar.makeExpandedInvisible();
}
});
mLastFullyOpenedPanel = null;
}
@@ -166,27 +173,7 @@ public class PhoneStatusBarView extends PanelBar {
@Override
public void panelExpansionChanged(PanelView panel, float frac) {
super.panelExpansionChanged(panel, frac);
if (DEBUG) {
Log.v(TAG, "panelExpansionChanged: f=" + frac);
}
mScrimController.setPanelExpansion(frac);
// fade out the panel as it gets buried into the status bar to avoid overdrawing the
// status bar on the last frame of a close animation
final int H = mBar.getStatusBarHeight();
final float ph = panel.getExpandedHeight() + panel.getPaddingBottom();
float alpha = 1f;
if (ph < 2*H) {
if (ph < H) alpha = 0f;
else alpha = (ph - H) / H;
alpha = alpha * alpha; // get there faster
}
if (panel.getAlpha() != alpha) {
panel.setAlpha(alpha);
}
mBar.updateCarrierLabelVisibility(false);
mBar.userActivity();
}

View File

@@ -405,4 +405,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
updateVisibilities();
updateSystemIconsLayoutParams();
}
@Override
public boolean hasOverlappingRendering() {
return !mKeyguardShowing || mExpanded;
}
}

View File

@@ -420,7 +420,7 @@ public class NotificationStackScrollLayout extends ViewGroup
int bottomStackPeekSize = mBottomStackPeekSize;
int minStackHeight = itemHeight + bottomStackPeekSize;
int stackHeight;
if (newStackHeight - mTopPadding >= minStackHeight) {
if (newStackHeight - mTopPadding >= minStackHeight || getNotGoneChildCount() == 0) {
setTranslationY(0);
stackHeight = newStackHeight;
} else {
@@ -1266,6 +1266,10 @@ public class NotificationStackScrollLayout extends ViewGroup
setTopPadding(clampPadding((int) start), animate);
}
public int getPeekHeight() {
return mIntrinsicPadding + mCollapsedSize + mBottomStackPeekSize;
}
private int clampPadding(int desiredPadding) {
return Math.max(desiredPadding, mIntrinsicPadding);
}

View File

@@ -59,7 +59,7 @@ public class TvStatusBar extends BaseStatusBar {
}
@Override
public void disable(int state) {
public void disable(int state, boolean animate) {
}
@Override