Merge "Add Home Recents Transition Animations" into nyc-dev

This commit is contained in:
Sid Soundararajan
2016-04-07 19:41:46 +00:00
committed by Android (Google) Code Review
9 changed files with 228 additions and 53 deletions

View File

@@ -57,4 +57,6 @@
<!-- Extra space around the PIP control button icon to match with the focused circle -->
<dimen name="tv_pip_button_icon_padding">5dp</dimen>
<!-- Values for entering Recents and exiting Recents -->
<dimen name="recents_tv_home_recents_shift">125dip</dimen>
</resources>

View File

@@ -17,5 +17,11 @@
<integer name="item_scale_anim_duration">150</integer>
<integer name="dismiss_short_duration">200</integer>
<integer name="dismiss_long_duration">400</integer>
<integer name="recents_tv_pip_focus_anim_duration">200</integer>
<!-- Duration for how long it takes cards to slide in or out when going to and from recents. -->
<integer name="recents_home_duration">400</integer>
<!-- Delay between the start of slide in animation for each card. -->
<integer name="recents_home_delay">40</integer>
</resources>

View File

@@ -37,14 +37,12 @@ import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -53,7 +51,9 @@ import com.android.systemui.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.tv.animations.HomeRecentsEnterExitAnimationHolder;
import com.android.systemui.recents.tv.views.RecentsTvView;
import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.tv.pip.PipManager;
@@ -76,11 +76,14 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
private RecentsPackageMonitor mPackageMonitor;
private long mLastTabKeyEventTime;
private boolean mIgnoreAltTabRelease;
private boolean mLaunchedFromHome;
private RecentsTvView mRecentsView;
private View mPipView;
private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
private TaskStackHorizontalGridView mTaskStackHorizontalGridView;
private FinishRecentsRunnable mFinishLaunchHomeRunnable;
private HomeRecentsEnterExitAnimationHolder mHomeRecentsEnterExitAnimationHolder;
private final PipManager mPipManager = PipManager.getInstance();
private final PipManager.Listener mPipListener = new PipManager.Listener() {
@@ -174,6 +177,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
if (!plan.hasTasks()) {
loader.preloadTasks(plan, -1, launchState.launchedFromHome);
}
mLaunchedFromHome = launchState.launchedFromHome;
TaskStack stack = plan.getTaskStack();
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
loadOpts.runningTaskId = launchState.launchedToTaskId;
@@ -187,7 +191,8 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
Collections.reverse(stackTasks);
if (mTaskStackViewAdapter == null) {
mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
mRecentsView.setTaskStackViewAdapter(mTaskStackViewAdapter);
mTaskStackHorizontalGridView = mRecentsView
.setTaskStackViewAdapter(mTaskStackViewAdapter);
} else {
mTaskStackViewAdapter.setNewStackTasks(stackTasks);
}
@@ -229,17 +234,24 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
}
void dismissRecentsToHome(boolean animateTaskViews) {
DismissRecentsToHomeAnimationStarted dismissEvent =
new DismissRecentsToHomeAnimationStarted(animateTaskViews);
dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
dismissEvent.addPostAnimationCallback(new Runnable() {
Runnable closeSystemWindows = new Runnable() {
@Override
public void run() {
Recents.getSystemServices().sendCloseSystemWindows(
BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
}
});
EventBus.getDefault().send(dismissEvent);
};
DismissRecentsToHomeAnimationStarted dismissEvent =
new DismissRecentsToHomeAnimationStarted(animateTaskViews);
dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
dismissEvent.addPostAnimationCallback(closeSystemWindows);
if(mTaskStackHorizontalGridView.getChildCount() > 0) {
mHomeRecentsEnterExitAnimationHolder.startExitAnimation(dismissEvent);
} else {
closeSystemWindows.run();
mFinishLaunchHomeRunnable.run();
}
}
boolean dismissRecentsToHomeIfVisible(boolean animated) {
@@ -319,6 +331,19 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
// Update the recent tasks
updateRecentsTasks();
mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
getApplicationContext(), mTaskStackHorizontalGridView);
if(mTaskStackHorizontalGridView != null &&
mTaskStackHorizontalGridView.getChildCount() > 0) {
if(mLaunchedFromHome) {
mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
} else {
mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
}
} else {
mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
}
// If this is a new instance from a configuration change, then we have to manually trigger
// the enter animation state, or if recents was relaunched by AM, without going through
// the normal mechanisms
@@ -340,6 +365,9 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
if(mLaunchedFromHome) {
mHomeRecentsEnterExitAnimationHolder.startEnterAnimation();
}
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
@@ -444,12 +472,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
}
}
public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(true));
mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
mRecentsView.invalidate();
}
public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
int launchToTaskId = launchState.launchedToTaskId;
@@ -489,6 +511,11 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
if(mLaunchedFromHome) {
mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
} else {
mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
}
// We post to make sure that this information is delivered after this traversals is
// finished.
mRecentsView.post(new Runnable() {

View File

@@ -25,6 +25,7 @@ import android.graphics.Rect;
import android.os.SystemClock;
import android.os.UserHandle;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
@@ -34,6 +35,7 @@ import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.tv.views.TaskCardView;
import com.android.systemui.statusbar.tv.TvStatusBar;
public class RecentsTvImpl extends RecentsImpl{
public final static String RECENTS_TV_ACTIVITY =
@@ -81,16 +83,7 @@ public class RecentsTvImpl extends RecentsImpl{
}
if (!useThumbnailTransition) {
// If there is no thumbnail transition, but is launching from home into recents, then
// use a quick home transition and do the animation from home
if (hasRecentTasks) {
ActivityOptions opts = getHomeTransitionActivityOptions();
startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */);
} else {
// Otherwise we do the normal fade from an unknown source
ActivityOptions opts = getUnknownTransitionActivityOptions();
startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */);
}
startRecentsActivity(topTask, null, true /* fromHome */, false /* fromThumbnail */);
}
mLastToggleTime = SystemClock.elapsedRealtime();
}
@@ -134,4 +127,13 @@ public class RecentsTvImpl extends RecentsImpl{
// If both the screenshot and thumbnail fails, then just fall back to the default transition
return getUnknownTransitionActivityOptions();
}
@Override
public void onVisibilityChanged(Context context, boolean visible) {
SystemUIApplication app = (SystemUIApplication) context;
TvStatusBar statusBar = app.getComponent(TvStatusBar.class);
if (statusBar != null) {
statusBar.updateRecentsVisibility(visible);
}
}
}

