Merge "Add Transition for App -> Recents on TV." into nyc-dev
am: 29f6a9b
* commit '29f6a9be037d305b32b237d2637fced77d2bcc36':
Add Transition for App -> Recents on TV.
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
android:id="@+id/recents_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/recents_tv_background_gradient"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layoutDirection="rtl">
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<ImageView
|
||||
android:id="@+id/card_view_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/recents_tv_card_height"
|
||||
android:layout_height="@dimen/recents_tv_screenshot_height"
|
||||
android:scaleType="centerCrop"
|
||||
android:gravity="center"
|
||||
android:layout_alignParentTop="true"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<resources>
|
||||
<!-- Dimens for recents card in the recents view on tv -->
|
||||
<dimen name="recents_tv_card_width">268dip</dimen>
|
||||
<dimen name="recents_tv_card_height">151dip</dimen>
|
||||
<dimen name="recents_tv_screenshot_height">151dip</dimen>
|
||||
<dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
|
||||
<dimen name="recents_tv_banner_width">114dip</dimen>
|
||||
<dimen name="recents_tv_banner_height">64dip</dimen>
|
||||
|
||||
@@ -15,4 +15,5 @@ limitations under the License.
|
||||
-->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item format="float" type="integer" name="unselected_scale">1.0</item>
|
||||
<item format="float" type="integer" name="selected_scale">1.1</item>
|
||||
</resources>
|
||||
|
||||
@@ -66,6 +66,7 @@ import com.android.systemui.recents.model.RecentsTaskLoader;
|
||||
import com.android.systemui.recents.model.Task;
|
||||
import com.android.systemui.recents.model.TaskGrouping;
|
||||
import com.android.systemui.recents.model.TaskStack;
|
||||
import com.android.systemui.recents.tv.views.TaskCardView;
|
||||
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
|
||||
import com.android.systemui.recents.views.TaskStackView;
|
||||
import com.android.systemui.recents.views.TaskStackViewScroller;
|
||||
@@ -166,6 +167,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
boolean mCanReuseTaskStackViews = true;
|
||||
boolean mDraggingInRecents;
|
||||
boolean mLaunchedWhileDocking;
|
||||
private boolean mIsRunningOnTv;
|
||||
|
||||
// Task launching
|
||||
Rect mSearchBarBounds = new Rect();
|
||||
@@ -230,8 +232,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
|
||||
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
mRecentsIntentActivityName = RECENTS_TV_ACTIVITY;
|
||||
mIsRunningOnTv = true;
|
||||
} else {
|
||||
mRecentsIntentActivityName = RECENTS_ACTIVITY;
|
||||
mIsRunningOnTv = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -793,6 +797,22 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the activity options for an app->recents transition on TV.
|
||||
*/
|
||||
private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
|
||||
ActivityManager.RunningTaskInfo topTask) {
|
||||
Bitmap thumbnail = mThumbnailTransitionBitmapCache;
|
||||
Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
|
||||
if (thumbnail != null) {
|
||||
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
|
||||
null, (int) rect.left, (int) rect.top,
|
||||
(int) rect.width(), (int) rect.height(), mHandler, null);
|
||||
}
|
||||
// If both the screenshot and thumbnail fails, then just fall back to the default transition
|
||||
return getUnknownTransitionActivityOptions();
|
||||
}
|
||||
|
||||
private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask,
|
||||
TaskViewTransform toTransform) {
|
||||
Bitmap thumbnail;
|
||||
@@ -872,6 +892,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
boolean isTopTaskHome, boolean animate) {
|
||||
RecentsTaskLoader loader = Recents.getTaskLoader();
|
||||
|
||||
// If we are on TV, divert to a different helper method
|
||||
if (mIsRunningOnTv) {
|
||||
setUpAndStartTvRecents(topTask, isTopTaskHome, animate);
|
||||
return;
|
||||
}
|
||||
// In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
|
||||
// should always preload the tasks now. If we are dragging in recents, reload them as
|
||||
// the stacks might have changed.
|
||||
@@ -946,6 +971,90 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
mLastToggleTime = SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set up the animations of Tv Recents, then start the Recents Activity.
|
||||
* TODO: Add the Transitions for Home -> Recents TV
|
||||
* TODO: Shift Transition code to separate class under /tv directory and access
|
||||
* from here
|
||||
*/
|
||||
private void setUpAndStartTvRecents(ActivityManager.RunningTaskInfo topTask,
|
||||
boolean isTopTaskHome, boolean animate) {
|
||||
RecentsTaskLoader loader = Recents.getTaskLoader();
|
||||
|
||||
// In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
|
||||
// should always preload the tasks now. If we are dragging in recents, reload them as
|
||||
// the stacks might have changed.
|
||||
if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) {
|
||||
// Create a new load plan if preloadRecents() was never triggered
|
||||
sInstanceLoadPlan = loader.createLoadPlan(mContext);
|
||||
}
|
||||
if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
|
||||
loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome);
|
||||
}
|
||||
TaskStack stack = sInstanceLoadPlan.getTaskStack();
|
||||
|
||||
// Update the header bar if necessary
|
||||
updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
|
||||
|
||||
// Prepare the dummy stack for the transition
|
||||
TaskStackLayoutAlgorithm.VisibilityReport stackVr =
|
||||
mDummyStackView.computeStackVisibilityReport();
|
||||
|
||||
if (!animate) {
|
||||
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
|
||||
startRecentsActivity(topTask, opts, false /* fromHome */,
|
||||
false /* fromSearchHome */, false /* fromThumbnail*/, stackVr);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasRecentTasks = stack.getTaskCount() > 0;
|
||||
boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
|
||||
|
||||
if (useThumbnailTransition) {
|
||||
// Try starting with a thumbnail transition
|
||||
ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask);
|
||||
if (opts != null) {
|
||||
startRecentsActivity(topTask, opts, false /* fromHome */,
|
||||
false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
|
||||
} else {
|
||||
// Fall through below to the non-thumbnail transition
|
||||
useThumbnailTransition = false;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
String homeActivityPackage = ssp.getHomeActivityPackageName();
|
||||
String searchWidgetPackage = null;
|
||||
if (RecentsDebugFlags.Static.EnableSearchBar) {
|
||||
searchWidgetPackage = Prefs.getString(mContext,
|
||||
Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null);
|
||||
} else {
|
||||
AppWidgetProviderInfo searchWidgetInfo = ssp.resolveSearchAppWidget();
|
||||
if (searchWidgetInfo != null) {
|
||||
searchWidgetPackage = searchWidgetInfo.provider.getPackageName();
|
||||
}
|
||||
}
|
||||
|
||||
// Determine whether we are coming from a search owned home activity
|
||||
boolean fromSearchHome = (homeActivityPackage != null) &&
|
||||
homeActivityPackage.equals(searchWidgetPackage);
|
||||
ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome);
|
||||
startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome,
|
||||
false /* fromThumbnail */, stackVr);
|
||||
} else {
|
||||
// Otherwise we do the normal fade from an unknown source
|
||||
ActivityOptions opts = getUnknownTransitionActivityOptions();
|
||||
startRecentsActivity(topTask, opts, true /* fromHome */,
|
||||
false /* fromSearchHome */, false /* fromThumbnail */, stackVr);
|
||||
}
|
||||
}
|
||||
mLastToggleTime = SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the recents activity.
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.android.systemui.R;
|
||||
|
||||
public class ViewFocusAnimator implements View.OnFocusChangeListener {
|
||||
private final float mUnselectedScale;
|
||||
private final float mSelectedScale;
|
||||
private final float mSelectedScaleDelta;
|
||||
private final float mUnselectedZ;
|
||||
private final float mSelectedZDelta;
|
||||
@@ -49,8 +50,9 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
|
||||
TypedValue out = new TypedValue();
|
||||
res.getValue(R.integer.unselected_scale, out, true);
|
||||
mUnselectedScale = out.getFloat();
|
||||
mSelectedScaleDelta = res.getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1) -
|
||||
mUnselectedScale;
|
||||
res.getValue(R.integer.selected_scale, out, true);
|
||||
mSelectedScale = out.getFloat();
|
||||
mSelectedScaleDelta = mSelectedScale - mUnselectedScale;
|
||||
|
||||
mUnselectedZ = res.getDimensionPixelOffset(R.dimen.recents_tv_unselected_item_z);
|
||||
mSelectedZDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_selected_item_z_delta);
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
package com.android.systemui.recents.tv.views;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -121,10 +119,10 @@ public class RecentsTvTransitionHelper {
|
||||
};
|
||||
}
|
||||
try {
|
||||
Rect taskRect = taskView.getGlobalRect();
|
||||
Rect taskRect = taskView.getFocusedThumbnailRect();
|
||||
WindowManagerGlobal.getWindowManagerService()
|
||||
.overridePendingAppTransitionThumb(task.thumbnail, taskRect.left,
|
||||
taskRect.top, callback, true);
|
||||
.overridePendingAppTransitionAspectScaledThumb(task.thumbnail, taskRect.left,
|
||||
taskRect.top, taskRect.width(), taskRect.height(), callback, true);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to override transition: " + e);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,13 @@
|
||||
package com.android.systemui.recents.tv.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
@@ -71,15 +76,46 @@ public class TaskCardView extends LinearLayout {
|
||||
mThumbnailView.getFocusedRect(r);
|
||||
}
|
||||
|
||||
public Rect getFocusedRect() {
|
||||
public Rect getFocusedThumbnailRect() {
|
||||
Rect r = new Rect();
|
||||
getFocusedRect(r);
|
||||
mThumbnailView.getGlobalVisibleRect(r);
|
||||
TypedValue out = new TypedValue();
|
||||
getContext().getResources().getValue(R.integer.selected_scale, out, true);
|
||||
float deltaScale = (out.getFloat() - 1.0f) / 2;
|
||||
r.set((int) (r.left - r.left * deltaScale),
|
||||
(int) (r.top - r.top * deltaScale),
|
||||
(int) (r.right + r.right * deltaScale),
|
||||
(int) (r.bottom + r.bottom * deltaScale));
|
||||
return r;
|
||||
}
|
||||
|
||||
public Rect getGlobalRect() {
|
||||
Rect r = new Rect();
|
||||
getGlobalVisibleRect(r);
|
||||
return r;
|
||||
public static Rect getStartingCardThumbnailRect(Context context) {
|
||||
Resources res = context.getResources();
|
||||
|
||||
TypedValue out = new TypedValue();
|
||||
res.getValue(R.integer.selected_scale, out, true);
|
||||
float scale = out.getFloat();
|
||||
|
||||
int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width);
|
||||
int widthDelta = (int) (width * scale - width);
|
||||
int height = (int) (res.getDimensionPixelOffset(
|
||||
R.dimen.recents_tv_screenshot_height) * scale);
|
||||
int padding = res.getDimensionPixelOffset(R.dimen.recents_tv_grid_row_padding);
|
||||
|
||||
int headerHeight = (int) ((res.getDimensionPixelOffset(
|
||||
R.dimen.recents_tv_card_extra_badge_size) +
|
||||
res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom)) * scale);
|
||||
|
||||
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
Display display = wm.getDefaultDisplay();
|
||||
Point size = new Point();
|
||||
display.getSize(size);
|
||||
int screenWidth = size.x;
|
||||
int screenHeight = size.y;
|
||||
|
||||
return new Rect(screenWidth - width - padding - widthDelta / 2,
|
||||
screenHeight / 2 - height / 2 + headerHeight / 2,
|
||||
screenWidth - padding + widthDelta / 2,
|
||||
screenHeight / 2 + height / 2 + headerHeight / 2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user