Merge "Add an animation for invalid widget resizing in 2 panel UI" into sc-v2-dev am: 3bbebe2439
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/15828712 Change-Id: I0847d3d3366bbc81ebe1299c294f5110311a5586
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
<dimen name="widget_handle_margin">13dp</dimen>
|
||||
<dimen name="resize_frame_background_padding">24dp</dimen>
|
||||
<dimen name="resize_frame_margin">22dp</dimen>
|
||||
<dimen name="resize_frame_invalid_drag_across_two_panel_opacity_margin">24dp</dimen>
|
||||
|
||||
<!-- App widget reconfigure button -->
|
||||
<dimen name="widget_reconfigure_button_corner_radius">14dp</dimen>
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.android.launcher3;
|
||||
|
||||
import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget;
|
||||
|
||||
import static com.android.launcher3.CellLayout.SPRING_LOADED_PROGRESS;
|
||||
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT;
|
||||
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RESIZE_COMPLETED;
|
||||
@@ -9,6 +10,8 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
|
||||
import static com.android.launcher3.views.BaseDragLayer.LAYOUT_X;
|
||||
import static com.android.launcher3.views.BaseDragLayer.LAYOUT_Y;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
@@ -29,6 +32,7 @@ import androidx.annotation.Px;
|
||||
|
||||
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.logging.InstanceId;
|
||||
import com.android.launcher3.logging.InstanceIdSequence;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
@@ -49,12 +53,14 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
private static final String KEY_RECONFIGURABLE_WIDGET_EDUCATION_TIP_SEEN =
|
||||
"launcher.reconfigurable_widget_education_tip_seen";
|
||||
private static final Rect sTmpRect = new Rect();
|
||||
private static final Rect sTmpRect2 = new Rect();
|
||||
|
||||
private static final int HANDLE_COUNT = 4;
|
||||
private static final int INDEX_LEFT = 0;
|
||||
private static final int INDEX_TOP = 1;
|
||||
private static final int INDEX_RIGHT = 2;
|
||||
private static final int INDEX_BOTTOM = 3;
|
||||
private static final float MIN_OPACITY_FOR_CELL_LAYOUT_DURING_INVALID_RESIZE = 0.5f;
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final DragViewStateAnnouncer mStateAnnouncer;
|
||||
@@ -103,6 +109,16 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
|
||||
private final InstanceId logInstanceId = new InstanceIdSequence().newInstanceId();
|
||||
|
||||
private final ViewGroupFocusHelper mDragLayerRelativeCoordinateHelper;
|
||||
|
||||
/**
|
||||
* In the two panel UI, it is not possible to resize a widget to cross its host
|
||||
* {@link CellLayout}'s sibling. When this happens, we gradually reduce the opacity of the
|
||||
* sibling {@link CellLayout} from 1f to
|
||||
* {@link #MIN_OPACITY_FOR_CELL_LAYOUT_DURING_INVALID_RESIZE}.
|
||||
*/
|
||||
private final float mDragAcrossTwoPanelOpacityMargin;
|
||||
|
||||
private boolean mLeftBorderActive;
|
||||
private boolean mRightBorderActive;
|
||||
private boolean mTopBorderActive;
|
||||
@@ -149,6 +165,10 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
for (int i = 0; i < HANDLE_COUNT; i++) {
|
||||
mSystemGestureExclusionRects.add(new Rect());
|
||||
}
|
||||
|
||||
mDragAcrossTwoPanelOpacityMargin = mLauncher.getResources().getDimensionPixelSize(
|
||||
R.dimen.resize_frame_invalid_drag_across_two_panel_opacity_margin);
|
||||
mDragLayerRelativeCoordinateHelper = new ViewGroupFocusHelper(mLauncher.getDragLayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -359,6 +379,37 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
lp.y = sTmpRect.top;
|
||||
}
|
||||
|
||||
// Handle invalid resize across CellLayouts in the two panel UI.
|
||||
if (mCellLayout.getParent() instanceof Workspace) {
|
||||
Workspace workspace = (Workspace) mCellLayout.getParent();
|
||||
CellLayout pairedCellLayout = workspace.getScreenPair(mCellLayout);
|
||||
if (pairedCellLayout != null) {
|
||||
Rect focusedCellLayoutBound = sTmpRect;
|
||||
mDragLayerRelativeCoordinateHelper.viewToRect(mCellLayout, focusedCellLayoutBound);
|
||||
Rect resizeFrameBound = sTmpRect2;
|
||||
findViewById(R.id.widget_resize_frame).getGlobalVisibleRect(resizeFrameBound);
|
||||
float progress = 1f;
|
||||
if (workspace.indexOfChild(pairedCellLayout) < workspace.indexOfChild(mCellLayout)
|
||||
&& mDeltaX < 0
|
||||
&& resizeFrameBound.left < focusedCellLayoutBound.left) {
|
||||
// Resize from right to left.
|
||||
progress = (mDragAcrossTwoPanelOpacityMargin + mDeltaX)
|
||||
/ mDragAcrossTwoPanelOpacityMargin;
|
||||
} else if (workspace.indexOfChild(pairedCellLayout)
|
||||
> workspace.indexOfChild(mCellLayout)
|
||||
&& mDeltaX > 0
|
||||
&& resizeFrameBound.right > focusedCellLayoutBound.right) {
|
||||
// Resize from left to right.
|
||||
progress = (mDragAcrossTwoPanelOpacityMargin - mDeltaX)
|
||||
/ mDragAcrossTwoPanelOpacityMargin;
|
||||
}
|
||||
float alpha = Math.max(MIN_OPACITY_FOR_CELL_LAYOUT_DURING_INVALID_RESIZE, progress);
|
||||
float springLoadedProgress = Math.min(1f, 1f - progress);
|
||||
updateInvalidResizeEffect(mCellLayout, pairedCellLayout, alpha,
|
||||
springLoadedProgress);
|
||||
}
|
||||
}
|
||||
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
@@ -515,13 +566,24 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
}
|
||||
|
||||
final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
|
||||
final CellLayout pairedCellLayout;
|
||||
if (mCellLayout.getParent() instanceof Workspace) {
|
||||
Workspace workspace = (Workspace) mCellLayout.getParent();
|
||||
pairedCellLayout = workspace.getScreenPair(mCellLayout);
|
||||
} else {
|
||||
pairedCellLayout = null;
|
||||
}
|
||||
if (!animate) {
|
||||
lp.width = newWidth;
|
||||
lp.height = newHeight;
|
||||
lp.x = newX;
|
||||
lp.y = newY;
|
||||
for (int i = 0; i < HANDLE_COUNT; i++) {
|
||||
mDragHandles[i].setAlpha(1.0f);
|
||||
mDragHandles[i].setAlpha(1f);
|
||||
}
|
||||
if (pairedCellLayout != null) {
|
||||
updateInvalidResizeEffect(mCellLayout, pairedCellLayout, /* alpha= */ 1f,
|
||||
/* springLoadedProgress= */ 0f);
|
||||
}
|
||||
requestLayout();
|
||||
} else {
|
||||
@@ -538,6 +600,10 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
set.play(mFirstFrameAnimatorHelper.addTo(
|
||||
ObjectAnimator.ofFloat(mDragHandles[i], ALPHA, 1f)));
|
||||
}
|
||||
if (pairedCellLayout != null) {
|
||||
updateInvalidResizeEffect(mCellLayout, pairedCellLayout, /* alpha= */ 1f,
|
||||
/* springLoadedProgress= */ 0f, /* animatorSet= */ set);
|
||||
}
|
||||
set.setDuration(SNAP_DURATION);
|
||||
set.start();
|
||||
}
|
||||
@@ -624,6 +690,52 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInvalidResizeEffect(CellLayout cellLayout, CellLayout pairedCellLayout,
|
||||
float alpha, float springLoadedProgress) {
|
||||
updateInvalidResizeEffect(cellLayout, pairedCellLayout, alpha,
|
||||
springLoadedProgress, /* animatorSet= */ null);
|
||||
}
|
||||
|
||||
private void updateInvalidResizeEffect(CellLayout cellLayout, CellLayout pairedCellLayout,
|
||||
float alpha, float springLoadedProgress, @Nullable AnimatorSet animatorSet) {
|
||||
int childCount = pairedCellLayout.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = pairedCellLayout.getChildAt(i);
|
||||
if (animatorSet != null) {
|
||||
animatorSet.play(
|
||||
mFirstFrameAnimatorHelper.addTo(
|
||||
ObjectAnimator.ofFloat(child, ALPHA, alpha)));
|
||||
} else {
|
||||
child.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
if (animatorSet != null) {
|
||||
animatorSet.play(mFirstFrameAnimatorHelper.addTo(
|
||||
ObjectAnimator.ofFloat(cellLayout, SPRING_LOADED_PROGRESS,
|
||||
springLoadedProgress)));
|
||||
animatorSet.play(mFirstFrameAnimatorHelper.addTo(
|
||||
ObjectAnimator.ofFloat(pairedCellLayout, SPRING_LOADED_PROGRESS,
|
||||
springLoadedProgress)));
|
||||
} else {
|
||||
cellLayout.setSpringLoadedProgress(springLoadedProgress);
|
||||
pairedCellLayout.setSpringLoadedProgress(springLoadedProgress);
|
||||
}
|
||||
|
||||
boolean shouldShowCellLayoutBorder = springLoadedProgress > 0f;
|
||||
if (animatorSet != null) {
|
||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
cellLayout.setIsDragOverlapping(shouldShowCellLayoutBorder);
|
||||
pairedCellLayout.setIsDragOverlapping(shouldShowCellLayoutBorder);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cellLayout.setIsDragOverlapping(shouldShowCellLayoutBorder);
|
||||
pairedCellLayout.setIsDragOverlapping(shouldShowCellLayoutBorder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isOfType(int type) {
|
||||
return (type & TYPE_WIDGET_RESIZE_FRAME) != 0;
|
||||
|
||||
@@ -2128,7 +2128,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
||||
actualIds.add(id);
|
||||
}
|
||||
int firstId = visibleIds.getArray().get(0);
|
||||
int pairId = mWorkspace.getPagePair(firstId);
|
||||
int pairId = mWorkspace.getScreenPair(firstId);
|
||||
// Double check that actual screenIds contains the visibleId, as empty screens are hidden
|
||||
// in single panel.
|
||||
if (actualIds.contains(firstId)) {
|
||||
@@ -2212,7 +2212,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
||||
// Some empty pages might have been removed while the phone was in a single panel
|
||||
// mode, so we want to add those empty pages back.
|
||||
IntSet screenIds = IntSet.wrap(orderedScreenIds);
|
||||
orderedScreenIds.forEach(screenId -> screenIds.add(mWorkspace.getPagePair(screenId)));
|
||||
orderedScreenIds.forEach(screenId -> screenIds.add(mWorkspace.getScreenPair(screenId)));
|
||||
orderedScreenIds = screenIds.getArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -651,7 +651,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
|
||||
// If the icon was dragged from Hotseat, there is no page pair
|
||||
if (isTwoPanelEnabled() && !(mDragSourceInternal.getParent() instanceof Hotseat)) {
|
||||
int pagePairScreenId = getPagePair(dragObject.dragInfo.screenId);
|
||||
int pagePairScreenId = getScreenPair(dragObject.dragInfo.screenId);
|
||||
CellLayout pagePair = mWorkspaceScreens.get(pagePairScreenId);
|
||||
if (pagePair == null) {
|
||||
// TODO: after http://b/198820019 is fixed, remove this
|
||||
@@ -917,16 +917,33 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page that is shown together with the given page when two panel is enabled.
|
||||
* Returns the screen ID of a page that is shown together with the given page screen ID when the
|
||||
* two panel UI is enabled.
|
||||
*/
|
||||
public int getPagePair(int page) {
|
||||
if (page % 2 == 0) {
|
||||
return page + 1;
|
||||
public int getScreenPair(int screenId) {
|
||||
if (screenId % 2 == 0) {
|
||||
return screenId + 1;
|
||||
} else {
|
||||
return page - 1;
|
||||
return screenId - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link CellLayout} that is shown together with the given {@link CellLayout} when the
|
||||
* two panel UI is enabled.
|
||||
*/
|
||||
@Nullable
|
||||
public CellLayout getScreenPair(CellLayout cellLayout) {
|
||||
if (!isTwoPanelEnabled()) {
|
||||
return null;
|
||||
}
|
||||
int screenId = getIdForScreen(cellLayout);
|
||||
if (screenId == -1) {
|
||||
return null;
|
||||
}
|
||||
return getScreenWithId(getScreenPair(screenId));
|
||||
}
|
||||
|
||||
public void stripEmptyScreens() {
|
||||
if (mLauncher.isWorkspaceLoading()) {
|
||||
// Don't strip empty screens if the workspace is still loading.
|
||||
@@ -959,7 +976,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
Iterator<Integer> removeScreensIterator = removeScreens.iterator();
|
||||
while (removeScreensIterator.hasNext()) {
|
||||
int pageToRemove = removeScreensIterator.next();
|
||||
int pagePair = getPagePair(pageToRemove);
|
||||
int pagePair = getScreenPair(pageToRemove);
|
||||
if (!removeScreens.contains(pagePair)) {
|
||||
// The page pair isn't empty so we want to remove the current page from the
|
||||
// removable pages' collection
|
||||
|
||||
Reference in New Issue
Block a user