Skip to content

Commit 64dbcd6

Browse files
mikejurkaAndroid (Google) Code Review
authored andcommitted
Merge "Tweak recents out animation a bit more" into jb-dev
2 parents 519e91e + c016aaa commit 64dbcd6

File tree

8 files changed

+115
-38
lines changed

8 files changed

+115
-38
lines changed

packages/SystemUI/res/layout-land/status_bar_recent_panel.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@
2626
android:layout_width="match_parent"
2727
systemui:recentItemLayout="@layout/status_bar_recent_item"
2828
>
29-
29+
<View
30+
android:id="@+id/recents_transition_background"
31+
android:layout_height="match_parent"
32+
android:layout_width="match_parent"
33+
android:visibility="invisible" />
3034
<FrameLayout
3135
android:id="@+id/recents_bg_protect"
3236
android:background="@drawable/status_bar_recents_background"

packages/SystemUI/res/layout-port/status_bar_recent_panel.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@
2626
android:layout_width="match_parent"
2727
systemui:recentItemLayout="@layout/status_bar_recent_item"
2828
>
29-
29+
<View
30+
android:id="@+id/recents_transition_background"
31+
android:layout_height="match_parent"
32+
android:layout_width="match_parent"
33+
android:visibility="invisible" />
3034
<FrameLayout
3135
android:id="@+id/recents_bg_protect"
3236
android:background="@drawable/status_bar_recents_background"

packages/SystemUI/res/layout/system_bar_recent_panel.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
android:clipChildren="false"
2929
systemui:recentItemLayout="@layout/system_bar_recent_item"
3030
>
31-
31+
<View
32+
android:id="@+id/recents_transition_background"
33+
android:layout_height="match_parent"
34+
android:layout_width="match_parent"
35+
android:visibility="invisible" />
3236
<FrameLayout
3337
android:id="@+id/recents_bg_protect"
3438
android:background="@drawable/recents_bg_protect_tile"
@@ -38,7 +42,6 @@
3842
android:layout_marginBottom="@*android:dimen/system_bar_height"
3943
android:clipToPadding="false"
4044
android:clipChildren="false">
41-
4245
<ImageView
4346
android:id="@+id/recents_transition_placeholder_icon"
4447
android:layout_width="wrap_content"

packages/SystemUI/src/com/android/systemui/recent/Choreographer.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,19 @@
2020
import android.animation.AnimatorSet;
2121
import android.animation.AnimatorSet.Builder;
2222
import android.animation.ObjectAnimator;
23+
import android.content.res.Resources;
24+
import android.graphics.drawable.ColorDrawable;
2325
import android.graphics.drawable.Drawable;
2426
import android.util.Slog;
2527
import android.view.View;
2628
import android.view.ViewRootImpl;
2729

