Add dismiss animation for Recents TV and Enable Dismiss
Redo rect calculations for new positions. Refactor some code to make a RecentsTvImpl. Change-Id: Ifa269fe18ea40ea9a102ec0207a6c7ab796e6f77
This commit is contained in:
BIN
packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.png
Normal file
BIN
packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 414 B |
BIN
packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.png
Normal file
BIN
packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 304 B |
BIN
packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.png
Normal file
BIN
packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 536 B |
@@ -28,12 +28,8 @@
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="beforeDescendants"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:paddingStart="@dimen/recents_tv_grid_row_padding"
|
||||
android:paddingEnd="@dimen/recents_tv_grid_row_padding"
|
||||
android:layout_marginTop="@dimen/recents_tv_gird_row_top_margin"
|
||||
android:focusable="true" />
|
||||
|
||||
<View
|
||||
android:id="@+id/pip_shade"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
android:focusableInTouchMode="true"
|
||||
android:layout_gravity="center"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/recents_tv_card"
|
||||
android:layout_width="@dimen/recents_tv_card_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
@@ -66,4 +68,30 @@
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_below="@id/card_title_text" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/card_dismiss"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_below="@id/recents_tv_card"
|
||||
android:alpha="0.0">
|
||||
<ImageView
|
||||
android:id="@+id/card_dismiss_icon"
|
||||
android:layout_width="@dimen/recents_tv_dismiss_icon_size"
|
||||
android:layout_height="@dimen/recents_tv_dismiss_icon_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="@dimen/recents_tv_dismiss_icon_top_margin"
|
||||
android:layout_marginBottom="@dimen/recents_tv_dismiss_icon_bottom_margin"
|
||||
android:src="@drawable/ic_cancel_white_24dp" />
|
||||
<TextView
|
||||
android:id="@+id/card_dismiss_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/recents_tv_dismiss_text_size"
|
||||
android:fontFamily="@string/font_roboto_light"
|
||||
android:textColor="@color/recents_tv_dismiss_text_color"
|
||||
android:text="@string/recents_tv_dismiss"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
</LinearLayout>
|
||||
</com.android.systemui.recents.tv.views.TaskCardView>
|
||||
@@ -19,4 +19,5 @@
|
||||
<resources>
|
||||
<color name="recents_tv_card_background_color">#FF37474F</color>
|
||||
<color name="recents_tv_card_title_text_color">#CCEEEEEE</color>
|
||||
<color name="recents_tv_dismiss_text_color">#7FEEEEEE</color>
|
||||
</resources>
|
||||
@@ -18,8 +18,8 @@
|
||||
-->
|
||||
<resources>
|
||||
<!-- Dimens for recents card in the recents view on tv -->
|
||||
<dimen name="recents_tv_card_width">268dip</dimen>
|
||||
<dimen name="recents_tv_screenshot_height">151dip</dimen>
|
||||
<dimen name="recents_tv_card_width">240dip</dimen>
|
||||
<dimen name="recents_tv_screenshot_height">135dip</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>
|
||||
@@ -29,10 +29,10 @@
|
||||
<dimen name="recents_tv_text_padding_bottom">12dip</dimen>
|
||||
|
||||
<!-- Padding for grid view in recents view on tv -->
|
||||
<dimen name="recents_tv_grid_row_padding">56dip</dimen>
|
||||
<dimen name="recents_tv_gird_row_top_padding">57dip</dimen>
|
||||
<dimen name="recents_tv_gird_row_top_margin">215dip</dimen>
|
||||
<dimen name="recents_tv_grid_max_row_height">268dip</dimen>
|
||||
<dimen name="recents_tv_gird_card_spacing">20dip</dimen>
|
||||
<dimen name="recents_tv_gird_card_spacing">8dip</dimen>
|
||||
<dimen name="recents_tv_gird_focused_card_delta">44dip</dimen>
|
||||
|
||||
<!-- Values for focus animation -->
|
||||
<dimen name="recents_tv_unselected_item_z">6dp</dimen>
|
||||
@@ -43,4 +43,13 @@
|
||||
|
||||
<!-- Values for text on recents cards on tv -->
|
||||
<dimen name="recents_tv_title_text_size">12sp</dimen>
|
||||
|
||||
<!-- Values for card dismiss state -->
|
||||
<dimen name="recents_tv_dismiss_shift_down">48dip</dimen>
|
||||
<dimen name="recents_tv_dismiss_top_margin">356dip</dimen>
|
||||
<dimen name="recents_tv_dismiss_icon_size">24dip</dimen>
|
||||
<dimen name="recents_tv_dismiss_icon_top_margin">38dip</dimen>
|
||||
<dimen name="recents_tv_dismiss_icon_bottom_margin">1dip</dimen>
|
||||
<dimen name="recents_tv_dismiss_text_size">12sp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -15,4 +15,6 @@
|
||||
-->
|
||||
<resources>
|
||||
<integer name="item_scale_anim_duration">150</integer>
|
||||
<integer name="dismiss_short_duration">200</integer>
|
||||
<integer name="dismiss_long_duration">400</integer>
|
||||
</resources>
|
||||
@@ -35,7 +35,11 @@
|
||||
<string name="pip_onboarding_description">Press and hold the HOME button to control PIP</string>
|
||||
<!-- Button to close picture-in-picture (PIP) onboarding screen. -->
|
||||
<string name="pip_onboarding_button">Got it</string>
|
||||
<!-- Dismiss icon description -->
|
||||
<string name="recents_tv_dismiss">Dismiss</string>
|
||||
<!-- Font for Recents -->
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string name="font_roboto_regular" translatable="false">sans-serif</string>
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string name="font_roboto_light" translatable="false">sans-serif-light</string>
|
||||
</resources>
|
||||
|
||||
@@ -15,5 +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>
|
||||
<item format="float" type="integer" name="selected_scale">1.259</item>
|
||||
</resources>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.recents;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.UiModeManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -53,6 +54,7 @@ import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
|
||||
import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
||||
import com.android.systemui.recents.model.RecentsTaskLoader;
|
||||
import com.android.systemui.recents.tv.RecentsTvImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -182,7 +184,13 @@ public class Recents extends SystemUI
|
||||
sTaskLoader = new RecentsTaskLoader(mContext);
|
||||
sConfiguration = new RecentsConfiguration(mContext);
|
||||
mHandler = new Handler();
|
||||
mImpl = new RecentsImpl(mContext);
|
||||
UiModeManager uiModeManager = (UiModeManager) mContext.
|
||||
getSystemService(Context.UI_MODE_SERVICE);
|
||||
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
mImpl = new RecentsTvImpl(mContext);
|
||||
} else {
|
||||
mImpl = new RecentsImpl(mContext);
|
||||
}
|
||||
|
||||
// Check if there is a recents override package
|
||||
if ("userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE)) {
|
||||
|
||||
@@ -21,12 +21,10 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.ITaskStackListener;
|
||||
import android.app.UiModeManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
@@ -66,7 +64,6 @@ 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;
|
||||
@@ -96,10 +93,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
|
||||
public final static String RECENTS_PACKAGE = "com.android.systemui";
|
||||
public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
|
||||
public final static String RECENTS_TV_ACTIVITY = "com.android.systemui.recents.tv.RecentsTvActivity";
|
||||
|
||||
//Used to store tv or non-tv activty for use in creating intents.
|
||||
private final String mRecentsIntentActivityName;
|
||||
|
||||
/**
|
||||
* An implementation of ITaskStackListener, that allows us to listen for changes to the system
|
||||
@@ -158,16 +151,15 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
}
|
||||
}
|
||||
|
||||
private static RecentsTaskLoadPlan sInstanceLoadPlan;
|
||||
protected static RecentsTaskLoadPlan sInstanceLoadPlan;
|
||||
|
||||
Context mContext;
|
||||
Handler mHandler;
|
||||
protected Context mContext;
|
||||
protected Handler mHandler;
|
||||
TaskStackListenerImpl mTaskStackListener;
|
||||
RecentsAppWidgetHost mAppWidgetHost;
|
||||
boolean mCanReuseTaskStackViews = true;
|
||||
protected boolean mCanReuseTaskStackViews = true;
|
||||
boolean mDraggingInRecents;
|
||||
boolean mLaunchedWhileDocking;
|
||||
private boolean mIsRunningOnTv;
|
||||
|
||||
// Task launching
|
||||
Rect mSearchBarBounds = new Rect();
|
||||
@@ -182,11 +174,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
// Header (for transition)
|
||||
TaskViewHeader mHeaderBar;
|
||||
final Object mHeaderBarLock = new Object();
|
||||
TaskStackView mDummyStackView;
|
||||
protected TaskStackView mDummyStackView;
|
||||
|
||||
// Variables to keep track of if we need to start recents after binding
|
||||
boolean mTriggeredFromAltTab;
|
||||
long mLastToggleTime;
|
||||
protected boolean mTriggeredFromAltTab;
|
||||
protected long mLastToggleTime;
|
||||
DozeTrigger mFastAltTabTrigger = new DozeTrigger(FAST_ALT_TAB_DELAY_MS, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -197,7 +189,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
}
|
||||
});
|
||||
|
||||
Bitmap mThumbnailTransitionBitmapCache;
|
||||
protected Bitmap mThumbnailTransitionBitmapCache;
|
||||
Task mThumbnailTransitionBitmapCacheKey;
|
||||
|
||||
public RecentsImpl(Context context) {
|
||||
@@ -227,16 +219,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize();
|
||||
launchOpts.onlyLoadForCache = true;
|
||||
loader.loadTasks(mContext, plan, launchOpts);
|
||||
|
||||
//Manager used to determine if we are running on tv or not
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public void onBootCompleted() {
|
||||
@@ -729,7 +711,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
/**
|
||||
* Creates the activity options for a unknown state->recents transition.
|
||||
*/
|
||||
private ActivityOptions getUnknownTransitionActivityOptions() {
|
||||
protected ActivityOptions getUnknownTransitionActivityOptions() {
|
||||
return ActivityOptions.makeCustomAnimation(mContext,
|
||||
R.anim.recents_from_unknown_enter,
|
||||
R.anim.recents_from_unknown_exit,
|
||||
@@ -739,7 +721,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
/**
|
||||
* Creates the activity options for a home->recents transition.
|
||||
*/
|
||||
private ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
|
||||
protected ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
|
||||
if (fromSearchHome) {
|
||||
return ActivityOptions.makeCustomAnimation(mContext,
|
||||
R.anim.recents_from_search_launcher_enter,
|
||||
@@ -797,22 +779,6 @@ 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;
|
||||
@@ -888,15 +854,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
/**
|
||||
* Shows the recents activity
|
||||
*/
|
||||
private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
|
||||
protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
|
||||
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.
|
||||
@@ -971,90 +932,6 @@ 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.
|
||||
*/
|
||||
@@ -1078,7 +955,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
launchState.launchedWhileDocking = mLaunchedWhileDocking;
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(RECENTS_PACKAGE, mRecentsIntentActivityName);
|
||||
intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||
| Intent.FLAG_ACTIVITY_TASK_ON_HOME);
|
||||
|
||||
@@ -47,7 +47,6 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
@@ -73,6 +72,7 @@ import com.android.systemui.Prefs;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.recents.RecentsDebugFlags;
|
||||
import com.android.systemui.recents.RecentsImpl;
|
||||
import com.android.systemui.recents.tv.RecentsTvImpl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -280,7 +280,7 @@ public class SystemServicesProxy {
|
||||
// Check if the front most activity is recents
|
||||
if ((topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE) &&
|
||||
(topActivity.getClassName().equals(RecentsImpl.RECENTS_ACTIVITY) ||
|
||||
topActivity.getClassName().equals(RecentsImpl.RECENTS_TV_ACTIVITY)))) {
|
||||
topActivity.getClassName().equals(RecentsTvImpl.RECENTS_TV_ACTIVITY)))) {
|
||||
if (isHomeTopMost != null) {
|
||||
isHomeTopMost.value = false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import com.android.systemui.recents.*;
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
||||
import com.android.systemui.recents.model.RecentsTaskLoader;
|
||||
import com.android.systemui.recents.model.TaskStack;
|
||||
import com.android.systemui.recents.tv.views.TaskCardView;
|
||||
|
||||
public class RecentsTvImpl extends RecentsImpl{
|
||||
public final static String RECENTS_TV_ACTIVITY =
|
||||
"com.android.systemui.recents.tv.RecentsTvActivity";
|
||||
|
||||
public RecentsTvImpl(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startRecentsActivity(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 (mTriggeredFromAltTab || sInstanceLoadPlan == null) {
|
||||
// Create a new load plan if preloadRecents() was never triggered
|
||||
sInstanceLoadPlan = loader.createLoadPlan(mContext);
|
||||
}
|
||||
if (mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
|
||||
loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome);
|
||||
}
|
||||
TaskStack stack = sInstanceLoadPlan.getTaskStack();
|
||||
|
||||
if (!animate) {
|
||||
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
|
||||
startRecentsActivity(topTask, opts, false /* fromHome */, false /* fromThumbnail*/);
|
||||
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 */, true /* fromThumbnail */);
|
||||
} 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();
|
||||
ActivityOptions opts = getHomeTransitionActivityOptions(false);
|
||||
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 */);
|
||||
}
|
||||
}
|
||||
mLastToggleTime = SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
|
||||
ActivityOptions opts, boolean fromHome, boolean fromThumbnail) {
|
||||
// Update the configuration based on the launch options
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
RecentsActivityLaunchState launchState = config.getLaunchState();
|
||||
launchState.launchedFromHome = fromHome;
|
||||
launchState.launchedFromSearchHome = false;
|
||||
launchState.launchedFromApp = fromThumbnail;
|
||||
launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
|
||||
launchState.launchedWithAltTab = mTriggeredFromAltTab;
|
||||
launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews;
|
||||
launchState.launchedHasConfigurationChanged = false;
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(RECENTS_PACKAGE, RECENTS_TV_ACTIVITY);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||
| Intent.FLAG_ACTIVITY_TASK_ON_HOME);
|
||||
|
||||
if (opts != null) {
|
||||
mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
|
||||
} else {
|
||||
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
|
||||
}
|
||||
mCanReuseTaskStackViews = true;
|
||||
EventBus.getDefault().send(new RecentsActivityStartingEvent());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.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.recents.tv.views.TaskCardView;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
mShortDuration = res.getInteger(R.integer.dismiss_short_duration);
|
||||
mLongDuration = res.getInteger(R.integer.dismiss_long_duration);
|
||||
}
|
||||
|
||||
public void startEnterAnimation() {
|
||||
mDismissArea.animate().setDuration(mShortDuration);
|
||||
mDismissArea.animate().setInterpolator(mFastOutSlowIn);
|
||||
mDismissArea.animate().alpha(1.0f);
|
||||
|
||||
mTaskCardView.animate().setDuration(mShortDuration);
|
||||
mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
|
||||
mTaskCardView.animate().translationYBy(mCardYDelta);
|
||||
mTaskCardView.animate().alpha(0.5f);
|
||||
}
|
||||
|
||||
public void startExitAnimation() {
|
||||
mDismissArea.animate().setDuration(mShortDuration);
|
||||
mDismissArea.animate().setInterpolator(mFastOutSlowIn);
|
||||
mDismissArea.animate().alpha(0.0f);
|
||||
|
||||
mTaskCardView.animate().setDuration(mShortDuration);
|
||||
mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
|
||||
mTaskCardView.animate().translationYBy(-mCardYDelta);
|
||||
mTaskCardView.animate().alpha(1.0f);
|
||||
}
|
||||
|
||||
public void startDismissAnimation(Animator.AnimatorListener listener) {
|
||||
mDismissArea.animate().setDuration(mShortDuration);
|
||||
mDismissArea.animate().setInterpolator(mFastOutSlowIn);
|
||||
mDismissArea.animate().alpha(0.0f);
|
||||
|
||||
mTaskCardView.animate().setDuration(mLongDuration);
|
||||
mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
|
||||
mTaskCardView.animate().translationYBy(mCardYDelta);
|
||||
mTaskCardView.animate().alpha(0.0f);
|
||||
mTaskCardView.animate().setListener(listener);
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,8 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
|
||||
private final float mSelectedScaleDelta;
|
||||
private final float mUnselectedZ;
|
||||
private final float mSelectedZDelta;
|
||||
private final float mUnselectedSpacing;
|
||||
private final float mSelectedSpacingDelta;
|
||||
private final int mAnimDuration;
|
||||
private final Interpolator mFocusInterpolator;
|
||||
|
||||
@@ -57,6 +59,9 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
|
||||
mUnselectedZ = res.getDimensionPixelOffset(R.dimen.recents_tv_unselected_item_z);
|
||||
mSelectedZDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_selected_item_z_delta);
|
||||
|
||||
mUnselectedSpacing = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_card_spacing);
|
||||
mSelectedSpacingDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_focused_card_delta);
|
||||
|
||||
mAnimDuration = res.getInteger(R.integer.item_scale_anim_duration);
|
||||
|
||||
mFocusInterpolator = new AccelerateDecelerateInterpolator();
|
||||
@@ -85,10 +90,14 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
|
||||
|
||||
float scale = mUnselectedScale + (level * mSelectedScaleDelta);
|
||||
float z = mUnselectedZ + (level * mSelectedZDelta);
|
||||
float spacing = mUnselectedSpacing + (level * mSelectedSpacingDelta);
|
||||
|
||||
mTargetView.setScaleX(scale);
|
||||
mTargetView.setScaleY(scale);
|
||||
mTargetView.setZ(z);
|
||||
|
||||
mTargetView.setPadding((int) spacing, mTargetView.getPaddingTop(),
|
||||
(int) spacing, mTargetView.getPaddingBottom());
|
||||
}
|
||||
|
||||
public float getFocusProgress() {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.systemui.recents.tv.views;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
@@ -22,12 +23,14 @@ import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.recents.tv.animations.DismissAnimationsHolder;
|
||||
import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
|
||||
import com.android.systemui.recents.model.Task;
|
||||
|
||||
@@ -37,8 +40,10 @@ public class TaskCardView extends LinearLayout {
|
||||
private TextView mTitleTextView;
|
||||
private ImageView mBadgeView;
|
||||
private Task mTask;
|
||||
private boolean mDismissState;
|
||||
|
||||
private ViewFocusAnimator mViewFocusAnimator;
|
||||
private DismissAnimationsHolder mDismissAnimationsHolder;
|
||||
|
||||
public TaskCardView(Context context) {
|
||||
this(context, null);
|
||||
@@ -51,6 +56,7 @@ public class TaskCardView extends LinearLayout {
|
||||
public TaskCardView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mViewFocusAnimator = new ViewFocusAnimator(this);
|
||||
mDismissState = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,6 +64,7 @@ public class TaskCardView extends LinearLayout {
|
||||
mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
|
||||
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
|
||||
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
|
||||
mDismissAnimationsHolder = new DismissAnimationsHolder(this);
|
||||
}
|
||||
|
||||
public void init(Task task) {
|
||||
@@ -98,13 +105,23 @@ public class TaskCardView extends LinearLayout {
|
||||
|
||||
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 height = res.getDimensionPixelOffset(R.dimen.recents_tv_screenshot_height);
|
||||
int heightDelta = (int) (height * scale - height);
|
||||
int topMargin = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_row_top_margin);
|
||||
|
||||
int headerHeight = (int) ((res.getDimensionPixelOffset(
|
||||
R.dimen.recents_tv_card_extra_badge_size) +
|
||||
res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom)) * scale);
|
||||
int headerHeight = res.getDimensionPixelOffset(R.dimen.recents_tv_card_extra_badge_size) +
|
||||
res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom);
|
||||
int headerHeightDelta = (int) (headerHeight * scale - headerHeight);
|
||||
|
||||
int dismissAreaHeight =
|
||||
res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_top_margin) +
|
||||
res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_bottom_margin) +
|
||||
res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_size) +
|
||||
res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_text_size);
|
||||
|
||||
int dismissAreaHeightDelta = (int) (dismissAreaHeight * scale - dismissAreaHeight);
|
||||
|
||||
int totalHeightDelta = heightDelta + headerHeightDelta + dismissAreaHeightDelta;
|
||||
|
||||
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
Display display = wm.getDefaultDisplay();
|
||||
@@ -113,9 +130,72 @@ public class TaskCardView extends LinearLayout {
|
||||
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);
|
||||
return new Rect(screenWidth / 2 - width / 2 - widthDelta / 2,
|
||||
topMargin - totalHeightDelta / 2 + (int) (headerHeight * scale),
|
||||
screenWidth / 2 + width / 2 + widthDelta / 2,
|
||||
topMargin - totalHeightDelta / 2 + (int) (headerHeight * scale) +
|
||||
(int) (height * scale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN : {
|
||||
if (!isInDismissState()) {
|
||||
setDismissState(true);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KeyEvent.KEYCODE_DPAD_UP : {
|
||||
if (isInDismissState()) {
|
||||
setDismissState(false);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//Eat right and left key presses when we are in dismiss state
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT : {
|
||||
if (isInDismissState()) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT : {
|
||||
if (isInDismissState()) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
private void setDismissState(boolean dismissState) {
|
||||
if (mDismissState != dismissState) {
|
||||
mDismissState = dismissState;
|
||||
if (dismissState) {
|
||||
mDismissAnimationsHolder.startEnterAnimation();
|
||||
} else {
|
||||
mDismissAnimationsHolder.startExitAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInDismissState() {
|
||||
return mDismissState;
|
||||
}
|
||||
|
||||
public void startDismissTaskAnimation(Animator.AnimatorListener listener) {
|
||||
mDismissAnimationsHolder.startDismissAnimation(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
setDismissState(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
|
||||
private ArrayList<TaskCardView> mTaskViews = new ArrayList<>();
|
||||
private Task mFocusedTask;
|
||||
|
||||
|
||||
public TaskStackHorizontalGridView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -53,7 +52,7 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
|
||||
setItemMargin((int) getResources().getDimension(R.dimen.recents_tv_gird_card_spacing));
|
||||
setWindowAlignment(WINDOW_ALIGN_NO_EDGE);
|
||||
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
|
||||
super.onAttachedToWindow();
|
||||
}
|
||||
@@ -108,6 +107,13 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
|
||||
return mFocusedTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - The focused task card view.
|
||||
*/
|
||||
public TaskCardView getFocusedTaskCardView() {
|
||||
return ((TaskCardView)findFocus());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param task
|
||||
* @return Child view for given task
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.systemui.recents.tv.views;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.app.Activity;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
@@ -25,6 +26,7 @@ import android.view.ViewGroup;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
|
||||
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
|
||||
import com.android.systemui.recents.model.Task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -39,7 +41,7 @@ public class TaskStackHorizontalViewAdapter extends
|
||||
private static final String TAG = "TaskStackViewAdapter";
|
||||
private List<Task> mTaskList;
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
|
||||
private TaskCardView mTaskCardView;
|
||||
private Task mTask;
|
||||
public ViewHolder(View v) {
|
||||
@@ -58,9 +60,14 @@ public class TaskStackHorizontalViewAdapter extends
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
EventBus.getDefault().send(new LaunchTvTaskEvent(mTaskCardView, mTask,
|
||||
null, INVALID_STACK_ID));
|
||||
((Activity)(v.getContext())).finish();
|
||||
if (mTaskCardView.isInDismissState()) {
|
||||
mTaskCardView.startDismissTaskAnimation(
|
||||
getRemoveAtListener(getAdapterPosition(), mTaskCardView));
|
||||
} else {
|
||||
EventBus.getDefault().send(new LaunchTvTaskEvent(mTaskCardView, mTask,
|
||||
null, INVALID_STACK_ID));
|
||||
((Activity) (v.getContext())).finish();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, v.getContext()
|
||||
.getString(R.string.recents_launch_error_message, mTask.title), e);
|
||||
@@ -97,4 +104,31 @@ public class TaskStackHorizontalViewAdapter extends
|
||||
public int getItemCount() {
|
||||
return mTaskList.size();
|
||||
}
|
||||
|
||||
private Animator.AnimatorListener getRemoveAtListener(final int position,
|
||||
final TaskCardView taskCardView) {
|
||||
return new Animator.AnimatorListener() {
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) { }
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
removeAt(position);
|
||||
EventBus.getDefault().send(new DeleteTaskDataEvent(taskCardView.getTask()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) { }
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) { }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private void removeAt(int position) {
|
||||
mTaskList.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user