View File

@@ -18,9 +18,8 @@ package com.android.systemui.recents.tv.animations;
import android.animation.Animator;
import android.content.res.Resources;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.View;
import android.widget.LinearLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.recents.tv.views.TaskCardView;
import com.android.systemui.R;
@@ -28,7 +27,6 @@ import com.android.systemui.R;
public class DismissAnimationsHolder {
private LinearLayout mDismissArea;
private LinearLayout mTaskCardView;
private FastOutSlowInInterpolator mFastOutSlowIn;
private int mCardYDelta;
private long mShortDuration;
private long mLongDuration;
@@ -36,7 +34,6 @@ public class DismissAnimationsHolder {
public DismissAnimationsHolder(TaskCardView taskCardView) {
mTaskCardView = (LinearLayout) taskCardView.findViewById(R.id.recents_tv_card);
mDismissArea = (LinearLayout) taskCardView.findViewById(R.id.card_dismiss);
mFastOutSlowIn = new FastOutSlowInInterpolator();
Resources res = taskCardView.getResources();
mCardYDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_shift_down);
@@ -45,36 +42,42 @@ public class DismissAnimationsHolder {
}
public void startEnterAnimation() {
mDismissArea.animate().setDuration(mShortDuration);
mDismissArea.animate().setInterpolator(mFastOutSlowIn);
mDismissArea.animate().alpha(1.0f);
mDismissArea.animate()
.setDuration(mShortDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.alpha(1.0f);
mTaskCardView.animate().setDuration(mShortDuration);
mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
mTaskCardView.animate().translationYBy(mCardYDelta);
mTaskCardView.animate().alpha(0.5f);
mTaskCardView.animate()
.setDuration(mShortDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.translationYBy(mCardYDelta)
.alpha(0.5f);
}
public void startExitAnimation() {
mDismissArea.animate().setDuration(mShortDuration);
mDismissArea.animate().setInterpolator(mFastOutSlowIn);
mDismissArea.animate().alpha(0.0f);
mDismissArea.animate()
.setDuration(mShortDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.alpha(0.0f);
mTaskCardView.animate().setDuration(mShortDuration);
mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
mTaskCardView.animate().translationYBy(-mCardYDelta);
mTaskCardView.animate().alpha(1.0f);
mTaskCardView.animate()
.setDuration(mShortDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.translationYBy(-mCardYDelta)
.alpha(1.0f);
}
public void startDismissAnimation(Animator.AnimatorListener listener) {
mDismissArea.animate().setDuration(mShortDuration);
mDismissArea.animate().setInterpolator(mFastOutSlowIn);
mDismissArea.animate().alpha(0.0f);
mDismissArea.animate()
.setDuration(mShortDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.alpha(0.0f);
mTaskCardView.animate().setDuration(mLongDuration);
mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
mTaskCardView.animate().translationYBy(mCardYDelta);
mTaskCardView.animate().alpha(0.0f);
mTaskCardView.animate().setListener(listener);
mTaskCardView.animate()
.setDuration(mLongDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.translationYBy(mCardYDelta)
.alpha(0.0f)
.setListener(listener);
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2016 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.recents.tv.animations;
import android.content.Context;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.tv.views.TaskCardView;
import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
public class HomeRecentsEnterExitAnimationHolder {
private Context mContext;
private TaskStackHorizontalGridView mGridView;
private long mDelay;
private int mDuration;
private int mTranslationX;
public HomeRecentsEnterExitAnimationHolder(Context context,
TaskStackHorizontalGridView gridView) {
mContext = context;
mGridView = gridView;
mTranslationX = mContext.getResources()
.getDimensionPixelSize(R.dimen.recents_tv_home_recents_shift);
mDelay = mContext.getResources().getInteger(R.integer.recents_home_delay);
mDuration = mContext.getResources().getInteger(R.integer.recents_home_duration);
}
public void startEnterAnimation() {
for(int i = 0; i < mGridView.getChildCount(); i++) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
view.setTranslationX(-mTranslationX);
view.setAlpha(0.0f);
view.animate()
.alpha(1.0f)
.translationX(0)
.setDuration(mDuration)
.setStartDelay(mDelay * i)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
}
}
public void startExitAnimation(DismissRecentsToHomeAnimationStarted dismissEvent) {
for(int i = mGridView.getChildCount() - 1; i >= 0; i--) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
view.animate()
.alpha(0.0f)
.translationXBy(-mTranslationX)
.setDuration(mDuration)
.setStartDelay(mDelay * (mGridView.getChildCount() - 1 - i))
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
if(i == 0) {
view.animate().setListener(dismissEvent.getAnimationTrigger()
.decrementOnAnimationEnd());
dismissEvent.getAnimationTrigger().increment();
}
}
}
public void setEnterFromHomeStartingAnimationValues() {
for(int i = 0; i < mGridView.getChildCount(); i++) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
view.setTranslationX(-mTranslationX);
view.setAlpha(0.0f);
}
}
public void setEnterFromAppStartingAnimationValues() {
for(int i = 0; i < mGridView.getChildCount(); i++) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
view.setTranslationX(0);
view.setAlpha(1.0f);
}
}
}

View File

@@ -218,9 +218,15 @@ public class RecentsTvView extends FrameLayout {
}
}
public void setTaskStackViewAdapter(TaskStackHorizontalViewAdapter taskStackViewAdapter) {
public TaskStackHorizontalGridView setTaskStackViewAdapter(
TaskStackHorizontalViewAdapter taskStackViewAdapter) {
if(mTaskStackHorizontalView != null) {
mTaskStackHorizontalView.setAdapter(taskStackViewAdapter);
}
return mTaskStackHorizontalView;
}
public TaskStackHorizontalGridView getGridView() {
return mTaskStackHorizontalView;
}
}

View File

@@ -64,6 +64,7 @@ public class TaskCardView extends LinearLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);

View File

@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.tv;
import android.content.ComponentName;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.view.View;
@@ -29,12 +30,22 @@ import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.tv.pip.PipManager;
/*
/**
* Status bar implementation for "large screen" products that mostly present no on-screen nav
*/
public class TvStatusBar extends BaseStatusBar {
/**
* Tracking calls to View.setSystemUiVisibility().
*/
int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
/**
* Last value sent to window manager.
*/
private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
@Override
public void setIcon(String slot, StatusBarIcon icon) {
}
@@ -207,4 +218,30 @@ public class TvStatusBar extends BaseStatusBar {
@Override
public void clickTile(ComponentName tile) {
}
@Override
public void start() {
super.start();
putComponent(TvStatusBar.class, this);
}
public void updateRecentsVisibility(boolean visible) {
// Update the recents visibility flag
if (visible) {
mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
} else {
mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE;
}
notifyUiVisibilityChanged(mSystemUiVisibility);
}
private void notifyUiVisibilityChanged(int vis) {
try {
if (mLastDispatchedSystemUiVisibility != vis) {
mWindowManagerService.statusBarVisibilityChanged(vis);
mLastDispatchedSystemUiVisibility = vis;
}
} catch (RemoteException ex) {
}
}
}