Merge "Add funtional animation for SplitSelect from Grid." into sc-dev

This commit is contained in:
TreeHugger Robot
2021-05-05 19:03:47 +00:00
committed by Android (Google) Code Review
9 changed files with 255 additions and 75 deletions
+7 -6
View File
@@ -15,12 +15,6 @@
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<com.android.quickstep.views.SplitPlaceholderView
android:id="@+id/split_placeholder"
android:layout_width="match_parent"
android:layout_height="@dimen/split_placeholder_size"
android:background="@android:color/darker_gray"
android:visibility="gone" />
<com.android.quickstep.views.LauncherRecentsView
android:id="@+id/overview_panel"
@@ -31,6 +25,13 @@
android:clipToPadding="false"
android:visibility="invisible" />
<com.android.quickstep.views.SplitPlaceholderView
android:id="@+id/split_placeholder"
android:layout_width="match_parent"
android:layout_height="@dimen/split_placeholder_size"
android:background="@android:color/darker_gray"
android:visibility="gone" />
<include
android:id="@+id/overview_actions_view"
layout="@layout/overview_actions_container" />
@@ -22,12 +22,12 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FA
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import android.util.FloatProperty;
@@ -97,10 +97,10 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
PagedOrientationHandler orientationHandler =
((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
FloatProperty taskViewsFloat = orientationHandler.getSplitSelectTaskOffset(
TASK_PRIMARY_TRANSLATION, TASK_SECONDARY_TRANSLATION, mLauncher.getDeviceProfile());
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mLauncher.getDeviceProfile());
setter.setFloat(mRecentsView, taskViewsFloat,
toState.getOverviewSecondaryTranslation(mLauncher),
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
toState.getOverviewSecondaryTranslation(mLauncher), LINEAR);
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
@@ -25,6 +25,7 @@ import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITIO
import android.animation.AnimatorSet;
import android.app.ActivityOptions;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -64,6 +65,7 @@ public class SplitSelectStateController {
private final SystemUiProxy mSystemUiProxy;
private TaskView mInitialTaskView;
private SplitPositionOption mInitialPosition;
private Rect mInitialBounds;
private final Handler mHandler;
public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) {
@@ -74,9 +76,11 @@ public class SplitSelectStateController {
/**
* To be called after first task selected
*/
public void setInitialTaskSelect(TaskView taskView, SplitPositionOption positionOption) {
public void setInitialTaskSelect(TaskView taskView, SplitPositionOption positionOption,
Rect initialBounds) {
mInitialTaskView = taskView;
mInitialPosition = positionOption;
mInitialBounds = initialBounds;
}
/**
@@ -220,9 +224,14 @@ public class SplitSelectStateController {
public void resetState() {
mInitialTaskView = null;
mInitialPosition = null;
mInitialBounds = null;
}
public boolean isSplitSelectActive() {
return mInitialTaskView != null;
}
public Rect getInitialBounds() {
return mInitialBounds;
}
}
@@ -245,8 +245,8 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher, Laun
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);
setTaskViewsPrimarySplitTranslation(mTaskViewsPrimarySplitTranslation);
setTaskViewsSecondarySplitTranslation(mTaskViewsSecondarySplitTranslation);
}
}
@@ -254,16 +254,29 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* more specific, we'd want to create a similar FloatProperty just for a TaskView's
* offsetX/Y property
*/
public static final FloatProperty<RecentsView> TASK_PRIMARY_TRANSLATION =
new FloatProperty<RecentsView>("taskPrimaryTranslation") {
public static final FloatProperty<RecentsView> TASK_PRIMARY_SPLIT_TRANSLATION =
new FloatProperty<RecentsView>("taskPrimarySplitTranslation") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.setTaskViewsPrimaryTranslation(v);
recentsView.setTaskViewsPrimarySplitTranslation(v);
}
@Override
public Float get(RecentsView recentsView) {
return recentsView.mTaskViewsPrimaryTranslation;
return recentsView.mTaskViewsPrimarySplitTranslation;
}
};
public static final FloatProperty<RecentsView> TASK_SECONDARY_SPLIT_TRANSLATION =
new FloatProperty<RecentsView>("taskSecondarySplitTranslation") {
@Override
public void setValue(RecentsView recentsView, float v) {
recentsView.setTaskViewsSecondarySplitTranslation(v);
}
@Override
public Float get(RecentsView recentsView) {
return recentsView.mTaskViewsSecondarySplitTranslation;
}
};
@@ -279,7 +292,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
view.mLiveTileTaskViewSimulator.recentsViewScale.value = scale;
view.updatePageOffsets();
view.setTaskViewsResistanceTranslation(view.mTaskViewsSecondaryTranslation);
view.setTaskViewsPrimaryTranslation(view.mTaskViewsPrimaryTranslation);
}
@Override
@@ -363,7 +375,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
private float mAdjacentPageOffset = 0;
protected float mTaskViewsSecondaryTranslation = 0;
protected float mTaskViewsPrimaryTranslation = 0;
protected float mTaskViewsPrimarySplitTranslation = 0;
protected float mTaskViewsSecondarySplitTranslation = 0;
// Progress from 0 to 1 where 0 is a carousel and 1 is a 2 row grid.
private float mGridProgress = 0;
private final IntSet mTopRowIdSet = new IntSet();
@@ -1848,15 +1861,28 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
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;
/*
* taskGridVerticalDiff is used to position the top of a task in the top row of the grid
* heightOffset is the vertical space one grid task takes + space between top and
* bottom row
* Summed together they provide the top position for bottom row of grid tasks
*/
final float taskGridVerticalDiff =
mLastComputedGridTaskSize.top - mLastComputedTaskSize.top;
final float heightOffset = (boxLength + taskTopMargin) + mRowSpacing;
int topRowWidth = 0;
int bottomRowWidth = 0;
float topAccumulatedTranslationX = 0;
float bottomAccumulatedTranslationX = 0;
// Contains whether the child index is in top or bottom of grid (for non-focused task)
// Different from mTopRowIdSet, which contains the taskId of what task is in top row
IntSet topSet = new IntSet();
IntSet bottomSet = new IntSet();
// Horizontal grid translation for each task
float[] gridTranslations = new float[taskCount];
int focusedTaskIndex = Integer.MAX_VALUE;
@@ -1910,7 +1936,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
boolean isTopRow = isTaskDismissal ? mTopRowIdSet.contains(taskId)
: topRowWidth <= bottomRowWidth;
if (isTopRow) {
gridTranslations[i] += topAccumulatedTranslationX;
topRowWidth += taskWidthAndSpacing;
topSet.add(i);
mTopRowIdSet.add(taskId);
@@ -1926,11 +1951,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing;
}
float gridTranslationX = mIsRtl ? widthOffset : -widthOffset;
gridTranslations[i] += gridTranslationX;
topAccumulatedTranslationX += gridTranslationX;
float currentTaskTranslationX = mIsRtl ? widthOffset : -widthOffset;
gridTranslations[i] += topAccumulatedTranslationX + currentTaskTranslationX;
topAccumulatedTranslationX += currentTaskTranslationX;
} else {
gridTranslations[i] += bottomAccumulatedTranslationX;
bottomRowWidth += taskWidthAndSpacing;
bottomSet.add(i);
@@ -1946,9 +1970,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing;
}
float gridTranslationX = mIsRtl ? widthOffset : -widthOffset;
gridTranslations[i] += gridTranslationX;
bottomAccumulatedTranslationX += gridTranslationX;
float currentTaskTranslationX = mIsRtl ? widthOffset : -widthOffset;
gridTranslations[i] += bottomAccumulatedTranslationX + currentTaskTranslationX;
bottomAccumulatedTranslationX += currentTaskTranslationX;
}
if (taskView == snappedTaskView) {
snappedTaskRowWidth = isTopRow ? topRowWidth : bottomRowWidth;
@@ -2139,18 +2163,43 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// Use setFloat instead of setViewAlpha as we want to keep the view visible even when it's
// alpha is set to 0 so that it can be recycled in the view pool properly
anim.setFloat(taskView, VIEW_ALPHA, 0, ACCEL_2);
FloatProperty<TaskView> secondaryViewTranslate =
taskView.getSecondaryDissmissTranslationProperty();
int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
int verticalFactor = mOrientationHandler.getSecondaryTranslationDirectionFactor();
SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
ResourceProvider rp = DynamicResource.provider(mActivity);
SpringProperty sp = new SpringProperty(SpringProperty.FLAG_CAN_SPRING_ON_START)
.setDampingRatio(rp.getFloat(R.dimen.dismiss_task_trans_y_damping_ratio))
.setStiffness(rp.getFloat(R.dimen.dismiss_task_trans_y_stiffness));
FloatProperty<TaskView> dismissingTaskViewTranslate =
taskView.getSecondaryDissmissTranslationProperty();;
// TODO(b/186800707) translate entire grid size distance
int translateDistance = mOrientationHandler.getSecondaryDimension(taskView);
int positiveNegativeFactor = mOrientationHandler.getSecondaryTranslationDirectionFactor();
if (splitController.isSplitSelectActive()) {
// Have the task translate towards whatever side was just pinned
int dir = mOrientationHandler.getSplitTaskViewDismissDirection(splitController
.getActiveSplitPositionOption(), mActivity.getDeviceProfile());
switch (dir) {
case PagedOrientationHandler.SPLIT_TRANSLATE_SECONDARY_NEGATIVE:
dismissingTaskViewTranslate = taskView
.getSecondaryDissmissTranslationProperty();
positiveNegativeFactor = -1;
break;
anim.add(ObjectAnimator.ofFloat(taskView, secondaryViewTranslate,
verticalFactor * secondaryTaskDimension).setDuration(duration), LINEAR, sp);
case PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_POSITIVE:
dismissingTaskViewTranslate = taskView.getPrimaryDismissTranslationProperty();
positiveNegativeFactor = 1;
break;
case PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_NEGATIVE:
dismissingTaskViewTranslate = taskView.getPrimaryDismissTranslationProperty();
positiveNegativeFactor = -1;
break;
default:
throw new IllegalStateException("Invalid split task translation: " + dir);
}
}
anim.add(ObjectAnimator.ofFloat(taskView, dismissingTaskViewTranslate,
positiveNegativeFactor * translateDistance).setDuration(duration), LINEAR, sp);
if (LIVE_TILE.get() && taskView.isRunningTask()) {
anim.addOnFrameCallback(() -> {
@@ -2215,18 +2264,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
}
// Additional offset for fake landscape, if the pinning happens to the right or
// left, we need to scroll all the tasks away from the direction of the splaceholder
// view
if (isSplitSelectionActive()) {
int splitPosition = getSplitPlaceholder().getSplitController()
.getActiveSplitPositionOption().mStagePosition;
int direction = mOrientationHandler
.getSplitTranslationDirectionFactor(splitPosition);
int splitOffset = mOrientationHandler.getSplitAnimationTranslation(
mSplitPlaceholderView.getHeight(), mActivity.getDeviceProfile());
offset += direction * splitOffset;
}
int scrollDiff = newScroll[i] - oldScroll[i] + offset;
if (scrollDiff != 0) {
FloatProperty translationProperty = child instanceof TaskView
@@ -2769,13 +2806,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mLiveTileTaskViewSimulator.recentsViewSecondaryTranslation.value = translation;
}
protected void setTaskViewsPrimaryTranslation(float translation) {
mTaskViewsPrimaryTranslation = translation;
protected void setTaskViewsPrimarySplitTranslation(float translation) {
mTaskViewsPrimarySplitTranslation = translation;
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView task = getTaskViewAt(i);
task.getPrimaryDismissTranslationProperty().set(task, translation / getScaleY());
task.getPrimarySplitTranslationProperty().set(task, translation);
}
}
protected void setTaskViewsSecondarySplitTranslation(float translation) {
mTaskViewsSecondarySplitTranslation = translation;
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView task = getTaskViewAt(i);
task.getSecondarySplitTranslationProperty().set(task, translation);
}
mLiveTileTaskViewSimulator.recentsViewPrimaryTranslation.value = translation;
}
/**
@@ -2798,8 +2842,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
public void initiateSplitSelect(TaskView taskView, SplitPositionOption splitPositionOption) {
mSplitHiddenTaskView = taskView;
SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
splitController.setInitialTaskSelect(taskView,
splitPositionOption);
Rect initialBounds = new Rect(taskView.getLeft(), taskView.getTop(), taskView.getRight(),
taskView.getBottom());
splitController.setInitialTaskSelect(taskView, splitPositionOption, initialBounds);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
mSplitPlaceholderView.setLayoutParams(
splitController.getLayoutParamsForActivePosition(getResources(),
@@ -2819,7 +2864,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
public PendingAnimation cancelSplitSelect(boolean animate) {
mSplitPlaceholderView.getSplitController().resetState();
SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
SplitPositionOption splitOption = splitController.getActiveSplitPositionOption();
Rect initialBounds = splitController.getInitialBounds();
splitController.resetState();
int duration = mActivity.getStateManager().getState().getTransitionDuration(getContext());
PendingAnimation pendingAnim = new PendingAnimation(duration);
if (!animate) {
@@ -2834,8 +2882,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
getPageScrolls(oldScroll, false,
view -> view.getVisibility() != GONE && view != mSplitHiddenTaskView);
// x is correct, y is before tasks move up
int[] locationOnScreen = mSplitHiddenTaskView.getLocationOnScreen();
int[] newScroll = new int[getChildCount()];
getPageScrolls(newScroll, false, SIMPLE_SCROLL_LOGIC);
@@ -2843,20 +2889,42 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
for (int i = mSplitHiddenTaskViewIndex; i >= 0; i--) {
View child = getChildAt(i);
if (child == mSplitHiddenTaskView) {
TaskView taskView = (TaskView) child;
int left = newScroll[i] + getPaddingStart();
int topMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
int top = -mSplitHiddenTaskView.getHeight() - locationOnScreen[1];
mSplitHiddenTaskView.layout(left, top,
left + mSplitHiddenTaskView.getWidth(),
top + mSplitHiddenTaskView.getHeight());
pendingAnim.add(ObjectAnimator.ofFloat(mSplitHiddenTaskView, TRANSLATION_Y,
-top + mSplitPlaceholderView.getHeight() - topMargin));
int dir = mOrientationHandler.getSplitTaskViewDismissDirection(splitOption,
mActivity.getDeviceProfile());
FloatProperty<TaskView> dismissingTaskViewTranslate;
Rect hiddenBounds = new Rect(taskView.getLeft(), taskView.getTop(),
taskView.getRight(), taskView.getBottom());
int distanceDelta = 0;
if (dir == PagedOrientationHandler.SPLIT_TRANSLATE_SECONDARY_NEGATIVE) {
dismissingTaskViewTranslate = taskView
.getSecondaryDissmissTranslationProperty();
distanceDelta = initialBounds.top - hiddenBounds.top;
taskView.layout(initialBounds.left, hiddenBounds.top, initialBounds.right,
hiddenBounds.bottom);
} else {
dismissingTaskViewTranslate = taskView
.getPrimaryDismissTranslationProperty();
distanceDelta = initialBounds.left - hiddenBounds.left;
taskView.layout(hiddenBounds.left, initialBounds.top, hiddenBounds.right,
initialBounds.bottom);
if (dir == PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_POSITIVE) {
distanceDelta *= -1;
}
}
pendingAnim.add(ObjectAnimator.ofFloat(mSplitHiddenTaskView,
dismissingTaskViewTranslate,
distanceDelta));
pendingAnim.add(ObjectAnimator.ofFloat(mSplitHiddenTaskView, ALPHA, 1));
} else {
// If insertion is on last index (furthest from clear all), we directly add the view
// else we translate all views to the right of insertion index further right,
// ignore views to left
if (showAsGrid()) {
// TODO(b/186800707) handle more elegantly for grid
continue;
}
int scrollDiff = newScroll[i] - oldScroll[i];
if (scrollDiff != 0) {
FloatProperty translationProperty = child instanceof TaskView
@@ -2882,6 +2950,12 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
pendingAnim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
// TODO(b/186800707) Figure out how to undo for grid view
// Need to handle cases where dismissed task is
// * Top Row
// * Bottom Row
// * Focused Task
updateGridProperties();
resetFromSplitSelectionState();
}
});
@@ -2891,13 +2965,16 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
private void resetFromSplitSelectionState() {
mSplitHiddenTaskView.setTranslationY(0);
int pageToSnapTo = mCurrentPage;
if (mSplitHiddenTaskViewIndex <= pageToSnapTo) {
pageToSnapTo += 1;
} else {
pageToSnapTo = mSplitHiddenTaskViewIndex;
if (!showAsGrid()) {
// TODO(b/186800707)
int pageToSnapTo = mCurrentPage;
if (mSplitHiddenTaskViewIndex <= pageToSnapTo) {
pageToSnapTo += 1;
} else {
pageToSnapTo = mSplitHiddenTaskViewIndex;
}
snapToPageImmediately(pageToSnapTo);
}
snapToPageImmediately(pageToSnapTo);
onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom());
resetTaskVisuals();
mSplitHiddenTaskView = null;
@@ -172,6 +172,32 @@ public class TaskView extends FrameLayout implements Reusable {
}
};
private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_X =
new FloatProperty<TaskView>("splitSelectTranslationX") {
@Override
public void setValue(TaskView taskView, float v) {
taskView.setSplitSelectTranslationX(v);
}
@Override
public Float get(TaskView taskView) {
return taskView.mSplitSelectTranslationX;
}
};
private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_Y =
new FloatProperty<TaskView>("splitSelectTranslationY") {
@Override
public void setValue(TaskView taskView, float v) {
taskView.setSplitSelectTranslationY(v);
}
@Override
public Float get(TaskView taskView) {
return taskView.mSplitSelectTranslationY;
}
};
private static final FloatProperty<TaskView> DISMISS_TRANSLATION_X =
new FloatProperty<TaskView>("dismissTranslationX") {
@Override
@@ -345,6 +371,9 @@ public class TaskView extends FrameLayout implements Reusable {
// The following grid translations scales with mGridProgress.
private float mGridTranslationX;
private float mGridTranslationY;
// Used when in SplitScreenSelectState
private float mSplitSelectTranslationY;
private float mSplitSelectTranslationX;
private ObjectAnimator mIconAndDimAnimator;
private float mIconScaleAnimStartProgress = 0;
@@ -826,8 +855,10 @@ public class TaskView extends FrameLayout implements Reusable {
protected void resetViewTransforms() {
// fullscreenTranslation and accumulatedTranslation should not be reset, as
// resetViewTransforms is called during Quickswitch scrolling.
mDismissTranslationX = mTaskOffsetTranslationX = mTaskResistanceTranslationX = 0f;
mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f;
mDismissTranslationX = mTaskOffsetTranslationX = mTaskResistanceTranslationX =
mSplitSelectTranslationX = 0f;
mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY =
mSplitSelectTranslationY = 0f;
applyTranslationX();
applyTranslationY();
setTranslationZ(0);
@@ -957,6 +988,15 @@ public class TaskView extends FrameLayout implements Reusable {
setScaleY(scale);
}
private void setSplitSelectTranslationX(float x) {
mSplitSelectTranslationX = x;
applyTranslationX();
}
private void setSplitSelectTranslationY(float y) {
mSplitSelectTranslationY = y;
applyTranslationY();
}
private void setDismissTranslationX(float x) {
mDismissTranslationX = x;
applyTranslationX();
@@ -1057,12 +1097,12 @@ public class TaskView extends FrameLayout implements Reusable {
private void applyTranslationX() {
setTranslationX(mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
+ getPersistentTranslationX());
+ mSplitSelectTranslationX + getPersistentTranslationX());
}
private void applyTranslationY() {
setTranslationY(mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
+ getPersistentTranslationY());
+ mSplitSelectTranslationY + getPersistentTranslationY());
}
/**
@@ -1086,6 +1126,16 @@ public class TaskView extends FrameLayout implements Reusable {
+ getGridTrans(mGridTranslationY);
}
public FloatProperty<TaskView> getPrimarySplitTranslationProperty() {
return getPagedOrientationHandler().getPrimaryValue(
SPLIT_SELECT_TRANSLATION_X, SPLIT_SELECT_TRANSLATION_Y);
}
public FloatProperty<TaskView> getSecondarySplitTranslationProperty() {
return getPagedOrientationHandler().getSecondaryValue(
SPLIT_SELECT_TRANSLATION_X, SPLIT_SELECT_TRANSLATION_Y);
}
public FloatProperty<TaskView> getPrimaryDismissTranslationProperty() {
return getPagedOrientationHandler().getPrimaryValue(
DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
@@ -159,6 +159,19 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
return VIEW_TRANSLATE_X;
}
@Override
public int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition,
DeviceProfile dp) {
// Don't use device profile here because we know we're in fake landscape, only split option
// available is top/left
if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
// Top (visually left) side
return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
}
throw new IllegalStateException("Invalid split stage position: " +
splitPosition.mStagePosition);
}
@Override
public int getPrimaryScroll(View view) {
return view.getScrollY();
@@ -42,6 +42,10 @@ import java.util.List;
*/
public interface PagedOrientationHandler {
int SPLIT_TRANSLATE_PRIMARY_POSITIVE = 0;
int SPLIT_TRANSLATE_PRIMARY_NEGATIVE = 1;
int SPLIT_TRANSLATE_SECONDARY_NEGATIVE = 2;
PagedOrientationHandler PORTRAIT = new PortraitPagedViewHandler();
PagedOrientationHandler LANDSCAPE = new LandscapePagedViewHandler();
PagedOrientationHandler SEASCAPE = new SeascapePagedViewHandler();
@@ -71,6 +75,13 @@ public interface PagedOrientationHandler {
int getSecondaryDimension(View view);
FloatProperty<View> getPrimaryViewTranslate();
FloatProperty<View> getSecondaryViewTranslate();
/**
* @param splitPosition The position where the view to be split will go
* @return {@link #SPLIT_TRANSLATE_*} constants to indicate which direction the
* dismissal should happen
*/
int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition, DeviceProfile dp);
int getPrimaryScroll(View view);
float getPrimaryScale(View view);
int getChildStart(View view);
@@ -155,6 +155,25 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
return VIEW_TRANSLATE_Y;
}
@Override
public int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition,
DeviceProfile dp) {
if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
if (dp.isLandscape) {
// Left side
return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
} else {
// Top side
return SPLIT_TRANSLATE_SECONDARY_NEGATIVE;
}
} else if (splitPosition.mStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
// We don't have a bottom option, so should be right
return SPLIT_TRANSLATE_PRIMARY_POSITIVE;
}
throw new IllegalStateException("Invalid split stage position: " +
splitPosition.mStagePosition);
}
@Override
public int getPrimaryScroll(View view) {
return view.getScrollX();