Improve transparent bar transitions.
1. Migrate transparent transitions to the new optimized background color animations. 2. Ensure sysui animation transparent -> opaque has enough time to run before window manager crops off the content area. 3. Lose the individual alpha on each status bar icon if the bars are not opaque. Animate the alpha if visible, make sure they play together. 4. Documentation typo fix found in AnimatorSet. Bug:10344949 Change-Id: I615668ce3c552d3df15dbba5cdeeca67549a0220
This commit is contained in:
@ -114,7 +114,7 @@ public class AnimationSet extends Animation {
|
||||
* Constructor to use when building an AnimationSet from code
|
||||
*
|
||||
* @param shareInterpolator Pass true if all of the animations in this set
|
||||
* should use the interpolator assocciated with this AnimationSet.
|
||||
* should use the interpolator associated with this AnimationSet.
|
||||
* Pass false if each animation should use its own interpolator.
|
||||
*/
|
||||
public AnimationSet(boolean shareInterpolator) {
|
||||
|
@ -70,6 +70,7 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.RecentsComponent;
|
||||
import com.android.systemui.SearchPanelView;
|
||||
import com.android.systemui.SystemUI;
|
||||
import com.android.systemui.statusbar.phone.BarTransitions;
|
||||
import com.android.systemui.statusbar.policy.NotificationRowLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -827,7 +828,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
// Construct the icon.
|
||||
final StatusBarIconView iconView = new StatusBarIconView(mContext,
|
||||
notification.getPackageName() + "/0x" + Integer.toHexString(notification.getId()),
|
||||
notification.getNotification());
|
||||
notification.getNotification(), getStatusBarMode());
|
||||
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
|
||||
|
||||
final StatusBarIcon ic = new StatusBarIcon(notification.getPackageName(),
|
||||
@ -850,6 +851,10 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
return entry;
|
||||
}
|
||||
|
||||
protected int getStatusBarMode() {
|
||||
return BarTransitions.MODE_OPAQUE;
|
||||
}
|
||||
|
||||
protected void addNotificationViews(NotificationData.Entry entry) {
|
||||
// Add the expanded view and icon.
|
||||
int pos = mNotificationData.add(entry);
|
||||
|
@ -16,6 +16,11 @@
|
||||
|
||||
package com.android.systemui.statusbar;
|
||||
|
||||
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
|
||||
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
|
||||
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
@ -48,10 +53,13 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
private int mNumberY;
|
||||
private String mNumberText;
|
||||
private Notification mNotification;
|
||||
private final float mAlphaWhenOpaque;
|
||||
private final float mAlphaWhenTransparent = 1;
|
||||
|
||||
public StatusBarIconView(Context context, String slot, Notification notification) {
|
||||
public StatusBarIconView(Context context, String slot, Notification notification, int mode) {
|
||||
super(context);
|
||||
final Resources res = context.getResources();
|
||||
mAlphaWhenOpaque = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
|
||||
mSlot = slot;
|
||||
mNumberPain = new Paint();
|
||||
mNumberPain.setTextAlign(Paint.Align.CENTER);
|
||||
@ -68,8 +76,7 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
final float scale = (float)imageBounds / (float)outerBounds;
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
|
||||
setAlpha(alpha);
|
||||
setAlpha(getAlphaFor(mode));
|
||||
}
|
||||
|
||||
setScaleType(ImageView.ScaleType.CENTER);
|
||||
@ -78,13 +85,22 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
public StatusBarIconView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
final Resources res = context.getResources();
|
||||
mAlphaWhenOpaque = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
|
||||
final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
|
||||
final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
|
||||
final float scale = (float)imageBounds / (float)outerBounds;
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
|
||||
setAlpha(alpha);
|
||||
setAlpha(getAlphaFor(MODE_OPAQUE));
|
||||
}
|
||||
|
||||
public ObjectAnimator animateTransitionTo(int mode) {
|
||||
return ObjectAnimator.ofFloat(this, "alpha", getAlpha(), getAlphaFor(mode));
|
||||
}
|
||||
|
||||
public float getAlphaFor(int mode) {
|
||||
final boolean isTransparent = mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSPARENT;
|
||||
return isTransparent ? mAlphaWhenTransparent : mAlphaWhenOpaque;
|
||||
}
|
||||
|
||||
private static boolean streq(String a, String b) {
|
||||
|
@ -60,6 +60,10 @@ public class BarTransitions {
|
||||
mSemiTransparent = res.getColor(R.color.status_bar_background_semi_transparent);
|
||||
}
|
||||
|
||||
public int getMode() {
|
||||
return mMode;
|
||||
}
|
||||
|
||||
public void setTransparent(Drawable transparent) {
|
||||
mTransparent = transparent;
|
||||
if (mMode == MODE_TRANSPARENT) {
|
||||
@ -80,16 +84,24 @@ public class BarTransitions {
|
||||
onTransition(oldMode, mMode, animate);
|
||||
}
|
||||
|
||||
protected Integer getBackgroundColor(int mode) {
|
||||
if (mode == MODE_SEMI_TRANSPARENT) return mSemiTransparent;
|
||||
if (mode == MODE_OPAQUE) return mOpaque;
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void onTransition(int oldMode, int newMode, boolean animate) {
|
||||
cancelBackgroundColorAnimation();
|
||||
if (animate && oldMode == MODE_SEMI_TRANSPARENT && newMode == MODE_OPAQUE) {
|
||||
startBackgroundColorAnimation(mSemiTransparent, mOpaque);
|
||||
} else if (animate && oldMode == MODE_OPAQUE && newMode == MODE_SEMI_TRANSPARENT) {
|
||||
startBackgroundColorAnimation(mOpaque, mSemiTransparent);
|
||||
} else if (newMode == MODE_OPAQUE || newMode == MODE_SEMI_TRANSPARENT) {
|
||||
mTarget.setBackgroundColor(newMode == MODE_OPAQUE ? mOpaque : mSemiTransparent);
|
||||
Integer oldColor = getBackgroundColor(oldMode);
|
||||
Integer newColor = getBackgroundColor(newMode);
|
||||
if (oldColor != null && newColor != null) {
|
||||
if (animate) {
|
||||
startBackgroundColorAnimation(oldColor, newColor);
|
||||
} else {
|
||||
mTarget.setBackgroundColor(newColor);
|
||||
}
|
||||
} else {
|
||||
mTarget.setBackground(newMode == MODE_TRANSPARENT? mTransparent
|
||||
mTarget.setBackground(newMode == MODE_TRANSPARENT ? mTransparent
|
||||
: newMode == MODE_SEMI_TRANSPARENT ? new ColorDrawable(mSemiTransparent)
|
||||
: new ColorDrawable(mOpaque));
|
||||
}
|
||||
|
@ -843,7 +843,7 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
|
||||
if (SPEW) Log.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
|
||||
+ " icon=" + icon);
|
||||
StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
|
||||
StatusBarIconView view = new StatusBarIconView(mContext, slot, null, getStatusBarMode());
|
||||
view.set(icon);
|
||||
mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
|
||||
}
|
||||
@ -1921,6 +1921,11 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getStatusBarMode() {
|
||||
return mStatusBarView.getBarTransitions().getMode();
|
||||
}
|
||||
|
||||
private int updateBarMode(int oldVis, int newVis, BarTransitions transitions,
|
||||
int transientFlag, int transparentFlag, int windowState) {
|
||||
final int oldMode = barMode(oldVis, transientFlag, transparentFlag);
|
||||
@ -1928,8 +1933,7 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
if (oldMode == newMode) {
|
||||
return -1; // no mode change
|
||||
}
|
||||
boolean animate = windowState == StatusBarManager.WINDOW_STATE_SHOWING
|
||||
&& oldMode == MODE_SEMI_TRANSPARENT && newMode == MODE_OPAQUE;
|
||||
final boolean animate = windowState == StatusBarManager.WINDOW_STATE_SHOWING;
|
||||
transitions.transitionTo(newMode, animate);
|
||||
return newMode;
|
||||
}
|
||||
|
@ -16,20 +16,26 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.NotFoundException;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.android.systemui.EventLogTags;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.StatusBarIconView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PhoneStatusBarView extends PanelBar {
|
||||
private static final String TAG = "PhoneStatusBarView";
|
||||
@ -49,10 +55,56 @@ public class PhoneStatusBarView extends PanelBar {
|
||||
private final StatusBarTransitions mBarTransitions;
|
||||
|
||||
private final class StatusBarTransitions extends BarTransitions {
|
||||
private final int mTransparent;
|
||||
|
||||
public StatusBarTransitions(Context context) {
|
||||
super(context, PhoneStatusBarView.this);
|
||||
final Resources res = context.getResources();
|
||||
mTransparent = res.getDrawable(R.color.status_bar_background_transparent);
|
||||
mTransparent = res.getColor(R.color.status_bar_background_transparent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer getBackgroundColor(int mode) {
|
||||
if (mode == MODE_TRANSPARENT) return mTransparent;
|
||||
return super.getBackgroundColor(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransition(int oldMode, int newMode, boolean animate) {
|
||||
super.onTransition(oldMode, newMode, animate);
|
||||
if (animate) {
|
||||
List<Animator> animators = new ArrayList<Animator>();
|
||||
for(StatusBarIconView icon : findStatusBarIcons()) {
|
||||
animators.add(icon.animateTransitionTo(newMode));
|
||||
}
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.playTogether(animators);
|
||||
set.start();
|
||||
} else {
|
||||
for(StatusBarIconView icon : findStatusBarIcons()) {
|
||||
icon.setAlpha(icon.getAlphaFor(newMode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<StatusBarIconView> findStatusBarIcons() {
|
||||
List<StatusBarIconView> icons = new ArrayList<StatusBarIconView>();
|
||||
findStatusBarIcons(icons, findViewById(R.id.moreIcon));
|
||||
findStatusBarIcons(icons, findViewById(R.id.statusIcons));
|
||||
findStatusBarIcons(icons, findViewById(R.id.notificationIcons));
|
||||
return icons;
|
||||
}
|
||||
|
||||
private void findStatusBarIcons(List<StatusBarIconView> icons, View v) {
|
||||
if (v instanceof StatusBarIconView) {
|
||||
icons.add((StatusBarIconView) v);
|
||||
} else if (v instanceof ViewGroup) {
|
||||
ViewGroup group = (ViewGroup) v;
|
||||
final int N = group.getChildCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
findStatusBarIcons(icons, group.getChildAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import android.app.StatusBarManager;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Slog;
|
||||
import android.view.View;
|
||||
import android.view.WindowManagerPolicy.WindowState;
|
||||
@ -38,9 +39,12 @@ public class BarController {
|
||||
private static final int TRANSIENT_BAR_SHOWING = 1;
|
||||
private static final int TRANSIENT_BAR_HIDING = 2;
|
||||
|
||||
private static final int TRANSPARENT_ANIMATION_DELAY_MS = 1000;
|
||||
|
||||
private final String mTag;
|
||||
private final int mTransientFlag;
|
||||
private final int mUnhideFlag;
|
||||
private final int mTransparentFlag;
|
||||
private final int mStatusBarManagerId;
|
||||
private final Handler mHandler;
|
||||
private final Object mServiceAquireLock = new Object();
|
||||
@ -50,11 +54,14 @@ public class BarController {
|
||||
private int mState;
|
||||
private int mTransientBarState;
|
||||
private boolean mPendingShow;
|
||||
private long mLastTransparent;
|
||||
|
||||
public BarController(String tag, int transientFlag, int unhideFlag, int statusBarManagerId) {
|
||||
public BarController(String tag, int transientFlag, int unhideFlag, int transparentFlag,
|
||||
int statusBarManagerId) {
|
||||
mTag = "BarController." + tag;
|
||||
mTransientFlag = transientFlag;
|
||||
mUnhideFlag = unhideFlag;
|
||||
mTransparentFlag = transparentFlag;
|
||||
mStatusBarManagerId = statusBarManagerId;
|
||||
mHandler = new Handler();
|
||||
}
|
||||
@ -77,6 +84,10 @@ public class BarController {
|
||||
return mTransientBarState == TRANSIENT_BAR_SHOWING;
|
||||
}
|
||||
|
||||
public boolean wasRecentlyTransparent() {
|
||||
return (SystemClock.uptimeMillis() - mLastTransparent) < TRANSPARENT_ANIMATION_DELAY_MS;
|
||||
}
|
||||
|
||||
public void adjustSystemUiVisibilityLw(int oldVis, int vis) {
|
||||
if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING &&
|
||||
(vis & mTransientFlag) == 0) {
|
||||
@ -181,11 +192,17 @@ public class BarController {
|
||||
vis |= mTransientFlag; // ignore clear requests until transition completes
|
||||
vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; // never show transient bars in low profile
|
||||
}
|
||||
if ((vis & mTransparentFlag) != 0 || (oldVis & mTransparentFlag) != 0) {
|
||||
mLastTransparent = SystemClock.uptimeMillis();
|
||||
}
|
||||
return vis;
|
||||
}
|
||||
|
||||
private void setTransientBarState(int state) {
|
||||
if (mWin != null && state != mTransientBarState) {
|
||||
if (mTransientBarState == TRANSIENT_BAR_SHOWING || state == TRANSIENT_BAR_SHOWING) {
|
||||
mLastTransparent = SystemClock.uptimeMillis();
|
||||
}
|
||||
mTransientBarState = state;
|
||||
if (DEBUG) Slog.d(mTag, "New state: " + transientBarStateToString(state));
|
||||
}
|
||||
|
@ -556,11 +556,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
private final BarController mStatusBarController = new BarController("StatusBar",
|
||||
View.STATUS_BAR_TRANSIENT,
|
||||
View.STATUS_BAR_UNHIDE,
|
||||
View.SYSTEM_UI_FLAG_TRANSPARENT_STATUS,
|
||||
StatusBarManager.WINDOW_STATUS_BAR);
|
||||
|
||||
private final BarController mNavigationBarController = new BarController("NavigationBar",
|
||||
View.NAVIGATION_BAR_TRANSIENT,
|
||||
View.NAVIGATION_BAR_UNHIDE,
|
||||
View.SYSTEM_UI_FLAG_TRANSPARENT_NAVIGATION,
|
||||
StatusBarManager.WINDOW_NAVIGATION_BAR);
|
||||
|
||||
private TransientNavigationConfirmation mTransientNavigationConfirmation;
|
||||
@ -2739,7 +2741,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
// We currently want to hide the navigation UI.
|
||||
mNavigationBarController.setBarShowingLw(false);
|
||||
}
|
||||
if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()) {
|
||||
if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()
|
||||
&& !mNavigationBarController.wasRecentlyTransparent()) {
|
||||
// If the opaque nav bar is currently requested to be visible,
|
||||
// and not in the process of animating on or off, then
|
||||
// we can tell the app that it is covered by it.
|
||||
@ -2762,7 +2765,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
// We currently want to hide the navigation UI.
|
||||
mNavigationBarController.setBarShowingLw(false);
|
||||
}
|
||||
if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()) {
|
||||
if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()
|
||||
&& !mNavigationBarController.wasRecentlyTransparent()) {
|
||||
// If the nav bar is currently requested to be visible,
|
||||
// and not in the process of animating on or off, then
|
||||
// we can tell the app that it is covered by it.
|
||||
@ -2832,7 +2836,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
mCurLeft, mCurTop, mCurRight, mCurBottom));
|
||||
}
|
||||
if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
|
||||
&& !statusBarTransient && !statusBarTransparent) {
|
||||
&& !statusBarTransient && !statusBarTransparent
|
||||
&& !mStatusBarController.wasRecentlyTransparent()) {
|
||||
// If the opaque status bar is currently requested to be visible,
|
||||
// and not in the process of animating on or off, then
|
||||
// we can tell the app that it is covered by it.
|
||||
@ -5011,7 +5016,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
if (mForcingShowNavBar && mFocusedWindow.getSurfaceLayer() < mForcingShowNavBarLayer) {
|
||||
tmpVisibility &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
|
||||
}
|
||||
final int visibility = updateTransientBarsLw(mLastSystemUiFlags, tmpVisibility);
|
||||
final int visibility = updateSystemBarsLw(mLastSystemUiFlags, tmpVisibility);
|
||||
final int diff = visibility ^ mLastSystemUiFlags;
|
||||
final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
|
||||
if (diff == 0 && mLastFocusNeedsMenu == needsMenu
|
||||
@ -5039,7 +5044,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
return diff;
|
||||
}
|
||||
|
||||
private int updateTransientBarsLw(int oldVis, int vis) {
|
||||
private int updateSystemBarsLw(int oldVis, int vis) {
|
||||
if (ImmersiveModeTesting.enabled) {
|
||||
vis = ImmersiveModeTesting.applyForced(mFocusedWindow, vis);
|
||||
}
|
||||
|
Reference in New Issue
Block a user