Merge "Focus running task in overview grid" into sc-dev

This commit is contained in:
Alex Chau 2021-04-02 03:57:58 +00:00 committed by Android (Google) Code Review
commit 5bd9ba2a80
16 changed files with 353 additions and 129 deletions

View File

@ -14,11 +14,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- NOTE! don't add dimensions for margins / gravity to root view in this file, they need to be
loaded at runtime. -->
<com.android.quickstep.views.GoOverviewActionsView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom">
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/action_buttons"

View File

@ -14,10 +14,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- NOTE! don't add dimensions for margins / gravity to root view in this file, they need to be
loaded at runtime. -->
<com.android.quickstep.views.OverviewActionsView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom">
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/action_buttons"

View File

@ -36,6 +36,7 @@
<dimen name="overview_grid_bottom_margin">90dp</dimen>
<dimen name="overview_grid_side_margin">54dp</dimen>
<dimen name="overview_grid_row_spacing">42dp</dimen>
<dimen name="overview_grid_focus_vertical_margin">130dp</dimen>
<dimen name="split_placeholder_size">110dp</dimen>
<dimen name="recents_page_spacing">16dp</dimen>

View File

@ -103,12 +103,11 @@ public final class RecentsViewStateController extends
private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
LauncherState state) {
float clearAllButtonAlpha = (state.getVisibleElements(mLauncher) & CLEAR_ALL_BUTTON) != 0
? 1 : 0;
float clearAllButtonAlpha = state.areElementsVisible(mLauncher, CLEAR_ALL_BUTTON) ? 1 : 0;
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
clearAllButtonAlpha, LINEAR);
float overviewButtonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_ACTIONS) != 0
? 1 : 0;
float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS)
&& mRecentsView.shouldShowOverviewActionsForState(state) ? 1 : 0;
propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
MultiValueAlpha.VALUE, overviewButtonAlpha, config.getInterpolator(
ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));

View File

@ -18,6 +18,7 @@ package com.android.launcher3.uioverrides.states;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import com.android.launcher3.BaseDraggingActivity;
@ -70,13 +71,12 @@ public class OverviewModalTaskState extends OverviewState {
}
public static float[] getOverviewScaleAndOffsetForModalState(BaseDraggingActivity activity) {
Rect out = new Rect();
activity.<RecentsView>getOverviewPanel().getTaskSize(out);
int taskHeight = out.height();
activity.<RecentsView>getOverviewPanel().getModalTaskSize(out);
int newHeight = out.height();
Point taskSize = activity.<RecentsView>getOverviewPanel().getSelectedTaskSize();
Rect modalTaskSize = new Rect();
activity.<RecentsView>getOverviewPanel().getModalTaskSize(modalTaskSize);
float scale = (float) newHeight / taskHeight;
float scale = Math.min((float) modalTaskSize.height() / taskSize.y,
(float) modalTaskSize.width() / taskSize.x);
return new float[] {scale, NO_OFFSET};
}

View File

@ -99,8 +99,7 @@ public class OverviewState extends LauncherState {
@Override
public int getVisibleElements(Launcher launcher) {
return displayOverviewTasksAsGrid(launcher.getDeviceProfile()) ? CLEAR_ALL_BUTTON
: CLEAR_ALL_BUTTON | OVERVIEW_ACTIONS;
return CLEAR_ALL_BUTTON | OVERVIEW_ACTIONS;
}
@Override

View File

@ -206,18 +206,17 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
Rect gridRect = new Rect();
calculateGridSize(context, dp, gridRect);
int rowSpacing = res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing);
float rowHeight = (gridRect.height() - rowSpacing) / 2f;
int verticalMargin = res.getDimensionPixelSize(
R.dimen.overview_grid_focus_vertical_margin);
float taskHeight = gridRect.height() - verticalMargin * 2;
PointF taskDimension = getTaskDimension(context, dp);
float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / Math.max(
taskDimension.x, taskDimension.y);
float scale = taskHeight / Math.max(taskDimension.x, taskDimension.y);
int outWidth = Math.round(scale * taskDimension.x);
int outHeight = Math.round(scale * taskDimension.y);
int gravity = Gravity.TOP;
int gravity = Gravity.CENTER_VERTICAL;
gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
gridRect.inset(0, dp.overviewTaskThumbnailTopMarginPx, 0, 0);
Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
} else {
int taskMargin = dp.overviewTaskMarginPx;
@ -293,6 +292,30 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
Math.max(insets.right, sideMargin), Math.max(insets.bottom, bottomMargin));
}
/**
* Calculates the overview grid non-focused task size for the provided device configuration.
*/
public final void calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect,
PagedOrientationHandler orientedState) {
Resources res = context.getResources();
Rect gridRect = new Rect();
calculateGridSize(context, dp, gridRect);
int rowSpacing = res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing);
float rowHeight = (gridRect.height() - rowSpacing) / 2f;
PointF taskDimension = getTaskDimension(context, dp);
float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / Math.max(
taskDimension.x, taskDimension.y);
int outWidth = Math.round(scale * taskDimension.x);
int outHeight = Math.round(scale * taskDimension.y);
int gravity = Gravity.TOP;
gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
gridRect.inset(0, dp.overviewTaskThumbnailTopMarginPx, 0, 0);
Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
}
/**
* Calculates the modal taskView size for the provided device configuration
*/