30+
import com.android.systemui.R;
31+
2832
/* package */ class Choreographer implements Animator.AnimatorListener {
2933
// should group this into a multi-property animation
3034
private static final int OPEN_DURATION = 136;
31-
private static final int CLOSE_DURATION = 130;
35+
private static final int CLOSE_DURATION = 230;
3236
private static final int SCRIM_DURATION = 400;
3337
private static final String TAG = RecentsPanelView.TAG;
3438
private static final boolean DEBUG = RecentsPanelView.DEBUG;
@@ -81,7 +85,7 @@ void createAnimation(boolean appearing) {
8185
mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
8286
fadeAnim.setInterpolator(appearing
8387
? new android.view.animation.AccelerateInterpolator(1.0f)
84-
: new android.view.animation.DecelerateInterpolator(1.0f));
88+
: new android.view.animation.AccelerateInterpolator(2.5f));
8589
fadeAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
8690

8791
Animator noRecentAppsFadeAnim = null;
@@ -110,6 +114,20 @@ void createAnimation(boolean appearing) {
110114
bgAnim.setDuration(appearing ? SCRIM_DURATION : CLOSE_DURATION);
111115
builder.with(bgAnim);
112116
}
117+
} else {
118+
final Resources res = mRootView.getResources();
119+
boolean isTablet = res.getBoolean(R.bool.config_recents_interface_for_tablets);
120+
if (!isTablet) {
121+
View recentsTransitionBackground =
122+
mRootView.findViewById(R.id.recents_transition_background);
123+
recentsTransitionBackground.setVisibility(View.VISIBLE);
124+
Drawable bgDrawable = new ColorDrawable(0xFF000000);
125+
recentsTransitionBackground.setBackground(bgDrawable);
126+
Animator bgAnim = ObjectAnimator.ofInt(bgDrawable, "alpha", 0, 255);
127+
bgAnim.setDuration(CLOSE_DURATION);
128+
bgAnim.setInterpolator(new android.view.animation.AccelerateInterpolator(1f));
129+
builder.with(bgAnim);
130+
}
113131
}
114132
mContentAnim.addListener(this);
115133
if (mListener != null) {
@@ -139,6 +157,10 @@ void jumpTo(boolean appearing) {
139157
if (mScrimView.getBackground() != null) {
140158
mScrimView.getBackground().setAlpha(appearing ? 255 : 0);
141159
}
160+
View recentsTransitionBackground =
161+
mRootView.findViewById(R.id.recents_transition_background);
162+
recentsTransitionBackground.setVisibility(View.INVISIBLE);
163+
mRootView.requestLayout();
142164
}
143165

144166
public void setPanelHeight(int h) {

packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@
3434
import android.graphics.drawable.Drawable;
3535
import android.net.Uri;
3636
import android.os.RemoteException;
37+
import android.os.ServiceManager;
3738
import android.provider.Settings;
3839
import android.util.AttributeSet;
3940
import android.util.Log;
4041
import android.view.Display;
4142
import android.view.KeyEvent;
43+
import android.view.IWindowManager;
4244
import android.view.LayoutInflater;
4345
import android.view.MenuItem;
4446
import android.view.MotionEvent;
@@ -86,7 +88,8 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
8688
OnRecentsPanelVisibilityChangedListener mVisibilityChangedListener;
8789

8890
ImageView mPlaceholderThumbnail;
89-
boolean mHideWindowAfterPlaceholderThumbnailIsHidden;
91+
View mTransitionBg;
92+
boolean mHideRecentsAfterThumbnailScaleUpStarted;
9093

9194
private RecentTasksLoader mRecentTasksLoader;
9295
private ArrayList<TaskDescription> mRecentTaskDescriptions;
@@ -97,6 +100,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
97100
private boolean mFitThumbnailToXY;
98101
private int mRecentItemLayoutId;
99102
private boolean mFirstScreenful = true;
103+
private boolean mHighEndGfx;
100104

101105
public static interface OnRecentsPanelVisibilityChangedListener {
102106
public void onRecentsPanelVisibilityChanged(boolean visible);
@@ -248,7 +252,7 @@ public int numItemsInOneScreenful() {
248252
@Override
249253
public boolean onKeyUp(int keyCode, KeyEvent event) {
250254
if (keyCode == KeyEvent.KEYCODE_BACK && !event.isCanceled()) {
251-
show(false, true);
255+
show(false, false);
252256
return true;
253257
}
254258
return super.onKeyUp(keyCode, event);
@@ -305,10 +309,6 @@ public void show(boolean show, boolean animate,
305309
ArrayList<TaskDescription> recentTaskDescriptions, boolean firstScreenful) {
306310
sendCloseSystemWindows(mContext, BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
307311

308-
// For now, disable animations. We may want to re-enable in the future
309-
if (show) {
310-
animate = false;
311-
}
312312
if (show) {
313313
// Need to update list of recent apps before we set visibility so this view's
314314
// content description is updated before it gets focus for TalkBack mode
@@ -318,6 +318,7 @@ public void show(boolean show, boolean animate,
318318
// quit early
319319
boolean noApps = !mFirstScreenful && (mRecentTaskDescriptions.size() == 0);
320320
if (mRecentsNoApps != null) {
321+
mRecentsNoApps.setAlpha(1f);
321322
mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
322323
} else {
323324
if (noApps) {
@@ -339,7 +340,6 @@ public void show(boolean show, boolean animate,
339340
mRecentTasksDirty = true;
340341
mWaitingToShow = false;
341342
mReadyToShow = false;
342-
mRecentsNoApps.setVisibility(View.INVISIBLE);
343343
}
344344
if (animate) {
345345
if (mShowing != show) {
@@ -488,7 +488,8 @@ protected void onFinishInflate() {
488488
if (mRecentsScrim != null) {
489489
Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
490490
.getDefaultDisplay();
491-
if (!ActivityManager.isHighEndGfx(d)) {
491+
mHighEndGfx = ActivityManager.isHighEndGfx(d);
492+
if (!mHighEndGfx) {
492493
mRecentsScrim.setBackground(null);
493494
} else if (mRecentsScrim.getBackground() instanceof BitmapDrawable) {
494495
// In order to save space, we make the background texture repeat in the Y direction
@@ -704,22 +705,57 @@ private void updateUiElements(Configuration config) {
704705
setContentDescription(recentAppsAccessibilityDescription);
705706
}
706707

708+
709+
boolean mThumbnailScaleUpStarted;
707710
public void handleOnClick(View view) {
708711
ViewHolder holder = (ViewHolder)view.getTag();
709712
TaskDescription ad = holder.taskDescription;
710713
final Context context = view.getContext();
711714
final ActivityManager am = (ActivityManager)
712715
context.getSystemService(Context.ACTIVITY_SERVICE);
713-
holder.thumbnailViewImage.setDrawingCacheEnabled(true);
714-
Bitmap bm = holder.thumbnailViewImage.getDrawingCache();
715-
mPlaceholderThumbnail = (ImageView) findViewById(R.id.recents_transition_placeholder_icon);
716+
Bitmap bm = holder.thumbnailViewImageBitmap;
717+
boolean usingDrawingCache;
718+
if (bm.getWidth() == holder.thumbnailViewImage.getWidth() &&
719+
bm.getHeight() == holder.thumbnailViewImage.getHeight()) {
720+
usingDrawingCache = false;
721+
} else {
722+
holder.thumbnailViewImage.setDrawingCacheEnabled(true);
723+
bm = holder.thumbnailViewImage.getDrawingCache();
724+
usingDrawingCache = true;
725+
}
726+
727+
if (mPlaceholderThumbnail == null) {
728+
mPlaceholderThumbnail =
729+
(ImageView) findViewById(R.id.recents_transition_placeholder_icon);
730+
}
731+
if (mTransitionBg == null) {
732+
mTransitionBg = (View) findViewById(R.id.recents_transition_background);
733+
734+
IWindowManager wm = IWindowManager.Stub.asInterface(
735+
ServiceManager.getService(Context.WINDOW_SERVICE));
736+
try {
737+
if (!wm.hasSystemNavBar()) {
738+
FrameLayout.LayoutParams lp =
739+
(FrameLayout.LayoutParams) mTransitionBg.getLayoutParams();
740+
int statusBarHeight = getResources().
741+
getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
742+
lp.setMargins(0, statusBarHeight, 0, 0);
743+
mTransitionBg.setLayoutParams(lp);
744+
}
745+
} catch (RemoteException e) {
746+
Log.w(TAG, "Failing checking whether status bar is visible", e);
747+
}
748+
}
716749

717750
final ImageView placeholderThumbnail = mPlaceholderThumbnail;
718-
mHideWindowAfterPlaceholderThumbnailIsHidden = false;
751+
mHideRecentsAfterThumbnailScaleUpStarted = false;
719752
placeholderThumbnail.setVisibility(VISIBLE);
720-
Bitmap b2 = bm.copy(bm.getConfig(), true);
721-
placeholderThumbnail.setImageBitmap(b2);
722-
753+
if (!usingDrawingCache) {
754+
placeholderThumbnail.setImageBitmap(bm);
755+
} else {
756+
Bitmap b2 = bm.copy(bm.getConfig(), true);
757+
placeholderThumbnail.setImageBitmap(b2);
758+
}
723759
Rect r = new Rect();
724760
holder.thumbnailViewImage.getGlobalVisibleRect(r);
725761

@@ -728,13 +764,16 @@ public void handleOnClick(View view) {
728764

729765
show(false, true);
730766

767+
mThumbnailScaleUpStarted = false;
731768
ActivityOptions opts = ActivityOptions.makeDelayedThumbnailScaleUpAnimation(
732769
holder.thumbnailViewImage, bm, 0, 0,
733770
new ActivityOptions.OnAnimationStartedListener() {
734771
@Override public void onAnimationStarted() {
735-
mPlaceholderThumbnail = null;
736-
placeholderThumbnail.setVisibility(INVISIBLE);
737-
if (mHideWindowAfterPlaceholderThumbnailIsHidden) {
772+
mThumbnailScaleUpStarted = true;
773+
if (!mHighEndGfx) {
774+
mPlaceholderThumbnail.setVisibility(INVISIBLE);
775+
}
776+
if (mHideRecentsAfterThumbnailScaleUpStarted) {
738777
hideWindow();
739778
}
740779
}
@@ -751,15 +790,19 @@ public void handleOnClick(View view) {
751790
if (DEBUG) Log.v(TAG, "Starting activity " + intent);
752791
context.startActivity(intent, opts.toBundle());
753792
}
754-
holder.thumbnailViewImage.setDrawingCacheEnabled(false);
793+
if (!usingDrawingCache) {
794+
holder.thumbnailViewImage.setDrawingCacheEnabled(false);
795+
}
755796
}
756797

757798
public void hideWindow() {
758-
if (mPlaceholderThumbnail != null) {
759-
mHideWindowAfterPlaceholderThumbnailIsHidden = true;
799+
if (!mThumbnailScaleUpStarted) {
800+
mHideRecentsAfterThumbnailScaleUpStarted = true;
760801
} else {
761802
setVisibility(GONE);
762-
mHideWindowAfterPlaceholderThumbnailIsHidden = false;
803+
mTransitionBg.setVisibility(INVISIBLE);
804+
mPlaceholderThumbnail.setVisibility(INVISIBLE);
805+
mHideRecentsAfterThumbnailScaleUpStarted = false;
763806
}
764807
}
765808

packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@ private int scrollPositionOfMostRecent() {
7676
}
7777

7878
private void addToRecycledViews(View v) {
79-
if (mRecycledViews.contains(v)) {
80-
throw new RuntimeException("Child was already recycled");
81-
}
8279
if (mRecycledViews.size() < mNumItemsInOneScreenful) {
8380
mRecycledViews.add(v);
8481
}
@@ -105,9 +102,6 @@ private void update() {
105102
old = recycledViews.next();
106103
recycledViews.remove();
107104
old.setVisibility(VISIBLE);
108-
if (old.getParent() != null) {
109-
throw new RuntimeException("Recycled child has parent (i: " + i + ", recycled i: " + mRecycledViews.size());
110-
}
111105
}
112106
final View view = mAdapter.getView(i, old, mLinearLayout);
113107

packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,13 +440,13 @@ public void handleMessage(Message m) {
440440
case MSG_OPEN_RECENTS_PANEL:
441441
if (DEBUG) Slog.d(TAG, "opening recents panel");
442442
if (mRecentsPanel != null) {
443-
mRecentsPanel.show(true, true);
443+
mRecentsPanel.show(true, false);
444444
}
445445
break;
446446
case MSG_CLOSE_RECENTS_PANEL:
447447
if (DEBUG) Slog.d(TAG, "closing recents panel");
448448
if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
449-
mRecentsPanel.show(false, true);
449+
mRecentsPanel.show(false, false);
450450
}
451451
break;
452452
case MSG_PRELOAD_RECENT_APPS:

services/java/com/android/server/wm/WindowManagerService.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
import android.view.animation.Animation;
128128
import android.view.animation.AnimationSet;
129129
import android.view.animation.AnimationUtils;
130+
import android.view.animation.DecelerateInterpolator;
130131
import android.view.animation.Interpolator;
131132
import android.view.animation.ScaleAnimation;
132133

@@ -280,6 +281,8 @@ public class WindowManagerService extends IWindowManager.Stub
280281
private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
281282
private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
282283

284+
private static final float THUMBNAIL_ANIMATION_DECELERATE_FACTOR = 1.5f;
285+
283286
final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
284287
new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
285288
@Override
@@ -3183,15 +3186,15 @@ private Animation createThumbnailAnimationLocked(int transit,
31833186
// it is the standard duration for that. Otherwise we use the longer
31843187
// task transition duration.
31853188
int duration;
3186-
int delayDuration = delayed ? 200 : 0;
3189+
int delayDuration = delayed ? 270 : 0;
31873190
switch (transit) {
31883191
case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
31893192
case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
31903193
duration = mContext.getResources().getInteger(
31913194
com.android.internal.R.integer.config_shortAnimTime);
31923195
break;
31933196
default:
3194-
duration = delayed ? 200 : 300;
3197+
duration = delayed ? 250 : 300;
31953198
break;
31963199
}
31973200
if (thumb) {
@@ -3206,6 +3209,8 @@ private Animation createThumbnailAnimationLocked(int transit,
32063209
AnimationSet set = new AnimationSet(true);
32073210
Animation alpha = new AlphaAnimation(1, 0);
32083211
scale.setDuration(duration);
3212+
scale.setInterpolator(
3213+
new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
32093214
set.addAnimation(scale);
32103215
alpha.setDuration(duration);
32113216
set.addAnimation(alpha);
@@ -3222,6 +3227,8 @@ private Animation createThumbnailAnimationLocked(int transit,
32223227
computePivot(mNextAppTransitionStartX, scaleW),
32233228
computePivot(mNextAppTransitionStartY, scaleH));
32243229
scale.setDuration(duration);
3230+
scale.setInterpolator(
3231+
new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
32253232
scale.setFillBefore(true);
32263233
if (delayDuration > 0) {
32273234
scale.setStartOffset(delayDuration);

0 commit comments

Comments
 (0)