Show multiple icons for GroupedTaskView

* Hide all overview actions for GroupedTaskView
* Move some logic from TaskView into respective
PagedOrientationHandlers
* Remove unused methods from PagedOrientationHandler
* NOTE this is just visual changes. Properly showing
task menu's is still in-progress

Bug: 181704764
Test: Tested GroupedTaskView in portrait/landscape,
fake landscape in small screen, and real portrait/landscape
in large screen

Change-Id: I9c13ca114024db0a8e3fa5d295951696adb8516f
This commit is contained in:
Vinit Nayak 2021-09-16 16:10:50 -07:00
parent 104ed0b9a8
commit af6b85e3bc
9 changed files with 249 additions and 113 deletions

View File

@ -44,4 +44,11 @@
android:layout_height="@dimen/task_thumbnail_icon_size"
android:focusable="false"
android:importantForAccessibility="no"/>
<com.android.quickstep.views.IconView
android:id="@+id/bottomRight_icon"
android:layout_width="@dimen/task_thumbnail_icon_size"
android:layout_height="@dimen/task_thumbnail_icon_size"
android:focusable="false"
android:importantForAccessibility="no"/>
</com.android.quickstep.views.GroupedTaskView>

View File

@ -1,18 +1,26 @@
package com.android.quickstep.views;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.util.CancellableTask;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import java.util.function.Consumer;
@ -30,8 +38,14 @@ public class GroupedTaskView extends TaskView {
private Task mSecondaryTask;
private TaskThumbnailView mSnapshotView2;
private CancellableTask mThumbnailLoadRequest2;
private SplitConfigurationOptions.StagedSplitBounds mSplitBoundsConfig;
private IconView mIconView2;
private CancellableTask<ThumbnailData> mThumbnailLoadRequest2;
private CancellableTask mIconLoadRequest2;
private final float[] mIcon2CenterCoords = new float[2];
private TransformingTouchDelegate mIcon2TouchDelegate;
@Nullable private StagedSplitBounds mSplitBoundsConfig;
private final Rect mPrimaryTempRect = new Rect();
private final Rect mSecondaryTempRect = new Rect();
public GroupedTaskView(Context context) {
super(context);
@ -49,10 +63,12 @@ public class GroupedTaskView extends TaskView {
protected void onFinishInflate() {
super.onFinishInflate();
mSnapshotView2 = findViewById(R.id.bottomright_snapshot);
mIconView2 = findViewById(R.id.bottomRight_icon);
mIcon2TouchDelegate = new TransformingTouchDelegate(mIconView2);
}
public void bind(Task primary, Task secondary, RecentsOrientedState orientedState,
SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig) {
StagedSplitBounds splitBoundsConfig) {
super.bind(primary, orientedState);
mSecondaryTask = secondary;
mTaskIdContainer[1] = secondary.key.id;
@ -67,6 +83,7 @@ public class GroupedTaskView extends TaskView {
if (visible) {
RecentsModel model = RecentsModel.INSTANCE.get(getContext());
TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
TaskIconCache iconCache = model.getIconCache();
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
mThumbnailLoadRequest2 = thumbnailCache.updateThumbnailInBackground(mSecondaryTask,
@ -76,7 +93,11 @@ public class GroupedTaskView extends TaskView {
}
if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
// TODO What's the Icon for this going to look like? :o
mIconLoadRequest2 = iconCache.updateIconInBackground(mSecondaryTask,
(task) -> {
setIcon(mIconView2, task.icon);
// TODO(199936292) Digital Wellbeing for individual tasks?
});
}
} else {
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
@ -86,11 +107,26 @@ public class GroupedTaskView extends TaskView {
mSecondaryTask.thumbnail = null;
}
if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
// TODO
setIcon(mIconView2, null);
}
}
}
public void updateSplitBoundsConfig(StagedSplitBounds stagedSplitBounds) {
mSplitBoundsConfig = stagedSplitBounds;
invalidate();
}
@Override
public boolean offerTouchToChildren(MotionEvent event) {
computeAndSetIconTouchDelegate(mIconView2, mIcon2CenterCoords, mIcon2TouchDelegate);
if (mIcon2TouchDelegate.onTouchEvent(event)) {
return true;
}
return super.offerTouchToChildren(event);
}
@Override
protected void cancelPendingLoadTasks() {
super.cancelPendingLoadTasks();
@ -98,6 +134,10 @@ public class GroupedTaskView extends TaskView {
mThumbnailLoadRequest2.cancel();
mThumbnailLoadRequest2 = null;
}
if (mIconLoadRequest2 != null) {
mIconLoadRequest2.cancel();
mIconLoadRequest2 = null;
}
}
@Override
@ -137,6 +177,7 @@ public class GroupedTaskView extends TaskView {
getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView,
mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig,
mActivity.getDeviceProfile());
updateIconPlacement();
}
@Override
@ -144,4 +185,32 @@ public class GroupedTaskView extends TaskView {
super.setOverlayEnabled(overlayEnabled);
mSnapshotView2.setOverlayEnabled(overlayEnabled);
}
@Override
public void setOrientationState(RecentsOrientedState orientationState) {
super.setOrientationState(orientationState);
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
boolean isGridTask = deviceProfile.overviewShowAsGrid && !isFocusedTask();
int iconDrawableSize = isGridTask ? deviceProfile.overviewTaskIconDrawableSizeGridPx
: deviceProfile.overviewTaskIconDrawableSizePx;
mIconView2.setDrawableSize(iconDrawableSize, iconDrawableSize);
mIconView2.setRotation(getPagedOrientationHandler().getDegreesRotated());
updateIconPlacement();
}
private void updateIconPlacement() {
if (mSplitBoundsConfig == null) {
return;
}
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
int taskIconHeight = deviceProfile.overviewTaskIconSizePx;
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
mSnapshotView.getBoundsOnScreen(mPrimaryTempRect);
mSnapshotView2.getBoundsOnScreen(mSecondaryTempRect);
getPagedOrientationHandler().setSplitIconParams(mIconView, mIconView2,
taskIconHeight, mPrimaryTempRect, mSecondaryTempRect,
isRtl, deviceProfile, mSplitBoundsConfig);
}
}

View File

@ -54,7 +54,8 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
HIDDEN_NON_ZERO_ROTATION,
HIDDEN_NO_TASKS,
HIDDEN_NO_RECENTS,
HIDDEN_FOCUSED_SCROLL})
HIDDEN_FOCUSED_SCROLL,
HIDDEN_SPLIT_SCREEN})
@Retention(RetentionPolicy.SOURCE)
public @interface ActionsHiddenFlags { }
@ -62,6 +63,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
public static final int HIDDEN_NO_TASKS = 1 << 1;
public static final int HIDDEN_NO_RECENTS = 1 << 2;
public static final int HIDDEN_FOCUSED_SCROLL = 1 << 3;
public static final int HIDDEN_SPLIT_SCREEN = 1 << 4;
@IntDef(flag = true, value = {
DISABLED_SCROLLING,

View File

@ -53,6 +53,7 @@ import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@ -1109,6 +1110,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
gtv.onTaskListVisibilityChanged(false);
removeView(gtv);
}
mSplitBoundsConfig = null;
}
updateLocusId();
}
@ -2161,7 +2163,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* All subsequent calls to reload will keep the task as the first item until {@link #reset()}
* is called. Also scrolls the view to this task.
*/
public void showCurrentTask(RunningTaskInfo[] runningTaskInfo) {
private void showCurrentTask(RunningTaskInfo[] runningTaskInfo) {
int runningTaskViewId = -1;
boolean needGroupTaskView = runningTaskInfo.length > 1;
RunningTaskInfo taskInfo = runningTaskInfo[0];
@ -3134,7 +3136,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
}
}
updateFocusedSplitButtonVisibility();
updateCurrentTaskActionsVisibility();
onDismissAnimationEnds();
mPendingAnimation = null;
}
@ -3143,16 +3145,19 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
/**
* Shows split button if
* * We're in large screen
* * We're not already in split
* Hides all overview actions if current page is for split apps, shows otherwise
* If actions are showing, we only show split option if
* * Device is large screen
* * There are at least 2 tasks to invoke split
*/
private void updateFocusedSplitButtonVisibility() {
mActionsView.setSplitButtonVisible(mActivity.getDeviceProfile().isTablet &&
!(getFocusedTaskView() instanceof GroupedTaskView) &&
getTaskViewCount() > 1
);
private void updateCurrentTaskActionsVisibility() {
boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
if (isCurrentSplit) {
return;
}
mActionsView.setSplitButtonVisible(
mActivity.getDeviceProfile().isTablet && getTaskViewCount() > 1);
}
/**
@ -4174,7 +4179,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
@Override
protected void notifyPageSwitchListener(int prevPage) {
super.notifyPageSwitchListener(prevPage);
updateFocusedSplitButtonVisibility();
updateCurrentTaskActionsVisibility();
loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
updateEnabledOverlays();
}
@ -4260,6 +4265,14 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
mSplitBoundsConfig = gluer.getStagedSplitBounds();
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView instanceof GroupedTaskView) {
// We initially create a GroupedTaskView in showCurrentTask() before launcher even
// receives the leashes for the remote apps, so the mSplitBoundsConfig that gets passed
// in there is either null or outdated, so we need to update here as soon as we're
// notified.
((GroupedTaskView) runningTaskView).updateSplitBoundsConfig(mSplitBoundsConfig);
}
for (RemoteTargetHandle remoteTargetHandle : mRemoteTargetHandles) {
TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
tvs.setOrientationState(mOrientationState);

View File

@ -374,7 +374,7 @@ public class TaskView extends FrameLayout implements Reusable {
protected Task mTask;
protected TaskThumbnailView mSnapshotView;
private IconView mIconView;
protected IconView mIconView;
private final DigitalWellBeingToast mDigitalWellBeingToast;
private float mFullscreenProgress;
private float mGridProgress;
@ -492,7 +492,7 @@ public class TaskView extends FrameLayout implements Reusable {
*/
public boolean offerTouchToChildren(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
computeAndSetIconTouchDelegate();
computeAndSetIconTouchDelegate(mIconView, mIconCenterCoords, mIconTouchDelegate);
computeAndSetChipTouchDelegate();
}
if (mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event)) {
@ -504,16 +504,17 @@ public class TaskView extends FrameLayout implements Reusable {
return false;
}
private void computeAndSetIconTouchDelegate() {
float iconHalfSize = mIconView.getWidth() / 2f;
mIconCenterCoords[0] = mIconCenterCoords[1] = iconHalfSize;
getDescendantCoordRelativeToAncestor(mIconView, mActivity.getDragLayer(), mIconCenterCoords,
protected void computeAndSetIconTouchDelegate(IconView iconView, float[] tempCenterCoords,
TransformingTouchDelegate transformingTouchDelegate) {
float iconHalfSize = iconView.getWidth() / 2f;
tempCenterCoords[0] = tempCenterCoords[1] = iconHalfSize;
getDescendantCoordRelativeToAncestor(iconView, mActivity.getDragLayer(), tempCenterCoords,
false);
mIconTouchDelegate.setBounds(
(int) (mIconCenterCoords[0] - iconHalfSize),
(int) (mIconCenterCoords[1] - iconHalfSize),
(int) (mIconCenterCoords[0] + iconHalfSize),
(int) (mIconCenterCoords[1] + iconHalfSize));
transformingTouchDelegate.setBounds(
(int) (tempCenterCoords[0] - iconHalfSize),
(int) (tempCenterCoords[1] - iconHalfSize),
(int) (tempCenterCoords[0] + iconHalfSize),
(int) (tempCenterCoords[1] + iconHalfSize));
}
private void computeAndSetChipTouchDelegate() {
@ -792,7 +793,7 @@ public class TaskView extends FrameLayout implements Reusable {
if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
mIconLoadRequest = iconCache.updateIconInBackground(mTask,
(task) -> {
setIcon(task.icon);
setIcon(mIconView, task.icon);
mDigitalWellBeingToast.initialize(mTask);
});
}
@ -804,7 +805,7 @@ public class TaskView extends FrameLayout implements Reusable {
mTask.thumbnail = null;
}
if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
setIcon(null);
setIcon(mIconView, null);
}
}
}
@ -840,10 +841,10 @@ public class TaskView extends FrameLayout implements Reusable {
}
}
private void setIcon(Drawable icon) {
protected void setIcon(IconView iconView, Drawable icon) {
if (icon != null) {
mIconView.setDrawable(icon);
mIconView.setOnClickListener(v -> {
iconView.setDrawable(icon);
iconView.setOnClickListener(v -> {
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
RecentsView recentsView = getRecentsView();
recentsView.switchToScreenshot(
@ -854,14 +855,14 @@ public class TaskView extends FrameLayout implements Reusable {
showTaskMenu();
}
});
mIconView.setOnLongClickListener(v -> {
iconView.setOnLongClickListener(v -> {
requestDisallowInterceptTouchEvent(true);
return showTaskMenu();
});
} else {
mIconView.setDrawable(null);
mIconView.setOnClickListener(null);
mIconView.setOnLongClickListener(null);
iconView.setDrawable(null);
iconView.setOnClickListener(null);
iconView.setOnLongClickListener(null);
}
}
@ -877,32 +878,8 @@ public class TaskView extends FrameLayout implements Reusable {
: deviceProfile.overviewTaskMarginPx;
int taskIconMargin = snapshotParams.topMargin - taskIconHeight - taskMargin;
LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
switch (orientationHandler.getRotation()) {
case ROTATION_90:
iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL;
iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2;
iconParams.leftMargin = 0;
iconParams.topMargin = snapshotParams.topMargin / 2;
break;
case ROTATION_180:
iconParams.gravity = BOTTOM | CENTER_HORIZONTAL;
iconParams.bottomMargin = -snapshotParams.topMargin;
iconParams.leftMargin = iconParams.rightMargin = 0;
iconParams.topMargin = taskIconMargin;
break;
case ROTATION_270:
iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
iconParams.leftMargin = -taskIconHeight - taskIconMargin / 2;
iconParams.rightMargin = 0;
iconParams.topMargin = snapshotParams.topMargin / 2;
break;
case Surface.ROTATION_0:
default:
iconParams.gravity = TOP | CENTER_HORIZONTAL;
iconParams.leftMargin = iconParams.rightMargin = 0;
iconParams.topMargin = taskIconMargin;
break;
}
orientationHandler.setIconAndSnapshotParams(mIconView, taskIconMargin, taskIconHeight,
snapshotParams, isRtl);
mSnapshotView.setLayoutParams(snapshotParams);
iconParams.width = iconParams.height = taskIconHeight;
mIconView.setLayoutParams(iconParams);

View File

@ -16,6 +16,10 @@
package com.android.launcher3.touch;
import static android.view.Gravity.CENTER_VERTICAL;
import static android.view.Gravity.END;
import static android.view.Gravity.START;
import static android.view.Gravity.TOP;
import static android.widget.ListPopupWindow.WRAP_CONTENT;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
@ -36,8 +40,8 @@ import android.view.MotionEvent;
import android.view.Surface;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.android.launcher3.DeviceProfile;
@ -46,6 +50,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.views.BaseDragLayer;
import java.util.Collections;
@ -222,11 +227,6 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
return view.getTop();
}
@Override
public float getChildStartWithTranslation(View view) {
return view.getTop() + view.getTranslationY();
}
@Override
public int getCenterForPage(View view, Rect insets) {
return (view.getPaddingLeft() + view.getMeasuredWidth() + insets.left
@ -243,11 +243,6 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
return view.getHeight() - view.getPaddingBottom() - insets.bottom;
}
@Override
public int getPrimaryTranslationDirectionFactor() {
return -1;
}
public int getSecondaryTranslationDirectionFactor() {
return 1;
}
@ -261,11 +256,6 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
}
}
@Override
public int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp) {
return translationOffset;
}
@Override
public float getTaskMenuX(float x, View thumbnailView, int overScroll) {
return thumbnailView.getMeasuredWidth() + x;
@ -386,7 +376,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
@Override
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
StagedSplitBounds splitInfo, int desiredStagePosition) {
float diff;
float horizontalDividerDiff = splitInfo.visualDividerBounds.width() / 2f;
if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
@ -400,7 +390,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
@Override
public void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
StagedSplitBounds splitInfo, int desiredStagePosition) {
if (desiredStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
// The preview set is for the bottom/right, inset by top/left task
splitOffset.x = splitInfo.leftTopBounds.width() + splitInfo.visualDividerBounds.width();
@ -419,8 +409,10 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
int secondarySnapshotHeight;
int secondarySnapshotWidth;
float taskPercent = splitBoundsConfig.appsStackedVertically ?
splitBoundsConfig.topTaskPercent : splitBoundsConfig.leftTaskPercent;
primarySnapshotWidth = parentWidth;
primarySnapshotHeight = (int) (totalThumbnailHeight * splitBoundsConfig.leftTaskPercent);
primarySnapshotHeight = (int) (totalThumbnailHeight * taskPercent);
secondarySnapshotWidth = parentWidth;
secondarySnapshotHeight = totalThumbnailHeight - primarySnapshotHeight - dividerBar;
@ -434,6 +426,38 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
View.MeasureSpec.EXACTLY));
}
@Override
public void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
FrameLayout.LayoutParams iconParams =
(FrameLayout.LayoutParams) iconView.getLayoutParams();
iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL;
iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2;
iconParams.leftMargin = 0;
iconParams.topMargin = snapshotParams.topMargin / 2;
}
@Override
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, Rect primarySnapshotBounds, Rect secondarySnapshotBounds,
boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
FrameLayout.LayoutParams primaryIconParams =
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
FrameLayout.LayoutParams secondaryIconParams =
new FrameLayout.LayoutParams(primaryIconParams);
int primaryHeight = primarySnapshotBounds.height();
int secondaryHeight = secondarySnapshotBounds.height();
primaryIconParams.gravity = (isRtl ? START : END) | TOP;
primaryIconView.setTranslationY((primaryHeight + taskIconHeight) / 2f );
secondaryIconParams.gravity = (isRtl ? START : END) | TOP;
secondaryIconView.setTranslationY(primaryHeight
+ ((secondaryHeight + taskIconHeight) / 2f));
primaryIconView.setLayoutParams(primaryIconParams);
secondaryIconView.setLayoutParams(secondaryIconParams);
}
@Override
public int getDefaultSplitPosition(DeviceProfile deviceProfile) {
throw new IllegalStateException("Default position not available in fake landscape");

View File

@ -29,12 +29,14 @@ import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import java.util.List;
@ -88,14 +90,11 @@ public interface PagedOrientationHandler {
int getPrimaryScroll(View view);
float getPrimaryScale(View view);
int getChildStart(View view);
float getChildStartWithTranslation(View view);
int getCenterForPage(View view, Rect insets);
int getScrollOffsetStart(View view, Rect insets);
int getScrollOffsetEnd(View view, Rect insets);
int getPrimaryTranslationDirectionFactor();
int getSecondaryTranslationDirectionFactor();
int getSplitTranslationDirectionFactor(@StagePosition int stagePosition);
int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp);
ChildBounds getChildBounds(View child, int childStart, int pageCenter, boolean layoutChild);
void setMaxScroll(AccessibilityEvent event, int maxScroll);
boolean getRecentsRtlSetting(Resources resources);
@ -144,12 +143,12 @@ public interface PagedOrientationHandler {
* outRect for
*/
void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
SplitConfigurationOptions.StagedSplitBounds splitInfo,
StagedSplitBounds splitInfo,
@SplitConfigurationOptions.StagePosition int desiredStagePosition);
/**
* It's important to note that {@link #setSplitTaskSwipeRect(DeviceProfile, Rect,
* SplitConfigurationOptions.StagedSplitBounds, int)} above operates on the outRect based on
* StagedSplitBounds, int)} above operates on the outRect based on
* launcher's coordinate system, meaning it will treat the outRect as portrait if home rotation
* is not allowed.
*
@ -159,7 +158,7 @@ public interface PagedOrientationHandler {
* usual Y
*/
void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
SplitConfigurationOptions.StagedSplitBounds splitInfo,
StagedSplitBounds splitInfo,
@SplitConfigurationOptions.StagePosition int desiredStagePosition);
void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
@ -167,6 +166,11 @@ public interface PagedOrientationHandler {
SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, DeviceProfile dp);
// Overview TaskMenuView methods
void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
FrameLayout.LayoutParams snapshotParams, boolean isRtl);
void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, Rect primarySnapshotBounds, Rect secondarySnapshotBounds,
boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
float getTaskMenuX(float x, View thumbnailView, int overScroll);
float getTaskMenuY(float y, View thumbnailView, int overScroll);
int getTaskMenuWidth(View view);