View File

@ -76,7 +76,9 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
float clearAllButtonAlpha = state.hasClearAllButton() ? 1 : 0;
setter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
clearAllButtonAlpha, LINEAR);
float overviewButtonAlpha = state.hasOverviewActions(mActivity) ? 1 : 0;
float overviewButtonAlpha =
state.hasOverviewActions() && mRecentsView.shouldShowOverviewActionsForState(state)
? 1 : 0;
setter.setFloat(mActivity.getActionsView().getVisibilityAlpha(),
MultiValueAlpha.VALUE, overviewButtonAlpha, LINEAR);

View File

@ -42,7 +42,7 @@ import com.android.systemui.shared.recents.model.Task.TaskKey;
import java.util.ArrayList;
@TargetApi(Build.VERSION_CODES.R)
public class FallbackRecentsView extends RecentsView<RecentsActivity>
public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsState>
implements StateListener<RecentsState> {
private RunningTaskInfo mHomeTaskInfo;

View File

@ -99,8 +99,8 @@ public class RecentsState implements BaseState<RecentsState> {
/**
* For this state, whether overview actions should be shown.
*/
public boolean hasOverviewActions(RecentsActivity activity) {
return hasFlag(FLAG_OVERVIEW_ACTIONS) && !showAsGrid(activity.getDeviceProfile());
public boolean hasOverviewActions() {
return hasFlag(FLAG_OVERVIEW_ACTIONS);
}
public float[] getOverviewScaleAndOffset(RecentsActivity activity) {

View File

@ -45,12 +45,13 @@ public class ClearAllButton extends Button implements PageCallbacks {
private float mScrollAlpha = 1;
private float mContentAlpha = 1;
private float mVisibilityAlpha = 1;
private float mFullscreenProgress = 1;
private float mGridProgress = 1;
private boolean mIsRtl;
private float mNormalTranslationPrimary;
private float mFullscreenTranslationPrimary;
private float mGridTranslationPrimary;
private float mGridTranslationSecondary;
private float mGridScrollOffset;
private float mScrollOffsetPrimary;
@ -130,13 +131,13 @@ public class ClearAllButton extends Button implements PageCallbacks {
setClickable(Math.min(alpha, 1) == 1);
}
public void setGridTranslationPrimary(float gridTranslationPrimary) {
mGridTranslationPrimary = gridTranslationPrimary;
public void setFullscreenTranslationPrimary(float fullscreenTranslationPrimary) {
mFullscreenTranslationPrimary = fullscreenTranslationPrimary;
applyPrimaryTranslation();
}
public void setGridTranslationSecondary(float gridTranslationSecondary) {
mGridTranslationSecondary = gridTranslationSecondary;
public void setGridTranslationPrimary(float gridTranslationPrimary) {
mGridTranslationPrimary = gridTranslationPrimary;
applyPrimaryTranslation();
}
@ -148,8 +149,11 @@ public class ClearAllButton extends Button implements PageCallbacks {
mScrollOffsetPrimary = scrollOffsetPrimary;
}
public float getScrollAdjustment(boolean gridEnabled) {
public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
float scrollAdjustment = 0;
if (fullscreenEnabled) {
scrollAdjustment += mFullscreenTranslationPrimary;
}
if (gridEnabled) {
scrollAdjustment += mGridTranslationPrimary + mGridScrollOffset;
}
@ -157,8 +161,18 @@ public class ClearAllButton extends Button implements PageCallbacks {
return scrollAdjustment;
}
public float getOffsetAdjustment(boolean gridEnabled) {
return getScrollAdjustment(gridEnabled);
public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
return getScrollAdjustment(fullscreenEnabled, gridEnabled);
}
/**
* Adjust translation when this TaskView is about to be shown fullscreen.
*
* @param progress: 0 = no translation; 1 = translate according to TaskVIew translations.
*/
public void setFullscreenProgress(float progress) {
mFullscreenProgress = progress;
applyPrimaryTranslation();
}
/**
@ -180,7 +194,8 @@ public class ClearAllButton extends Button implements PageCallbacks {
PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
orientationHandler.getPrimaryViewTranslate().set(this,
orientationHandler.getPrimaryValue(0f, getOriginalTranslationY())
+ mNormalTranslationPrimary + getGridTrans(mGridTranslationPrimary));
+ mNormalTranslationPrimary + getFullscreenTrans(
mFullscreenTranslationPrimary) + getGridTrans(mGridTranslationPrimary));
}
private void applySecondaryTranslation() {
@ -191,8 +206,11 @@ public class ClearAllButton extends Button implements PageCallbacks {
PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
orientationHandler.getSecondaryViewTranslate().set(this,
orientationHandler.getSecondaryValue(0f, getOriginalTranslationY())
+ getGridTrans(mGridTranslationSecondary));
orientationHandler.getSecondaryValue(0f, getOriginalTranslationY()));
}
private float getFullscreenTrans(float endTranslation) {
return mFullscreenProgress > 0 ? endTranslation : 0;
}
private float getGridTrans(float endTranslation) {

View File

@ -19,11 +19,13 @@ import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
@ -35,6 +37,7 @@ import com.android.launcher3.LauncherState;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.systemui.plugins.PluginListener;
@ -44,7 +47,7 @@ import com.android.systemui.plugins.RecentsExtraCard;
* {@link RecentsView} used in Launcher activity
*/
@TargetApi(Build.VERSION_CODES.O)
public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher, LauncherState>
implements StateListener<LauncherState> {
private RecentsExtraCard mRecentsExtraCardPlugin;
@ -234,4 +237,33 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
}
}
}
@Override
protected void onDismissAnimationEnds() {
super.onDismissAnimationEnds();
if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
// We want to keep the tasks translations in this temporary state
// after resetting the rest above
setTaskViewsResistanceTranslation(mTaskViewsSecondaryTranslation);
setTaskViewsPrimaryTranslation(mTaskViewsPrimaryTranslation);
}
}
@Override
public void initiateSplitSelect(TaskView taskView,
SplitConfigurationOptions.SplitPositionOption splitPositionOption) {
super.initiateSplitSelect(taskView, splitPositionOption);
mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// If overview is in modal state when rotate, reset it to overview state without running
// animation.
if (mActivity.isInState(OVERVIEW_MODAL_TASK)) {
mActivity.getStateManager().goToState(LauncherState.OVERVIEW, false);
resetModalVisuals();
}
}
}

View File

@ -16,6 +16,7 @@
package com.android.quickstep.views;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SHARE;
import android.content.Context;
@ -32,6 +33,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.SysUINavigationMode;
@ -76,6 +78,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
private static final int INDEX_VISIBILITY_ALPHA = 1;
private static final int INDEX_FULLSCREEN_ALPHA = 2;
private static final int INDEX_HIDDEN_FLAGS_ALPHA = 3;
private static final int INDEX_SCROLL_ALPHA = 4;
private final MultiValueAlpha mMultiValueAlpha;
@ -87,6 +90,9 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
protected T mCallbacks;
private float mModalness;
private float mModalTransformY;
public OverviewActionsView(Context context) {
this(context, null);
}
@ -97,7 +103,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
public OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, 0);
mMultiValueAlpha = new MultiValueAlpha(this, 4);
mMultiValueAlpha = new MultiValueAlpha(this, 5);
mMultiValueAlpha.setUpdateVisibility(true);
}
@ -189,6 +195,10 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA);
}
public AlphaProperty getScrollAlpha() {
return mMultiValueAlpha.getProperty(INDEX_SCROLL_ALPHA);
}
private void updateHorizontalPadding() {
setPadding(mInsets.left, 0, mInsets.right, 0);
}
@ -224,4 +234,27 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
bottomMargin += mInsets.bottom;
return bottomMargin;
}
/**
* The current task is fully modal (modalness = 1) when it is shown on its own in a modal
* way. Modalness 0 means the task is shown in context with all the other tasks.
*/
public void setTaskModalness(float modalness) {
mModalness = modalness;
applyTranslationY();
}
public void setModalTransformY(float modalTransformY) {
mModalTransformY = modalTransformY;
applyTranslationY();
}
private void applyTranslationY() {
setTranslationY(getModalTrans(mModalTransformY));
}
private float getModalTrans(float endTranslation) {
float progress = ACCEL_DEACCEL.getInterpolation(mModalness);
return Utilities.mapRange(progress, 0, endTranslation);
}
}

