am b77edbfd: Improve transparent bar transitions.

* commit 'b77edbfdab54531023c8bbea7d89b6cefc42096c':
  Improve transparent bar transitions.
This commit is contained in:
John Spurlock
2013-08-23 05:24:28 -07:00
committed by Android Git Automerger
8 changed files with 136 additions and 25 deletions

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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));
}

View File

@@ -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;
}

View File

@@ -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));
}
}
}
}

View File

@@ -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));
}

View File

@@ -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);
}