View File

@ -16,6 +16,11 @@
package com.android.launcher3.touch;
import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.CENTER_HORIZONTAL;
import static android.view.Gravity.START;
import static android.view.Gravity.TOP;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
@ -36,6 +41,7 @@ import android.view.Surface;
import android.view.VelocityTracker;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.android.launcher3.DeviceProfile;
@ -44,6 +50,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.views.BaseDragLayer;
import java.util.ArrayList;
@ -227,11 +234,6 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
return view.getLeft();
}
@Override
public float getChildStartWithTranslation(View view) {
return view.getLeft() + view.getTranslationX();
}
@Override
public int getCenterForPage(View view, Rect insets) {
return (view.getPaddingTop() + view.getMeasuredHeight() + insets.top
@ -248,11 +250,6 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
return view.getWidth() - view.getPaddingRight() - insets.right;
}
@Override
public int getPrimaryTranslationDirectionFactor() {
return 1;
}
public int getSecondaryTranslationDirectionFactor() {
return -1;
}
@ -266,14 +263,6 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
}
}
@Override
public int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp) {
if (dp.isLandscape) {
return translationOffset;
}
return 0;
}
@Override
public float getTaskMenuX(float x, View thumbnailView, int overScroll) {
return x + overScroll;
@ -471,7 +460,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
@Override
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
StagedSplitBounds splitInfo, int desiredStagePosition) {
boolean isLandscape = dp.isLandscape;
float verticalDividerDiff = splitInfo.visualDividerBounds.height() / 2f;
float horizontalDividerDiff = splitInfo.visualDividerBounds.width() / 2f;
@ -497,7 +486,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
@Override
public void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
StagedSplitBounds splitInfo, int desiredStagePosition) {
if (desiredStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
if (dp.isLandscape) {
splitOffset.x = splitInfo.leftTopBounds.width() +
@ -554,6 +543,46 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
View.MeasureSpec.EXACTLY));
}
@Override
public void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
FrameLayout.LayoutParams iconParams =
(FrameLayout.LayoutParams) iconView.getLayoutParams();
iconParams.gravity = TOP | CENTER_HORIZONTAL;
iconParams.leftMargin = iconParams.rightMargin = 0;
iconParams.topMargin = taskIconMargin;
}
@Override
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, Rect primarySnapshotBounds, Rect secondarySnapshotBounds,
boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
FrameLayout.LayoutParams primaryIconParams =
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
FrameLayout.LayoutParams secondaryIconParams =
new FrameLayout.LayoutParams(primaryIconParams);
if (deviceProfile.isLandscape) {
int primaryWidth = primarySnapshotBounds.width();
int secondaryWidth = secondarySnapshotBounds.width();
primaryIconParams.gravity = TOP | START;
primaryIconView.setTranslationX((primaryWidth - taskIconHeight) / 2f );
secondaryIconParams.gravity = TOP | START;
secondaryIconView.setTranslationX(primaryWidth
+ ((secondaryWidth - taskIconHeight) / 2f));
} else {
primaryIconView.setTranslationX(0);
secondaryIconView.setTranslationX(0);
primaryIconView.setTranslationY(0);
secondaryIconView.setTranslationY(0);
secondaryIconParams.gravity = BOTTOM | CENTER_HORIZONTAL;
secondaryIconParams.bottomMargin = -(secondaryIconParams.topMargin + taskIconHeight);
}
primaryIconView.setLayoutParams(primaryIconParams);
secondaryIconView.setLayoutParams(secondaryIconParams);
}
@Override
public int getDefaultSplitPosition(DeviceProfile deviceProfile) {
if (!deviceProfile.isTablet) {

View File

@ -16,6 +16,10 @@
package com.android.launcher3.touch;
import static android.view.Gravity.CENTER_VERTICAL;
import static android.view.Gravity.END;
import static android.view.Gravity.START;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
@ -26,6 +30,7 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.view.Surface;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.android.launcher3.DeviceProfile;
@ -53,11 +58,6 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
}
}
@Override
public int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp) {
return translationOffset;
}
@Override
public boolean getRecentsRtlSetting(Resources resources) {
return Utilities.isRtl(resources);
@ -114,6 +114,17 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
}
@Override
public void setIconAndSnapshotParams(View mIconView, int taskIconMargin, int taskIconHeight,
FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
FrameLayout.LayoutParams iconParams =
(FrameLayout.LayoutParams) mIconView.getLayoutParams();
iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
iconParams.leftMargin = -taskIconHeight - taskIconMargin / 2;
iconParams.rightMargin = 0;
iconParams.topMargin = snapshotParams.topMargin / 2;
}
/* ---------- The following are only used by TaskViewTouchHandler. ---------- */
@Override