View File

@ -25,8 +25,6 @@ import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARA
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.mapToRange;
@ -81,6 +79,7 @@ import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@ -91,6 +90,7 @@ import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.ListView;
import androidx.annotation.Nullable;
@ -100,7 +100,6 @@ import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherState;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@ -111,6 +110,7 @@ import com.android.launcher3.anim.SpringProperty;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
@ -161,8 +161,9 @@ import java.util.function.Consumer;
* A list of recent tasks.
*/
@TargetApi(Build.VERSION_CODES.R)
public abstract class RecentsView<T extends StatefulActivity> extends PagedView implements
Insettable, TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>,
STATE_TYPE extends BaseState<STATE_TYPE>> extends PagedView implements Insettable,
TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener,
SplitScreenBounds.OnChangeListener {
@ -295,7 +296,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
};
protected final RecentsOrientedState mOrientationState;
protected final BaseActivityInterface mSizeStrategy;
protected final BaseActivityInterface<STATE_TYPE, ACTIVITY_TYPE> mSizeStrategy;
protected RecentsAnimationController mRecentsAnimationController;
protected SurfaceTransactionApplier mSyncTransactionApplier;
protected int mTaskWidth;
@ -304,6 +305,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
protected final TaskViewSimulator mLiveTileTaskViewSimulator;
protected final Rect mLastComputedTaskSize = new Rect();
protected final Rect mLastComputedGridSize = new Rect();
protected final Rect mLastComputedGridTaskSize = new Rect();
// How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot.
protected Float mLastComputedTaskPushOutDistance = null;
protected boolean mEnableDrawingLiveTile = false;
@ -317,10 +319,11 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
// The threshold at which we update the SystemUI flags when animating from the task into the app
public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f;
protected final T mActivity;
protected final ACTIVITY_TYPE mActivity;
private final float mFastFlingVelocity;
private final RecentsModel mModel;
private final int mRowSpacing;
private final int mGridSideMargin;
private final ClearAllButton mClearAllButton;
private final Rect mClearAllButtonDeadZoneRect = new Rect();
private final Rect mTaskViewDeadZoneRect = new Rect();
@ -347,8 +350,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
private boolean mOverviewFullscreenEnabled;
private float mAdjacentPageOffset = 0;
private float mTaskViewsSecondaryTranslation = 0;
private float mTaskViewsPrimaryTranslation = 0;
protected float mTaskViewsSecondaryTranslation = 0;
protected float mTaskViewsPrimaryTranslation = 0;
// Progress from 0 to 1 where 0 is a carousel and 1 is a 2 row grid.
private float mGridProgress = 0;
@ -436,6 +439,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
protected int mRunningTaskId = -1;
protected boolean mRunningTaskTileHidden;
private Task mTmpRunningTask;
protected int mFocusedTaskId = -1;
private float mFocusedTaskRatio;
private boolean mRunningTaskIconScaledDown = false;
@ -542,6 +547,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mRowSpacing = getResources().getDimensionPixelSize(R.dimen.overview_grid_row_spacing);
mGridSideMargin = getResources().getDimensionPixelSize(R.dimen.overview_grid_side_margin);
mSquaredTouchSlop = squaredTouchSlop(context);
mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
@ -648,7 +654,6 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mActionsView = actionsView;
mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, getTaskViewCount() == 0);
mSplitPlaceholderView = splitPlaceholderView;
}
public SplitPlaceholderView getSplitPlaceholder() {
@ -1129,6 +1134,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
for (int i = 0; i < taskCount; i++) {
getTaskViewAt(i).setFullscreenProgress(mFullscreenProgress);
}
mClearAllButton.setFullscreenProgress(fullscreenProgress);
// Fade out the actions view quickly (0.1 range)
mActionsView.getFullscreenAlpha().setValue(
@ -1168,9 +1174,31 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mSizeStrategy.calculateGridSize(mActivity, mActivity.getDeviceProfile(),
mLastComputedGridSize);
mSizeStrategy.calculateGridTaskSize(mActivity, mActivity.getDeviceProfile(),
mLastComputedGridTaskSize, mOrientationHandler);
// Force TaskView to update size from thumbnail
updateTaskSize();
// Update ActionsView position
FrameLayout.LayoutParams layoutParams =
(FrameLayout.LayoutParams) mActionsView.getLayoutParams();
if (dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
layoutParams.gravity = Gravity.BOTTOM;
layoutParams.bottomMargin =
dp.heightPx - mInsets.bottom - mLastComputedGridSize.bottom;
layoutParams.leftMargin = mLastComputedTaskSize.left;
layoutParams.rightMargin = dp.widthPx - mLastComputedTaskSize.right;
// When in modal state, remove bottom margin to avoid covering content.
mActionsView.setModalTransformY(layoutParams.bottomMargin);
} else {
layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
layoutParams.bottomMargin = 0;
layoutParams.leftMargin = 0;
layoutParams.rightMargin = 0;
mActionsView.setModalTransformY(0);
}
mActionsView.setLayoutParams(layoutParams);
}
/**
@ -1211,6 +1239,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
getTaskViewAt(i).setFullscreenTranslationX(
fullscreenTranslations[i] - fullscreenTranslations[firstNonHomeTaskIndex]);
}
mClearAllButton.setFullscreenTranslationPrimary(
accumulatedTranslationX - fullscreenTranslations[firstNonHomeTaskIndex]);
// Align ClearAllButton to the left (RTL) or right (non-RTL), which is different from other
// TaskViews.
@ -1226,11 +1256,36 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mLastComputedTaskSize.set(outRect);
}
/**
* Returns the size of task selected to enter modal state.
*/
public Point getSelectedTaskSize() {
mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), mTempRect,
mOrientationHandler);
int taskWidth = mTempRect.width();
int taskHeight = mTempRect.height();
if (mRunningTaskId != -1) {
int boxLength = Math.max(taskWidth, taskHeight);
if (mFocusedTaskRatio > 1) {
taskWidth = boxLength;
taskHeight = (int) (boxLength / mFocusedTaskRatio);
} else {
taskWidth = (int) (boxLength * mFocusedTaskRatio);
taskHeight = boxLength;
}
}
return new Point(taskWidth, taskHeight);
}
/** Gets the last computed task size */
public Rect getLastComputedTaskSize() {
return mLastComputedTaskSize;
}
public Rect getLastComputedGridTaskSize() {
return mLastComputedGridTaskSize;
}
/** Gets the task size for modal state. */
public void getModalTaskSize(Rect outRect) {
mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
@ -1249,6 +1304,15 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
// After scrolling, update the visible task's data
loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
// After scrolling, update ActionsView's visibility.
TaskView focusedTaskView = getFocusedTaskView();
if (focusedTaskView != null) {
float scrollDiff = Math.abs(getScrollForPage(indexOfChild(focusedTaskView))
- mOrientationHandler.getPrimaryScroll(this));
float delta = (mGridSideMargin - scrollDiff) / (float) mGridSideMargin;
mActionsView.getScrollAlpha().setValue(Utilities.boundToRange(delta, 0, 1));
}
}
// Update the high res thumbnail loader state
@ -1413,6 +1477,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
setCurrentTask(-1);
mIgnoreResetTaskId = -1;
mTaskListChangeId = -1;
mFocusedTaskId = -1;
mRecentsAnimationController = null;
mLiveTileParams.setTargetSet(null);
@ -1439,6 +1504,17 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
return getTaskIndexForId(mRunningTaskId);
}
public @Nullable TaskView getFocusedTaskView() {
return getTaskView(mFocusedTaskId);
}
/**
* Returns the width to height ratio of the focused {@link TaskView}.
*/
public float getFocusedTaskRatio() {
return mFocusedTaskRatio;
}
/**
* Get the index of the task view whose id matches {@param taskId}.
* @return -1 if there is no task view for the task id, else the index of the task view.
@ -1530,6 +1606,11 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
*/
public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) {
mCurrentGestureEndTarget = endTarget;
if (showAsGrid()) {
mFocusedTaskId = mRunningTaskId;
mFocusedTaskRatio =
mLastComputedTaskSize.width() / (float) mLastComputedTaskSize.height();
}
}
/**
@ -1550,8 +1631,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
setRunningTaskHidden(false);
animateUpRunningTaskIconScale();
// TODO: This should be tied to whether there is a focus app on overview.
if (!showAsGrid()) {
if (!showAsGrid() || getFocusedTaskView() != null) {
animateActionsViewIn();
}
@ -1671,6 +1751,13 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
anim.start();
}
private void animateActionsViewOut() {
ObjectAnimator anim = ObjectAnimator.ofFloat(
mActionsView.getVisibilityAlpha(), MultiValueAlpha.VALUE, 1, 0);
anim.setDuration(TaskView.SCALE_ICON_DURATION);
anim.start();
}
public void animateUpRunningTaskIconScale() {
animateUpRunningTaskIconScale(0);
}
@ -1696,8 +1783,12 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
return;
}
final int boxLength = Math.max(mTaskWidth, mTaskHeight);
final int boxLength = Math.max(mLastComputedGridTaskSize.width(),
mLastComputedGridTaskSize.height());
int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
float heightOffset = (boxLength + taskTopMargin) + mRowSpacing;
float taskGridVerticalDiff = mLastComputedGridTaskSize.top - mLastComputedTaskSize.top;
int topRowWidth = 0;
int bottomRowWidth = 0;
float topAccumulatedTranslationX = 0;
@ -1720,15 +1811,23 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
}
// Evenly distribute tasks between rows unless rearranging due to task dismissal, in
// which case keep tasks in their respective rows.
if ((!isTaskDismissal && topRowWidth <= bottomRowWidth) || (isTaskDismissal && mTopIdSet
.contains(taskView.getTask().key.id))) {
// which case keep tasks in their respective rows. For the running task, don't join
// the grid.
if (taskView.isRunningTask()) {
topRowWidth += taskView.getLayoutParams().width + mPageSpacing;
bottomRowWidth += taskView.getLayoutParams().width + mPageSpacing;
// Center view vertically in case it's from different orientation.
taskView.setGridTranslationY((mLastComputedTaskSize.height() + taskTopMargin
- taskView.getLayoutParams().height) / 2f);
} else if ((!isTaskDismissal && topRowWidth <= bottomRowWidth) || (isTaskDismissal
&& mTopIdSet.contains(taskView.getTask().key.id))) {
gridTranslations[i] += topAccumulatedTranslationX;
topRowWidth += taskView.getLayoutParams().width + mPageSpacing;
topSet.add(i);
mTopIdSet.add(taskView.getTask().key.id);
taskView.setGridTranslationY(0);
taskView.setGridTranslationY(taskGridVerticalDiff);
// Move horizontally into empty space.
float widthOffset = 0;
@ -1745,8 +1844,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
bottomSet.add(i);
// Move into bottom row.
float heightOffset = (boxLength + taskTopMargin) + mRowSpacing;
taskView.setGridTranslationY(heightOffset);
taskView.setGridTranslationY(heightOffset + taskGridVerticalDiff);
// Move horizontally into empty space.
float widthOffset = 0;
@ -1804,8 +1902,6 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mClearAllButton.setGridTranslationPrimary(
clearAllTotalTranslationX - gridTranslations[firstNonHomeTaskIndex]);
mClearAllButton.setGridTranslationSecondary(
boxLength - mTaskHeight / 2f + mRowSpacing / 2f);
mClearAllButton.setGridScrollOffset(
mIsRtl ? mLastComputedTaskSize.left - mLastComputedGridSize.left
: mLastComputedTaskSize.right - mLastComputedGridSize.right);
@ -2082,24 +2178,25 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
snapToPageImmediately(pageToSnapTo);
// Grid got messed up, reapply.
updateGridProperties(true);
if (showAsGrid() && getFocusedTaskView() == null) {
animateActionsViewOut();
}
}
// Update the layout synchronously so that the position of next view is
// immediately available.
onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom());
}
resetTaskVisuals();
if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
// We want to keep the tasks translations in this temporary state
// after resetting the rest above
setTaskViewsResistanceTranslation(mTaskViewsSecondaryTranslation);
setTaskViewsPrimaryTranslation(mTaskViewsPrimaryTranslation);
}
onDismissAnimationEnds();
mPendingAnimation = null;
}
});
return anim;
}
protected void onDismissAnimationEnds() {
}
public PendingAnimation createAllTasksDismissAnimation(long duration) {
if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
@ -2267,13 +2364,6 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
if (mOrientationState.setRecentsRotation(rotation)) {
updateOrientationHandler();
}
// If overview is in modal state when rotate, reset it to overview state without running
// animation.
if (mActivity.isInState(OVERVIEW_MODAL_TASK)) {
mActivity.getStateManager().goToState(LauncherState.OVERVIEW, false);
resetModalVisuals();
}
}
public void setLayoutRotation(int touchRotation, int displayRotation) {
@ -2485,7 +2575,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
return distanceToOffscreen * offsetProgress;
}
private void setTaskViewsResistanceTranslation(float translation) {
protected void setTaskViewsResistanceTranslation(float translation) {
mTaskViewsSecondaryTranslation = translation;
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView task = getTaskViewAt(i);
@ -2494,7 +2584,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mLiveTileTaskViewSimulator.recentsViewSecondaryTranslation.value = translation;
}
private void setTaskViewsPrimaryTranslation(float translation) {
protected void setTaskViewsPrimaryTranslation(float translation) {
mTaskViewsPrimaryTranslation = translation;
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView task = getTaskViewAt(i);
@ -2533,7 +2623,6 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mSplitPlaceholderView.getSplitController().setInitialTaskSelect(taskView,
splitPositionOption);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
}
public PendingAnimation createSplitSelectInitAnimation() {
@ -2964,10 +3053,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
* Returns page scroll of the left most child.
*/
public int getLeftMostChildScroll() {
if (mIsRtl) {
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
}
return getScrollForPage(mTaskViewStartIndex);
return getScrollForPage(mIsRtl ? indexOfChild(mClearAllButton) : mTaskViewStartIndex);
}
@Override
@ -2978,10 +3064,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
// so use the rightmost task as the min scroll.
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
}
if (mIsRtl) {
return getScrollForPage(mTaskViewStartIndex);
}
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
return getScrollForPage(mIsRtl ? mTaskViewStartIndex : indexOfChild(mClearAllButton));
}
return super.computeMaxScroll();
}
@ -3000,7 +3083,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
scrollDiff = ((TaskView) child).getScrollAdjustment(mOverviewFullscreenEnabled,
showAsGrid());
} else if (child instanceof ClearAllButton) {
scrollDiff = ((ClearAllButton) child).getScrollAdjustment(showAsGrid());
scrollDiff = ((ClearAllButton) child).getScrollAdjustment(
mOverviewFullscreenEnabled, showAsGrid());
}
if (scrollDiff != 0) {
@ -3019,7 +3103,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
childOffset += ((TaskView) child).getOffsetAdjustment(mOverviewFullscreenEnabled,
showAsGrid());
} else if (child instanceof ClearAllButton) {
childOffset += ((ClearAllButton) child).getOffsetAdjustment(showAsGrid());
childOffset += ((ClearAllButton) child).getOffsetAdjustment(mOverviewFullscreenEnabled,
showAsGrid());
}
return childOffset;
}
@ -3195,6 +3280,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
boolean inPlaceLandscape = !mOrientationState.canRecentsActivityRotate()
&& mOrientationState.getTouchRotation() != ROTATION_0;
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, modalness < 1 && inPlaceLandscape);
mActionsView.setTaskModalness(modalness);
}
@Nullable
@ -3229,6 +3315,11 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mCurrentGestureEndTarget).displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
}
public boolean shouldShowOverviewActionsForState(STATE_TYPE state) {
return !state.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())
|| getFocusedTaskView() != null;
}
/**
* Used to register callbacks for when our empty message state changes.
*

View File

@ -987,7 +987,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
return scrollAdjustment;
}
public float getOffsetAdjustment(boolean fullscreenEnabled,boolean gridEnabled) {
public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
return getScrollAdjustment(fullscreenEnabled, gridEnabled);
}
@ -1213,62 +1213,77 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
*/
void updateTaskSize() {
ViewGroup.LayoutParams params = getLayoutParams();
float fullscreenScale;
float boxTranslationY;
int expectedWidth;
int expectedHeight;
if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
final int thumbnailPadding =
mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
final Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
final int taskWidth = lastComputedTaskSize.width();
final int taskHeight = lastComputedTaskSize.height();
Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
int taskWidth = lastComputedTaskSize.width();
int taskHeight = lastComputedTaskSize.height();
int expectedWidth;
int expectedHeight;
float thumbnailRatio = mTask != null ? mTask.getVisibleThumbnailRatio(
TaskView.CLIP_STATUS_AND_NAV_BARS) : 0f;
if (isRunningTask() || thumbnailRatio == 0f) {
expectedWidth = taskWidth;
expectedHeight = taskHeight + thumbnailPadding;
int boxWidth;
int boxHeight;
float thumbnailRatio;
boolean isFocusedTask = isFocusedTask();
if (isFocusedTask || isRunningTask()) {
// Task will be focused and should use focused task size. Use runningTaskRatio
// that is associated with the original orientation of the focused task if possible.
boxWidth = taskWidth;
boxHeight = taskHeight;
thumbnailRatio = isFocusedTask ? getRecentsView().getFocusedTaskRatio() : 0;
} else {
int boxLength = Math.max(taskWidth, taskHeight);
if (thumbnailRatio > 1) {
expectedWidth = boxLength;
expectedHeight = (int) (boxLength / thumbnailRatio) + thumbnailPadding;
} else {
expectedWidth = (int) (boxLength * thumbnailRatio);
expectedHeight = boxLength + thumbnailPadding;
}
// Otherwise task is in grid, and should use lastComputedGridTaskSize.
Rect lastComputedGridTaskSize = getRecentsView().getLastComputedGridTaskSize();
boxWidth = lastComputedGridTaskSize.width();
boxHeight = lastComputedGridTaskSize.height();
thumbnailRatio = mTask != null ? mTask.getVisibleThumbnailRatio(
TaskView.CLIP_STATUS_AND_NAV_BARS) : 0f;
}
int boxLength = Math.max(boxWidth, boxHeight);
// Bound width/height to the box size.
if (thumbnailRatio == 0f) {
expectedWidth = boxWidth;
expectedHeight = boxHeight + thumbnailPadding;
} else if (thumbnailRatio > 1) {
expectedWidth = boxLength;
expectedHeight = (int) (boxLength / thumbnailRatio) + thumbnailPadding;
} else {
expectedWidth = (int) (boxLength * thumbnailRatio);
expectedHeight = boxLength + thumbnailPadding;
}
float heightDiff = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f;
setBoxTranslationY(heightDiff);
// Scale to to fit task Rect.
fullscreenScale = taskWidth / (float) boxWidth;
float fullscreenScale = 1f;
if (expectedWidth > taskWidth) {
// In full screen, expectedWidth should not be larger than taskWidth.
fullscreenScale = taskWidth / (float) expectedWidth;
} else if (expectedHeight - thumbnailPadding > taskHeight) {
// In full screen, expectedHeight should not be larger than taskHeight.
fullscreenScale = taskHeight / (float) (expectedHeight - thumbnailPadding);
// In full screen, scale back TaskView to original size.
if (expectedWidth > boxWidth) {
fullscreenScale *= boxWidth / (float) expectedWidth;
} else if (expectedHeight - thumbnailPadding > boxHeight) {
fullscreenScale *= boxHeight / (float) (expectedHeight - thumbnailPadding);
}
setFullscreenScale(fullscreenScale);
if (params.width != expectedWidth || params.height != expectedHeight) {
params.width = expectedWidth;
params.height = expectedHeight;
setLayoutParams(params);
}
// Align to top of task Rect.
boxTranslationY = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f;
} else {
setBoxTranslationY(0);
setFullscreenScale(1);
if (params.width != ViewGroup.LayoutParams.MATCH_PARENT) {
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
setLayoutParams(params);
}
fullscreenScale = 1f;
boxTranslationY = 0f;
expectedWidth = ViewGroup.LayoutParams.MATCH_PARENT;
expectedHeight = ViewGroup.LayoutParams.MATCH_PARENT;
}
setFullscreenScale(fullscreenScale);
setBoxTranslationY(boxTranslationY);
if (params.width != expectedWidth || params.height != expectedHeight) {
params.width = expectedWidth;
params.height = expectedHeight;
setLayoutParams(params);
}
}
private float getFullscreenTrans(float endTranslation) {
float progress = ACCEL_DEACCEL.getInterpolation(mFullscreenProgress);
return Utilities.mapRange(progress, 0, endTranslation);
@ -1281,6 +1296,13 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
return this == getRecentsView().getRunningTaskView();
}
public boolean isFocusedTask() {
if (getRecentsView() == null) {
return false;
}
return this == getRecentsView().getFocusedTaskView();
}
public void setShowScreenshot(boolean showScreenshot) {
mShowScreenshot = showScreenshot;
}

View File

@ -14,6 +14,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- NOTE! don't add dimensions for margins / gravity to root view in this file, they need to be
loaded at runtime. -->
<Space
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"