Initial changes to creating a fake landscape Launcher UI
Workspace and hotseat are drawn in rotated UI giving the impression that the device is in Portrait, even though it is in landscape Bug: 131360075 Change-Id: I29c4068af25fd4dcf7039b9a45886e864a137977
This commit is contained in:
+2
-2
@@ -116,7 +116,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
|
||||
} else {
|
||||
workspaceView = null;
|
||||
}
|
||||
final Rect iconLocation = new Rect();
|
||||
final RectF iconLocation = new RectF();
|
||||
boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow();
|
||||
final FloatingIconView floatingView = canUseWorkspaceView
|
||||
? FloatingIconView.getFloatingIconView(activity, workspaceView,
|
||||
@@ -138,7 +138,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
|
||||
final float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx;
|
||||
|
||||
if (canUseWorkspaceView) {
|
||||
return new RectF(iconLocation);
|
||||
return iconLocation;
|
||||
} else {
|
||||
// Fallback to animate to center of screen.
|
||||
return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize,
|
||||
|
||||
@@ -52,7 +52,7 @@ public class TaskViewDrawable extends Drawable {
|
||||
|
||||
private final RecentsView mParent;
|
||||
private final View mIconView;
|
||||
private final int[] mIconPos;
|
||||
private final float[] mIconPos;
|
||||
private final TaskView mTaskView;
|
||||
|
||||
private final TaskThumbnailView mThumbnailView;
|
||||
@@ -68,7 +68,7 @@ public class TaskViewDrawable extends Drawable {
|
||||
mParent = parent;
|
||||
mTaskView = tv;
|
||||
mIconView = tv.getIconView();
|
||||
mIconPos = new int[2];
|
||||
mIconPos = new float[2];
|
||||
mIconScale = mIconView.getScaleX();
|
||||
Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true);
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
||||
*/
|
||||
private ValueAnimator getOpeningWindowAnimators(View v, RemoteAnimationTargetCompat[] targets,
|
||||
Rect windowTargetBounds, boolean toggleVisibility) {
|
||||
Rect bounds = new Rect();
|
||||
RectF bounds = new RectF();
|
||||
mFloatingView = FloatingIconView.getFloatingIconView(mLauncher, v, toggleVisibility,
|
||||
bounds, true /* isOpening */, mFloatingView);
|
||||
Rect crop = new Rect();
|
||||
@@ -423,8 +423,8 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
||||
// Scale the app icon to take up the entire screen. This simplifies the math when
|
||||
// animating the app window position / scale.
|
||||
float smallestSize = Math.min(windowTargetBounds.height(), windowTargetBounds.width());
|
||||
float maxScaleX = smallestSize / (float) bounds.width();
|
||||
float maxScaleY = smallestSize / (float) bounds.height();
|
||||
float maxScaleX = smallestSize / bounds.width();
|
||||
float maxScaleY = smallestSize / bounds.height();
|
||||
float scale = Math.max(maxScaleX, maxScaleY);
|
||||
float startScale = 1f;
|
||||
if (v instanceof BubbleTextView && !(v.getParent() instanceof DeepShortcutView)) {
|
||||
|
||||
@@ -123,12 +123,12 @@ public abstract class BaseRecyclerView extends RecyclerView {
|
||||
* @param ev MotionEvent in {@param eventSource}
|
||||
*/
|
||||
public boolean shouldContainerScroll(MotionEvent ev, View eventSource) {
|
||||
int[] point = new int[2];
|
||||
point[0] = (int) ev.getX();
|
||||
point[1] = (int) ev.getY();
|
||||
float[] point = new float[2];
|
||||
point[0] = ev.getX();
|
||||
point[1] = ev.getY();
|
||||
Utilities.mapCoordInSelfToDescendant(mScrollbar, eventSource, point);
|
||||
// IF the MotionEvent is inside the thumb, container should not be pulled down.
|
||||
if (mScrollbar.shouldBlockIntercept(point[0], point[1])) {
|
||||
if (mScrollbar.shouldBlockIntercept((int) point[0], (int) point[1])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +142,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mActivity = ActivityContext.lookupContext(context);
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
@@ -150,18 +149,24 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
mLayoutHorizontal = a.getBoolean(R.styleable.BubbleTextView_layoutHorizontal, false);
|
||||
|
||||
int display = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
|
||||
int defaultIconSize = grid.iconSizePx;
|
||||
final int defaultIconSize;
|
||||
if (display == DISPLAY_WORKSPACE) {
|
||||
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
|
||||
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
|
||||
defaultIconSize = grid.iconSizePx;
|
||||
} else if (display == DISPLAY_ALL_APPS) {
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
|
||||
setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
|
||||
defaultIconSize = grid.allAppsIconSizePx;
|
||||
} else if (display == DISPLAY_FOLDER) {
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.folderChildTextSizePx);
|
||||
setCompoundDrawablePadding(grid.folderChildDrawablePaddingPx);
|
||||
defaultIconSize = grid.folderChildIconSizePx;
|
||||
} else {
|
||||
defaultIconSize = mActivity.getDeviceProfile().iconSizePx;
|
||||
}
|
||||
mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
|
||||
|
||||
|
||||
@@ -57,12 +57,14 @@ import com.android.launcher3.anim.PropertyListBuilder;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.util.CellAndSpan;
|
||||
import com.android.launcher3.util.GridOccupancy;
|
||||
import com.android.launcher3.util.ParcelableSparseArray;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.Transposable;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -76,7 +78,7 @@ import java.util.Stack;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
public class CellLayout extends ViewGroup {
|
||||
public class CellLayout extends ViewGroup implements Transposable {
|
||||
public static final int WORKSPACE_ACCESSIBILITY_DRAG = 2;
|
||||
public static final int FOLDER_ACCESSIBILITY_DRAG = 1;
|
||||
|
||||
@@ -182,6 +184,7 @@ public class CellLayout extends ViewGroup {
|
||||
// Related to accessible drag and drop
|
||||
private DragAndDropAccessibilityDelegate mTouchHelper;
|
||||
private boolean mUseTouchHelper = false;
|
||||
private RotationMode mRotationMode = RotationMode.NORMAL;
|
||||
|
||||
public CellLayout(Context context) {
|
||||
this(context, null);
|
||||
@@ -203,7 +206,7 @@ public class CellLayout extends ViewGroup {
|
||||
setClipToPadding(false);
|
||||
mActivity = ActivityContext.lookupContext(context);
|
||||
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
|
||||
|
||||
mCellWidth = mCellHeight = -1;
|
||||
mFixedCellWidth = mFixedCellHeight = -1;
|
||||
@@ -317,6 +320,24 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
public void setRotationMode(RotationMode mode) {
|
||||
if (mRotationMode != mode) {
|
||||
mRotationMode = mode;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RotationMode getRotationMode() {
|
||||
return mRotationMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPadding(int left, int top, int right, int bottom) {
|
||||
mRotationMode.mapRect(left, top, right, bottom, mTempRect);
|
||||
super.setPadding(mTempRect.left, mTempRect.top, mTempRect.right, mTempRect.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchHoverEvent(MotionEvent event) {
|
||||
// Always attempt to dispatch hover events to accessibility first.
|
||||
@@ -745,6 +766,14 @@ public class CellLayout extends ViewGroup {
|
||||
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
int childWidthSize = widthSize - (getPaddingLeft() + getPaddingRight());
|
||||
int childHeightSize = heightSize - (getPaddingTop() + getPaddingBottom());
|
||||
|
||||
mShortcutsAndWidgets.setRotation(mRotationMode.surfaceRotation);
|
||||
if (mRotationMode.isTransposed) {
|
||||
int tmp = childWidthSize;
|
||||
childWidthSize = childHeightSize;
|
||||
childHeightSize = tmp;
|
||||
}
|
||||
|
||||
if (mFixedCellWidth < 0 || mFixedCellHeight < 0) {
|
||||
int cw = DeviceProfile.calculateCellWidth(childWidthSize, mCountX);
|
||||
int ch = DeviceProfile.calculateCellHeight(childHeightSize, mCountY);
|
||||
@@ -787,7 +816,6 @@ public class CellLayout extends ViewGroup {
|
||||
int top = getPaddingTop();
|
||||
int bottom = b - t - getPaddingBottom();
|
||||
|
||||
mShortcutsAndWidgets.layout(left, top, right, bottom);
|
||||
// Expand the background drawing bounds by the padding baked into the background drawable
|
||||
mBackground.getPadding(mTempRect);
|
||||
mBackground.setBounds(
|
||||
@@ -795,6 +823,16 @@ public class CellLayout extends ViewGroup {
|
||||
top - mTempRect.top - getPaddingTop(),
|
||||
right + mTempRect.right + getPaddingRight(),
|
||||
bottom + mTempRect.bottom + getPaddingBottom());
|
||||
|
||||
if (mRotationMode.isTransposed) {
|
||||
int halfW = mShortcutsAndWidgets.getMeasuredWidth() / 2;
|
||||
int halfH = mShortcutsAndWidgets.getMeasuredHeight() / 2;
|
||||
int cX = (left + right) / 2;
|
||||
int cY = (top + bottom) / 2;
|
||||
mShortcutsAndWidgets.layout(cX - halfW, cY - halfH, cX + halfW, cY + halfH);
|
||||
} else {
|
||||
mShortcutsAndWidgets.layout(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -929,7 +967,7 @@ public class CellLayout extends ViewGroup {
|
||||
if (resize) {
|
||||
cellToRect(cellX, cellY, spanX, spanY, r);
|
||||
if (v instanceof LauncherAppWidgetHostView) {
|
||||
DeviceProfile profile = mActivity.getDeviceProfile();
|
||||
DeviceProfile profile = mActivity.getWallpaperDeviceProfile();
|
||||
Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -419,6 +419,10 @@ public class DeviceProfile {
|
||||
updateWorkspacePadding();
|
||||
}
|
||||
|
||||
/**
|
||||
* The current device insets. This is generally same as the insets being dispatched to
|
||||
* {@link Insettable} elements, but can differ if the element is using a different profile.
|
||||
*/
|
||||
public Rect getInsets() {
|
||||
return mInsets;
|
||||
}
|
||||
@@ -582,45 +586,6 @@ public class DeviceProfile {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an item's location on the home screen. This is useful if the home screen
|
||||
* is animating, otherwise use {@link View#getLocationOnScreen(int[])}.
|
||||
* @param pageDiff The page difference relative to the current page.
|
||||
*/
|
||||
public void getItemLocation(int cellX, int cellY, int spanX, int spanY, int container,
|
||||
int pageDiff, Rect outBounds) {
|
||||
outBounds.setEmpty();
|
||||
if (container == CONTAINER_HOTSEAT) {
|
||||
final int actualHotseatCellHeight;
|
||||
if (isVerticalBarLayout()) {
|
||||
actualHotseatCellHeight = availableHeightPx / inv.numRows;
|
||||
if (mIsSeascape) {
|
||||
outBounds.left = mHotseatPadding.left;
|
||||
} else {
|
||||
outBounds.left = availableWidthPx - hotseatBarSizePx + mHotseatPadding.left;
|
||||
}
|
||||
outBounds.right = outBounds.left + iconSizePx;
|
||||
outBounds.top = mHotseatPadding.top
|
||||
+ actualHotseatCellHeight * (inv.numRows - cellX - 1);
|
||||
outBounds.bottom = outBounds.top + actualHotseatCellHeight;
|
||||
} else {
|
||||
actualHotseatCellHeight = hotseatBarSizePx - hotseatBarBottomPaddingPx
|
||||
- hotseatBarTopPaddingPx;
|
||||
outBounds.left = mInsets.left + workspacePadding.left + cellLayoutPaddingLeftRightPx
|
||||
+ (cellX * getCellSize().x);
|
||||
outBounds.right = outBounds.left + getCellSize().x;
|
||||
outBounds.top = mInsets.top + availableHeightPx - hotseatBarSizePx;
|
||||
outBounds.bottom = outBounds.top + actualHotseatCellHeight;
|
||||
}
|
||||
} else {
|
||||
outBounds.left = mInsets.left + workspacePadding.left + cellLayoutPaddingLeftRightPx
|
||||
+ (cellX * getCellSize().x) + (pageDiff * availableWidthPx);
|
||||
outBounds.right = outBounds.left + (getCellSize().x * spanX);
|
||||
outBounds.top = mInsets.top + workspacePadding.top + (cellY * getCellSize().y);
|
||||
outBounds.bottom = outBounds.top + (getCellSize().y * spanY);
|
||||
}
|
||||
}
|
||||
|
||||
private static Context getContext(Context c, int orientation) {
|
||||
Configuration context = new Configuration(c.getResources().getConfiguration());
|
||||
context.orientation = orientation;
|
||||
|
||||
@@ -26,11 +26,13 @@ import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.views.Transposable;
|
||||
|
||||
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable {
|
||||
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable, Transposable {
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mHasVerticalHotseat;
|
||||
@@ -77,7 +79,8 @@ public class Hotseat extends CellLayout implements LogContainerProvider, Insetta
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
|
||||
insets = grid.getInsets();
|
||||
|
||||
if (grid.isVerticalBarLayout()) {
|
||||
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
@@ -105,4 +108,9 @@ public class Hotseat extends CellLayout implements LogContainerProvider, Insetta
|
||||
// Don't let if follow through to workspace
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RotationMode getRotationMode() {
|
||||
return Launcher.getLauncher(getContext()).getRotationMode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -71,6 +72,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.widget.Toast;
|
||||
@@ -93,6 +95,7 @@ import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.FolderIconPreviewVerifier;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.keyboard.CustomActionsPopup;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
@@ -272,6 +275,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
|
||||
private float mCurrentAssistantVisibility = 0f;
|
||||
|
||||
private DeviceProfile mStableDeviceProfile;
|
||||
private RotationMode mRotationMode = RotationMode.NORMAL;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
RaceConditionTracker.onEvent(ON_CREATE_EVT, ENTER);
|
||||
@@ -390,6 +396,12 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (FeatureFlags.FAKE_LANDSCAPE_UI.get()) {
|
||||
WindowManager.LayoutParams lp = getWindow().getAttributes();
|
||||
lp.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
|
||||
getWindow().setAttributes(lp);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -418,6 +430,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
|
||||
@Override
|
||||
protected void reapplyUi() {
|
||||
if (FeatureFlags.FAKE_LANDSCAPE_UI.get()) {
|
||||
mRotationMode = mStableDeviceProfile == null ? RotationMode.NORMAL :
|
||||
(mDeviceProfile.isSeascape() ? RotationMode.SEASCAPE : RotationMode.LANDSCAPE);
|
||||
}
|
||||
getRootView().dispatchInsets();
|
||||
getStateManager().reapplyState(true /* cancelCurrentAnimation */);
|
||||
}
|
||||
@@ -469,8 +485,41 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
display.getSize(mwSize);
|
||||
mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
|
||||
}
|
||||
|
||||
if (FeatureFlags.FAKE_LANDSCAPE_UI.get() && mDeviceProfile.isVerticalBarLayout()
|
||||
&& !mDeviceProfile.isMultiWindowMode) {
|
||||
mStableDeviceProfile = mDeviceProfile.inv.portraitProfile;
|
||||
mRotationMode = mDeviceProfile.isSeascape()
|
||||
? RotationMode.SEASCAPE : RotationMode.LANDSCAPE;
|
||||
} else {
|
||||
mStableDeviceProfile = null;
|
||||
mRotationMode = RotationMode.NORMAL;
|
||||
}
|
||||
|
||||
onDeviceProfileInitiated();
|
||||
mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout(), true);
|
||||
mModelWriter = mModel.getWriter(getWallpaperDeviceProfile().isVerticalBarLayout(), true);
|
||||
}
|
||||
|
||||
public void updateInsets(Rect insets) {
|
||||
mDeviceProfile.updateInsets(insets);
|
||||
if (mStableDeviceProfile != null) {
|
||||
mStableDeviceProfile.updateInsets(insets);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RotationMode getRotationMode() {
|
||||
return mRotationMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Device profile to be used by UI elements which are shown directly on top of the wallpaper
|
||||
* and whose presentation is tied to the wallpaper (and physical device) and not the activity
|
||||
* configuration.
|
||||
*/
|
||||
@Override
|
||||
public DeviceProfile getWallpaperDeviceProfile() {
|
||||
return mStableDeviceProfile == null ? mDeviceProfile : mStableDeviceProfile;
|
||||
}
|
||||
|
||||
public RotationHelper getRotationHelper() {
|
||||
@@ -1812,7 +1861,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
mAppWidgetHost.clearViews();
|
||||
|
||||
if (mHotseat != null) {
|
||||
mHotseat.resetLayout(mDeviceProfile.isVerticalBarLayout());
|
||||
mHotseat.resetLayout(getWallpaperDeviceProfile().isVerticalBarLayout());
|
||||
}
|
||||
TraceHelper.endSection("startBinding");
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class LauncherRootView extends InsettableFrameLayout {
|
||||
UI_STATE_ROOT_VIEW, drawInsetBar ? FLAG_DARK_NAV : 0);
|
||||
|
||||
// Update device profile before notifying th children.
|
||||
mLauncher.getDeviceProfile().updateInsets(insets);
|
||||
mLauncher.updateInsets(insets);
|
||||
boolean resetState = !insets.equals(mInsets);
|
||||
setInsets(insets);
|
||||
|
||||
@@ -114,7 +114,7 @@ public class LauncherRootView extends InsettableFrameLayout {
|
||||
}
|
||||
|
||||
public void dispatchInsets() {
|
||||
mLauncher.getDeviceProfile().updateInsets(mInsets);
|
||||
mLauncher.updateInsets(mInsets);
|
||||
super.setInsets(mInsets);
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
|
||||
public void setupLp(View child) {
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
|
||||
if (child instanceof LauncherAppWidgetHostView) {
|
||||
DeviceProfile profile = mActivity.getDeviceProfile();
|
||||
DeviceProfile profile = mActivity.getWallpaperDeviceProfile();
|
||||
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX,
|
||||
profile.appWidgetScale.x, profile.appWidgetScale.y);
|
||||
} else {
|
||||
@@ -108,12 +108,12 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
|
||||
|
||||
public int getCellContentHeight() {
|
||||
return Math.min(getMeasuredHeight(),
|
||||
mActivity.getDeviceProfile().getCellHeight(mContainerType));
|
||||
mActivity.getWallpaperDeviceProfile().getCellHeight(mContainerType));
|
||||
}
|
||||
|
||||
public void measureChild(View child) {
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
|
||||
final DeviceProfile profile = mActivity.getDeviceProfile();
|
||||
final DeviceProfile profile = mActivity.getWallpaperDeviceProfile();
|
||||
|
||||
if (child instanceof LauncherAppWidgetHostView) {
|
||||
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX,
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.WallpaperManager;
|
||||
@@ -63,13 +60,12 @@ import android.view.animation.Interpolator;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutManager;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.views.Transposable;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
|
||||
import java.io.Closeable;
|
||||
@@ -97,7 +93,6 @@ public final class Utilities {
|
||||
|
||||
private static final int[] sLoc0 = new int[2];
|
||||
private static final int[] sLoc1 = new int[2];
|
||||
private static final float[] sPoint = new float[2];
|
||||
private static final Matrix sMatrix = new Matrix();
|
||||
private static final Matrix sInverseMatrix = new Matrix();
|
||||
|
||||
@@ -143,7 +138,7 @@ public final class Utilities {
|
||||
*/
|
||||
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
|
||||
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
|
||||
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
|
||||
TimeUnit.SECONDS, new LinkedBlockingQueue<>());
|
||||
|
||||
public static boolean IS_RUNNING_IN_TEST_HARNESS =
|
||||
ActivityManager.isRunningInTestHarness();
|
||||
@@ -170,37 +165,60 @@ public final class Utilities {
|
||||
* assumption fails, we will need to return a pair of scale factors.
|
||||
*/
|
||||
public static float getDescendantCoordRelativeToAncestor(
|
||||
View descendant, View ancestor, int[] coord, boolean includeRootScroll) {
|
||||
sPoint[0] = coord[0];
|
||||
sPoint[1] = coord[1];
|
||||
View descendant, View ancestor, float[] coord, boolean includeRootScroll) {
|
||||
return getDescendantCoordRelativeToAncestor(descendant, ancestor, coord, includeRootScroll,
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a coordinate relative to the descendant, find the coordinate in a parent view's
|
||||
* coordinates.
|
||||
*
|
||||
* @param descendant The descendant to which the passed coordinate is relative.
|
||||
* @param ancestor The root view to make the coordinates relative to.
|
||||
* @param coord The coordinate that we want mapped.
|
||||
* @param includeRootScroll Whether or not to account for the scroll of the descendant:
|
||||
* sometimes this is relevant as in a child's coordinates within the descendant.
|
||||
* @param ignoreTransform If true, view transform is ignored
|
||||
* @return The factor by which this descendant is scaled relative to this DragLayer. Caution
|
||||
* this scale factor is assumed to be equal in X and Y, and so if at any point this
|
||||
* assumption fails, we will need to return a pair of scale factors.
|
||||
*/
|
||||
public static float getDescendantCoordRelativeToAncestor(View descendant, View ancestor,
|
||||
float[] coord, boolean includeRootScroll, boolean ignoreTransform) {
|
||||
float scale = 1.0f;
|
||||
View v = descendant;
|
||||
while(v != ancestor && v != null) {
|
||||
// For TextViews, scroll has a meaning which relates to the text position
|
||||
// which is very strange... ignore the scroll.
|
||||
if (v != descendant || includeRootScroll) {
|
||||
sPoint[0] -= v.getScrollX();
|
||||
sPoint[1] -= v.getScrollY();
|
||||
offsetPoints(coord, -v.getScrollX(), -v.getScrollY());
|
||||
}
|
||||
|
||||
v.getMatrix().mapPoints(sPoint);
|
||||
sPoint[0] += v.getLeft();
|
||||
sPoint[1] += v.getTop();
|
||||
if (ignoreTransform) {
|
||||
if (v instanceof Transposable) {
|
||||
RotationMode m = ((Transposable) v).getRotationMode();
|
||||
if (m.isTransposed) {
|
||||
sMatrix.setRotate(m.surfaceRotation, v.getPivotX(), v.getPivotY());
|
||||
sMatrix.mapPoints(coord);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
v.getMatrix().mapPoints(coord);
|
||||
}
|
||||
offsetPoints(coord, v.getLeft(), v.getTop());
|
||||
scale *= v.getScaleX();
|
||||
|
||||
v = (View) v.getParent();
|
||||
}
|
||||
|
||||
coord[0] = Math.round(sPoint[0]);
|
||||
coord[1] = Math.round(sPoint[1]);
|
||||
return scale;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inverse of {@link #getDescendantCoordRelativeToAncestor(View, View, int[], boolean)}.
|
||||
* Inverse of {@link #getDescendantCoordRelativeToAncestor(View, View, float[], boolean)}.
|
||||
*/
|
||||
public static void mapCoordInSelfToDescendant(View descendant, View root, int[] coord) {
|
||||
public static void mapCoordInSelfToDescendant(View descendant, View root, float[] coord) {
|
||||
sMatrix.reset();
|
||||
View v = descendant;
|
||||
while(v != root) {
|
||||
@@ -211,12 +229,23 @@ public final class Utilities {
|
||||
}
|
||||
sMatrix.postTranslate(-v.getScrollX(), -v.getScrollY());
|
||||
sMatrix.invert(sInverseMatrix);
|
||||
sInverseMatrix.mapPoints(coord);
|
||||
}
|
||||
|
||||
sPoint[0] = coord[0];
|
||||
sPoint[1] = coord[1];
|
||||
sInverseMatrix.mapPoints(sPoint);
|
||||
coord[0] = Math.round(sPoint[0]);
|
||||
coord[1] = Math.round(sPoint[1]);
|
||||
/**
|
||||
* Sets {@param out} to be same as {@param in} by rounding individual values
|
||||
*/
|
||||
public static void roundArray(float[] in, int[] out) {
|
||||
for (int i = 0; i < in.length; i++) {
|
||||
out[i] = Math.round(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void offsetPoints(float[] points, float offsetX, float offsetY) {
|
||||
for (int i = 0; i < points.length; i += 2) {
|
||||
points[i] += offsetX;
|
||||
points[i + 1] += offsetY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,53 +598,6 @@ public final class Utilities {
|
||||
return String.format(Locale.ENGLISH, "%d,%d", x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location bounds of a view.
|
||||
* - For DeepShortcutView, we return the bounds of the icon view.
|
||||
* - For BubbleTextView, we return the icon bounds.
|
||||
*/
|
||||
public static void getLocationBoundsForView(Launcher launcher, View v, Rect outRect) {
|
||||
final DragLayer dragLayer = launcher.getDragLayer();
|
||||
final boolean isBubbleTextView = v instanceof BubbleTextView;
|
||||
final boolean isFolderIcon = v instanceof FolderIcon;
|
||||
final Rect rect = new Rect();
|
||||
|
||||
// Deep shortcut views have their icon drawn in a separate view.
|
||||
final boolean fromDeepShortcutView = v.getParent() instanceof DeepShortcutView;
|
||||
if (v instanceof DeepShortcutView) {
|
||||
dragLayer.getDescendantRectRelativeToSelf(((DeepShortcutView) v).getIconView(), rect);
|
||||
} else if (fromDeepShortcutView) {
|
||||
DeepShortcutView view = (DeepShortcutView) v.getParent();
|
||||
dragLayer.getDescendantRectRelativeToSelf(view.getIconView(), rect);
|
||||
} else if ((isBubbleTextView || isFolderIcon) && v.getTag() instanceof ItemInfo
|
||||
&& (((ItemInfo) v.getTag()).container == CONTAINER_DESKTOP
|
||||
|| ((ItemInfo) v.getTag()).container == CONTAINER_HOTSEAT)) {
|
||||
CellLayout pageViewIsOn = ((CellLayout) v.getParent().getParent());
|
||||
int pageNum = launcher.getWorkspace().indexOfChild(pageViewIsOn);
|
||||
|
||||
DeviceProfile dp = launcher.getDeviceProfile();
|
||||
ItemInfo info = ((ItemInfo) v.getTag());
|
||||
dp.getItemLocation(info.cellX, info.cellY, info.spanX, info.spanY,
|
||||
info.container, pageNum - launcher.getCurrentWorkspaceScreen(), rect);
|
||||
} else {
|
||||
dragLayer.getDescendantRectRelativeToSelf(v, rect);
|
||||
}
|
||||
int viewLocationLeft = rect.left;
|
||||
int viewLocationTop = rect.top;
|
||||
|
||||
if (isBubbleTextView && !fromDeepShortcutView) {
|
||||
((BubbleTextView) v).getIconBounds(rect);
|
||||
} else if (isFolderIcon) {
|
||||
((FolderIcon) v).getPreviewBounds(rect);
|
||||
} else {
|
||||
rect.set(0, 0, rect.width(), rect.height());
|
||||
}
|
||||
viewLocationLeft += rect.left;
|
||||
viewLocationTop += rect.top;
|
||||
outRect.set(viewLocationLeft, viewLocationTop, viewLocationLeft + rect.width(),
|
||||
viewLocationTop + rect.height());
|
||||
}
|
||||
|
||||
public static void unregisterReceiverSafely(Context context, BroadcastReceiver receiver) {
|
||||
try {
|
||||
context.unregisterReceiver(receiver);
|
||||
|
||||
@@ -82,6 +82,7 @@ import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
|
||||
@@ -175,7 +176,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
@Thunk final Launcher mLauncher;
|
||||
@Thunk DragController mDragController;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final int[] mTempXY = new int[2];
|
||||
private final float[] mTempFXY = new float[2];
|
||||
@Thunk float[] mDragViewVisualCenter = new float[2];
|
||||
private final float[] mTempTouchCoordinates = new float[2];
|
||||
|
||||
@@ -285,18 +288,23 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
mInsets.set(insets);
|
||||
|
||||
DeviceProfile grid = mLauncher.getDeviceProfile();
|
||||
mMaxDistanceForFolderCreation = grid.isTablet
|
||||
? 0.75f * grid.iconSizePx
|
||||
: 0.55f * grid.iconSizePx;
|
||||
DeviceProfile stableGrid = mLauncher.getWallpaperDeviceProfile();
|
||||
|
||||
mMaxDistanceForFolderCreation = stableGrid.isTablet
|
||||
? 0.75f * stableGrid.iconSizePx
|
||||
: 0.55f * stableGrid.iconSizePx;
|
||||
mWorkspaceFadeInAdjacentScreens = grid.shouldFadeAdjacentWorkspaceScreens();
|
||||
|
||||
Rect padding = grid.workspacePadding;
|
||||
setPadding(padding.left, padding.top, padding.right, padding.bottom);
|
||||
Rect padding = stableGrid.workspacePadding;
|
||||
|
||||
if (grid.shouldFadeAdjacentWorkspaceScreens()) {
|
||||
RotationMode rotationMode = mLauncher.getRotationMode();
|
||||
|
||||
rotationMode.mapRect(padding, mTempRect);
|
||||
setPadding(mTempRect.left, mTempRect.top, mTempRect.right, mTempRect.bottom);
|
||||
rotationMode.mapRect(insets, mInsets);
|
||||
|
||||
if (mWorkspaceFadeInAdjacentScreens) {
|
||||
// In landscape mode the page spacing is set to the default.
|
||||
setPageSpacing(grid.edgeMarginPx);
|
||||
} else {
|
||||
@@ -306,11 +314,13 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
setPageSpacing(Math.max(grid.edgeMarginPx, padding.left + 1));
|
||||
}
|
||||
|
||||
int paddingLeftRight = grid.cellLayoutPaddingLeftRightPx;
|
||||
int paddingBottom = grid.cellLayoutBottomPaddingPx;
|
||||
|
||||
int paddingLeftRight = stableGrid.cellLayoutPaddingLeftRightPx;
|
||||
int paddingBottom = stableGrid.cellLayoutBottomPaddingPx;
|
||||
for (int i = mWorkspaceScreens.size() - 1; i >= 0; i--) {
|
||||
mWorkspaceScreens.valueAt(i)
|
||||
.setPadding(paddingLeftRight, 0, paddingLeftRight, paddingBottom);
|
||||
CellLayout page = mWorkspaceScreens.valueAt(i);
|
||||
page.setRotationMode(rotationMode);
|
||||
page.setPadding(paddingLeftRight, 0, paddingLeftRight, paddingBottom);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,7 +340,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
|
||||
float scale = 1;
|
||||
if (isWidget) {
|
||||
DeviceProfile profile = mLauncher.getDeviceProfile();
|
||||
DeviceProfile profile = mLauncher.getWallpaperDeviceProfile();
|
||||
scale = Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y);
|
||||
}
|
||||
size[0] = r.width();
|
||||
@@ -550,8 +560,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
// created CellLayout.
|
||||
CellLayout newScreen = (CellLayout) LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.workspace_screen, this, false /* attachToRoot */);
|
||||
int paddingLeftRight = mLauncher.getDeviceProfile().cellLayoutPaddingLeftRightPx;
|
||||
int paddingBottom = mLauncher.getDeviceProfile().cellLayoutBottomPaddingPx;
|
||||
DeviceProfile grid = mLauncher.getWallpaperDeviceProfile();
|
||||
int paddingLeftRight = grid.cellLayoutPaddingLeftRightPx;
|
||||
int paddingBottom = grid.cellLayoutBottomPaddingPx;
|
||||
newScreen.setRotationMode(mLauncher.getRotationMode());
|
||||
newScreen.setPadding(paddingLeftRight, 0, paddingLeftRight, paddingBottom);
|
||||
|
||||
mWorkspaceScreens.put(screenId, newScreen);
|
||||
@@ -1930,18 +1942,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
if (child == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ShortcutAndWidgetContainer boundingLayout = child.getShortcutsAndWidgets();
|
||||
|
||||
// Use the absolute left instead of the child left, as we want the visible area
|
||||
// irrespective of the visible child. Since the view can only scroll horizontally, the
|
||||
// top position is not affected.
|
||||
mTempXY[0] = getPaddingLeft() + boundingLayout.getLeft();
|
||||
mTempXY[1] = child.getTop() + boundingLayout.getTop();
|
||||
|
||||
float scale = mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempXY);
|
||||
outArea.set(mTempXY[0], mTempXY[1],
|
||||
(int) (mTempXY[0] + scale * boundingLayout.getMeasuredWidth()),
|
||||
(int) (mTempXY[1] + scale * boundingLayout.getMeasuredHeight()));
|
||||
mLauncher.getDragLayer().getDescendantRectRelativeToSelf(boundingLayout, outArea);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2094,14 +2097,14 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
}
|
||||
|
||||
boolean isPointInSelfOverHotseat(int x, int y) {
|
||||
mTempXY[0] = x;
|
||||
mTempXY[1] = y;
|
||||
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempXY, true);
|
||||
mTempFXY[0] = x;
|
||||
mTempFXY[1] = y;
|
||||
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempFXY, true);
|
||||
View hotseat = mLauncher.getHotseat();
|
||||
return mTempXY[0] >= hotseat.getLeft() &&
|
||||
mTempXY[0] <= hotseat.getRight() &&
|
||||
mTempXY[1] >= hotseat.getTop() &&
|
||||
mTempXY[1] <= hotseat.getBottom();
|
||||
return mTempFXY[0] >= hotseat.getLeft() &&
|
||||
mTempFXY[0] <= hotseat.getRight() &&
|
||||
mTempFXY[1] >= hotseat.getTop() &&
|
||||
mTempFXY[1] <= hotseat.getBottom();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2111,13 +2114,8 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
*/
|
||||
private void mapPointFromDropLayout(CellLayout layout, float[] xy) {
|
||||
if (mLauncher.isHotseatLayout(layout)) {
|
||||
mTempXY[0] = (int) xy[0];
|
||||
mTempXY[1] = (int) xy[1];
|
||||
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempXY, true);
|
||||
mLauncher.getDragLayer().mapCoordInSelfToDescendant(layout, mTempXY);
|
||||
|
||||
xy[0] = mTempXY[0];
|
||||
xy[1] = mTempXY[1];
|
||||
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, xy, true);
|
||||
mLauncher.getDragLayer().mapCoordInSelfToDescendant(layout, xy);
|
||||
} else {
|
||||
mapPointFromSelfToChild(layout, xy);
|
||||
}
|
||||
@@ -2608,13 +2606,14 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
DeviceProfile profile = mLauncher.getDeviceProfile();
|
||||
Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y);
|
||||
}
|
||||
loc[0] = r.left;
|
||||
loc[1] = r.top;
|
||||
|
||||
mTempFXY[0] = r.left;
|
||||
mTempFXY[1] = r.top;
|
||||
setFinalTransitionTransform();
|
||||
float cellLayoutScale =
|
||||
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, loc, true);
|
||||
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, mTempFXY, true);
|
||||
resetTransitionTransform();
|
||||
Utilities.roundArray(mTempFXY, loc);
|
||||
|
||||
if (scale) {
|
||||
float dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
|
||||
|
||||
@@ -93,14 +93,16 @@ public class WorkspaceStateTransitionAnimation {
|
||||
Interpolator scaleInterpolator = builder.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
|
||||
propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
|
||||
|
||||
// Set the hotseat's pivot point to match the workspace's, so that it scales together.
|
||||
DragLayer dragLayer = mLauncher.getDragLayer();
|
||||
int[] workspacePivot = new int[]{(int) mWorkspace.getPivotX(),
|
||||
(int) mWorkspace.getPivotY()};
|
||||
dragLayer.getDescendantCoordRelativeToSelf(mWorkspace, workspacePivot);
|
||||
dragLayer.mapCoordInSelfToDescendant(hotseat, workspacePivot);
|
||||
hotseat.setPivotX(workspacePivot[0]);
|
||||
hotseat.setPivotY(workspacePivot[1]);
|
||||
if (!hotseat.getRotationMode().isTransposed) {
|
||||
// Set the hotseat's pivot point to match the workspace's, so that it scales together.
|
||||
DragLayer dragLayer = mLauncher.getDragLayer();
|
||||
float[] workspacePivot =
|
||||
new float[]{ mWorkspace.getPivotX(), mWorkspace.getPivotY() };
|
||||
dragLayer.getDescendantCoordRelativeToSelf(mWorkspace, workspacePivot);
|
||||
dragLayer.mapCoordInSelfToDescendant(hotseat, workspacePivot);
|
||||
hotseat.setPivotX(workspacePivot[0]);
|
||||
hotseat.setPivotY(workspacePivot[1]);
|
||||
}
|
||||
float hotseatScale = hotseatScaleAndTranslation.scale;
|
||||
propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale, scaleInterpolator);
|
||||
|
||||
|
||||
@@ -110,6 +110,10 @@ abstract class BaseFlags {
|
||||
"ENABLE_HINTS_IN_OVERVIEW", false,
|
||||
"Show chip hints and gleams on the overview screen");
|
||||
|
||||
public static final TogglableFlag FAKE_LANDSCAPE_UI = new TogglableFlag(
|
||||
"FAKE_LANDSCAPE_UI", false,
|
||||
"Rotate launcher UI instead of using transposed layout");
|
||||
|
||||
public static void initialize(Context context) {
|
||||
// Avoid the disk read for user builds
|
||||
if (Utilities.IS_DEBUG_DEVICE) {
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
package com.android.launcher3.dragndrop;
|
||||
|
||||
import static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.getMode;
|
||||
import static android.view.View.MeasureSpec.getSize;
|
||||
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -29,12 +33,14 @@ import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
@@ -42,6 +48,7 @@ import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DropTargetBar;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
@@ -52,6 +59,7 @@ import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.uioverrides.UiFactory;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.views.Transposable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -260,10 +268,10 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
||||
Rect r = new Rect();
|
||||
getViewRectRelativeToSelf(dragView, r);
|
||||
|
||||
int coord[] = new int[2];
|
||||
float coord[] = new float[2];
|
||||
float childScale = child.getScaleX();
|
||||
coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2);
|
||||
coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2);
|
||||
coord[0] = lp.x + (child.getMeasuredWidth() * (1 - childScale) / 2);
|
||||
coord[1] = lp.y + (child.getMeasuredHeight() * (1 - childScale) / 2);
|
||||
|
||||
// Since the child hasn't necessarily been laid out, we force the lp to be updated with
|
||||
// the correct coordinates (above) and use these to determine the final location
|
||||
@@ -271,8 +279,8 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
||||
// We need to account for the scale of the child itself, as the above only accounts for
|
||||
// for the scale in parents.
|
||||
scale *= childScale;
|
||||
int toX = coord[0];
|
||||
int toY = coord[1];
|
||||
int toX = Math.round(coord[0]);
|
||||
int toY = Math.round(coord[1]);
|
||||
float toScale = scale;
|
||||
if (child instanceof TextView) {
|
||||
TextView tv = (TextView) child;
|
||||
@@ -551,4 +559,159 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
||||
public WorkspaceAndHotseatScrim getScrim() {
|
||||
return mScrim;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
RotationMode rotation = mActivity.getRotationMode();
|
||||
int count = getChildCount();
|
||||
|
||||
if (!rotation.isTransposed
|
||||
|| getMode(widthMeasureSpec) != EXACTLY
|
||||
|| getMode(heightMeasureSpec) != EXACTLY) {
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
child.setRotation(rotation.surfaceRotation);
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
} else {
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
if (!(child instanceof Transposable)) {
|
||||
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
|
||||
} else {
|
||||
measureChildWithMargins(child, heightMeasureSpec, 0, widthMeasureSpec, 0);
|
||||
|
||||
child.setPivotX(child.getMeasuredWidth() / 2);
|
||||
child.setPivotY(child.getMeasuredHeight() / 2);
|
||||
child.setRotation(rotation.surfaceRotation);
|
||||
}
|
||||
}
|
||||
setMeasuredDimension(getSize(widthMeasureSpec), getSize(heightMeasureSpec));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
RotationMode rotation = mActivity.getRotationMode();
|
||||
if (!rotation.isTransposed) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
return;
|
||||
}
|
||||
|
||||
final int count = getChildCount();
|
||||
|
||||
final int parentWidth = right - left;
|
||||
final int parentHeight = bottom - top;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (lp instanceof LayoutParams) {
|
||||
final LayoutParams dlp = (LayoutParams) lp;
|
||||
if (dlp.customPosition) {
|
||||
child.layout(dlp.x, dlp.y, dlp.x + dlp.width, dlp.y + dlp.height);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
final int width = child.getMeasuredWidth();
|
||||
final int height = child.getMeasuredHeight();
|
||||
|
||||
int childLeft;
|
||||
int childTop;
|
||||
|
||||
int gravity = lp.gravity;
|
||||
if (gravity == -1) {
|
||||
gravity = Gravity.TOP | Gravity.START;
|
||||
}
|
||||
|
||||
final int layoutDirection = getLayoutDirection();
|
||||
|
||||
int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
|
||||
int horizontalGravity = absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
|
||||
int verticalGravity = absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK;
|
||||
|
||||
if (child instanceof Transposable) {
|
||||
if (rotation == RotationMode.SEASCAPE) {
|
||||
if (horizontalGravity == Gravity.RIGHT) {
|
||||
horizontalGravity = Gravity.LEFT;
|
||||
} else if (horizontalGravity == Gravity.LEFT) {
|
||||
horizontalGravity = Gravity.RIGHT;
|
||||
}
|
||||
|
||||
if (verticalGravity == Gravity.TOP) {
|
||||
verticalGravity = Gravity.BOTTOM;
|
||||
} else if (verticalGravity == Gravity.BOTTOM) {
|
||||
verticalGravity = Gravity.TOP;
|
||||
}
|
||||
}
|
||||
|
||||
switch (horizontalGravity) {
|
||||
case Gravity.CENTER_HORIZONTAL:
|
||||
childTop = (parentHeight - height) / 2 +
|
||||
lp.topMargin - lp.bottomMargin;
|
||||
break;
|
||||
case Gravity.RIGHT:
|
||||
childTop = width / 2 + lp.rightMargin - height / 2;
|
||||
break;
|
||||
case Gravity.LEFT:
|
||||
default:
|
||||
childTop = parentHeight - lp.leftMargin - width / 2 - height / 2;
|
||||
}
|
||||
|
||||
switch (verticalGravity) {
|
||||
case Gravity.CENTER_VERTICAL:
|
||||
childLeft = (parentWidth - width) / 2 +
|
||||
lp.leftMargin - lp.rightMargin;
|
||||
break;
|
||||
case Gravity.BOTTOM:
|
||||
childLeft = parentWidth - width / 2 - height / 2 - lp.bottomMargin;
|
||||
break;
|
||||
case Gravity.TOP:
|
||||
default:
|
||||
childLeft = height / 2 - width / 2 + lp.topMargin;
|
||||
}
|
||||
} else {
|
||||
switch (horizontalGravity) {
|
||||
case Gravity.CENTER_HORIZONTAL:
|
||||
childLeft = (parentWidth - width) / 2 +
|
||||
lp.leftMargin - lp.rightMargin;
|
||||
break;
|
||||
case Gravity.RIGHT:
|
||||
childLeft = parentWidth - width - lp.rightMargin;
|
||||
break;
|
||||
case Gravity.LEFT:
|
||||
default:
|
||||
childLeft = lp.leftMargin;
|
||||
}
|
||||
|
||||
switch (verticalGravity) {
|
||||
case Gravity.TOP:
|
||||
childTop = lp.topMargin;
|
||||
break;
|
||||
case Gravity.CENTER_VERTICAL:
|
||||
childTop = (parentHeight - height) / 2 +
|
||||
lp.topMargin - lp.bottomMargin;
|
||||
break;
|
||||
case Gravity.BOTTOM:
|
||||
childTop = parentHeight - height - lp.bottomMargin;
|
||||
break;
|
||||
default:
|
||||
childTop = lp.topMargin;
|
||||
}
|
||||
}
|
||||
|
||||
child.layout(childLeft, childTop, childLeft + width, childTop + height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,7 +869,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
DeviceProfile grid = mLauncher.getDeviceProfile();
|
||||
|
||||
DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
|
||||
DragLayer parent = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
|
||||
DragLayer parent = mLauncher.getDragLayer();
|
||||
int width = getFolderWidth();
|
||||
int height = getFolderHeight();
|
||||
|
||||
@@ -881,8 +881,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
|
||||
// We need to bound the folder to the currently visible workspace area
|
||||
if (mLauncher.getStateManager().getState().overviewUi) {
|
||||
mLauncher.getDragLayer().getDescendantRectRelativeToSelf(mLauncher.getOverviewPanel(),
|
||||
sTempRect);
|
||||
parent.getDescendantRectRelativeToSelf(mLauncher.getOverviewPanel(), sTempRect);
|
||||
} else {
|
||||
mLauncher.getWorkspace().getPageAreaRelativeToDragLayer(sTempRect);
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||
"is dependent on this");
|
||||
}
|
||||
|
||||
DeviceProfile grid = launcher.getDeviceProfile();
|
||||
DeviceProfile grid = launcher.getWallpaperDeviceProfile();
|
||||
FolderIcon icon = (FolderIcon) LayoutInflater.from(group.getContext())
|
||||
.inflate(resId, group, false);
|
||||
|
||||
@@ -174,7 +174,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||
icon.setOnClickListener(ItemClickHandler.INSTANCE);
|
||||
icon.mInfo = folderInfo;
|
||||
icon.mLauncher = launcher;
|
||||
icon.mDotRenderer = launcher.getDeviceProfile().mDotRenderer;
|
||||
icon.mDotRenderer = grid.mDotRenderer;
|
||||
icon.setContentDescription(launcher.getString(R.string.folder_name_format, folderInfo.title));
|
||||
Folder folder = Folder.fromXml(launcher);
|
||||
folder.setDragController(launcher.getDragController());
|
||||
@@ -508,7 +508,8 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||
public void drawDot(Canvas canvas) {
|
||||
if ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0) {
|
||||
Rect iconBounds = mDotParams.iconBounds;
|
||||
BubbleTextView.getIconBounds(this, iconBounds, mLauncher.getDeviceProfile().iconSizePx);
|
||||
BubbleTextView.getIconBounds(this, iconBounds,
|
||||
mLauncher.getWallpaperDeviceProfile().iconSizePx);
|
||||
|
||||
// If we are animating to the accepting state, animate the dot out.
|
||||
mDotParams.scale = Math.max(0, mDotScale - mBackground.getScaleProgress());
|
||||
|
||||
@@ -42,7 +42,6 @@ import android.view.View;
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
/**
|
||||
@@ -135,7 +134,7 @@ public class PreviewBackground {
|
||||
mBgColor = ta.getColor(R.styleable.FolderIconPreview_android_colorPrimary, 0);
|
||||
ta.recycle();
|
||||
|
||||
DeviceProfile grid = activity.getDeviceProfile();
|
||||
DeviceProfile grid = activity.getWallpaperDeviceProfile();
|
||||
previewSize = grid.folderIconSizePx;
|
||||
|
||||
basePreviewOffsetX = (availableSpaceX - previewSize) / 2;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.graphics;
|
||||
|
||||
import android.graphics.Rect;
|
||||
|
||||
public abstract class RotationMode {
|
||||
|
||||
public final float surfaceRotation;
|
||||
public final boolean isTransposed;
|
||||
|
||||
private RotationMode(float surfaceRotation) {
|
||||
this.surfaceRotation = surfaceRotation;
|
||||
isTransposed = surfaceRotation != 0;
|
||||
}
|
||||
|
||||
public final void mapRect(Rect rect, Rect out) {
|
||||
mapRect(rect.left, rect.top, rect.right, rect.bottom, out);
|
||||
}
|
||||
|
||||
public void mapRect(int left, int top, int right, int bottom, Rect out) {
|
||||
out.set(left, top, right, bottom);
|
||||
}
|
||||
|
||||
public static RotationMode NORMAL = new RotationMode(0) { };
|
||||
|
||||
public static RotationMode LANDSCAPE = new RotationMode(-90) {
|
||||
@Override
|
||||
public void mapRect(int left, int top, int right, int bottom, Rect out) {
|
||||
out.left = top;
|
||||
out.top = right;
|
||||
out.right = bottom;
|
||||
out.bottom = left;
|
||||
}
|
||||
};
|
||||
|
||||
public static RotationMode SEASCAPE = new RotationMode(90) {
|
||||
@Override
|
||||
public void mapRect(int left, int top, int right, int bottom, Rect out) {
|
||||
out.left = bottom;
|
||||
out.top = left;
|
||||
out.right = top;
|
||||
out.bottom = right;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import android.view.View.AccessibilityDelegate;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
|
||||
/**
|
||||
@@ -56,6 +57,19 @@ public interface ActivityContext {
|
||||
|
||||
DeviceProfile getDeviceProfile();
|
||||
|
||||
/**
|
||||
* Device profile to be used by UI elements which are shown directly on top of the wallpaper
|
||||
* and whose presentation is tied to the wallpaper (and physical device) and not the activity
|
||||
* configuration.
|
||||
*/
|
||||
default DeviceProfile getWallpaperDeviceProfile() {
|
||||
return getDeviceProfile();
|
||||
}
|
||||
|
||||
default RotationMode getRotationMode() {
|
||||
return RotationMode.NORMAL;
|
||||
}
|
||||
|
||||
static ActivityContext lookupContext(Context context) {
|
||||
if (context instanceof ActivityContext) {
|
||||
return (ActivityContext) context;
|
||||
|
||||
@@ -88,7 +88,8 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
||||
// Touch is being dispatched through a proxy from InputMonitor
|
||||
private static final int TOUCH_DISPATCHING_PROXY = 1 << 2;
|
||||
|
||||
protected final int[] mTmpXY = new int[2];
|
||||
protected final float[] mTmpXY = new float[2];
|
||||
protected final float[] mTmpRectPoints = new float[4];
|
||||
protected final Rect mHitRect = new Rect();
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
@@ -306,14 +307,16 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
||||
* @return The factor by which this descendant is scaled relative to this DragLayer.
|
||||
*/
|
||||
public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
|
||||
mTmpXY[0] = 0;
|
||||
mTmpXY[1] = 0;
|
||||
float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
|
||||
|
||||
r.set(mTmpXY[0], mTmpXY[1],
|
||||
(int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()),
|
||||
(int) (mTmpXY[1] + scale * descendant.getMeasuredHeight()));
|
||||
return scale;
|
||||
mTmpRectPoints[0] = 0;
|
||||
mTmpRectPoints[1] = 0;
|
||||
mTmpRectPoints[2] = descendant.getWidth();
|
||||
mTmpRectPoints[3] = descendant.getHeight();
|
||||
float s = getDescendantCoordRelativeToSelf(descendant, mTmpRectPoints);
|
||||
r.left = Math.round(Math.min(mTmpRectPoints[0], mTmpRectPoints[2]));
|
||||
r.top = Math.round(Math.min(mTmpRectPoints[1], mTmpRectPoints[3]));
|
||||
r.right = Math.round(Math.max(mTmpRectPoints[0], mTmpRectPoints[2]));
|
||||
r.bottom = Math.round(Math.max(mTmpRectPoints[1], mTmpRectPoints[3]));
|
||||
return s;
|
||||
}
|
||||
|
||||
public float getLocationInDragLayer(View child, int[] loc) {
|
||||
@@ -323,6 +326,14 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
||||
}
|
||||
|
||||
public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
|
||||
mTmpXY[0] = coord[0];
|
||||
mTmpXY[1] = coord[1];
|
||||
float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
|
||||
Utilities.roundArray(mTmpXY, coord);
|
||||
return scale;
|
||||
}
|
||||
|
||||
public float getDescendantCoordRelativeToSelf(View descendant, float[] coord) {
|
||||
return getDescendantCoordRelativeToSelf(descendant, coord, false);
|
||||
}
|
||||
|
||||
@@ -338,17 +349,27 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
||||
* this scale factor is assumed to be equal in X and Y, and so if at any point this
|
||||
* assumption fails, we will need to return a pair of scale factors.
|
||||
*/
|
||||
public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
|
||||
public float getDescendantCoordRelativeToSelf(View descendant, float[] coord,
|
||||
boolean includeRootScroll) {
|
||||
return Utilities.getDescendantCoordRelativeToAncestor(descendant, this,
|
||||
coord, includeRootScroll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of {@link #getDescendantCoordRelativeToSelf(View, float[])}.
|
||||
*/
|
||||
public void mapCoordInSelfToDescendant(View descendant, float[] coord) {
|
||||
Utilities.mapCoordInSelfToDescendant(descendant, this, coord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
|
||||
*/
|
||||
public void mapCoordInSelfToDescendant(View descendant, int[] coord) {
|
||||
Utilities.mapCoordInSelfToDescendant(descendant, this, coord);
|
||||
mTmpXY[0] = coord[0];
|
||||
mTmpXY[1] = coord[1];
|
||||
Utilities.mapCoordInSelfToDescendant(descendant, this, mTmpXY);
|
||||
Utilities.roundArray(mTmpXY, coord);
|
||||
}
|
||||
|
||||
public void getViewRectRelativeToSelf(View v, Rect r) {
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
|
||||
import static com.android.launcher3.Utilities.mapToRange;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
|
||||
|
||||
@@ -23,6 +26,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
@@ -61,12 +65,10 @@ import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import static com.android.launcher3.Utilities.mapToRange;
|
||||
|
||||
/**
|
||||
* A view that is created to look like another view with the purpose of creating fluid animations.
|
||||
*/
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
public class FloatingIconView extends View implements Animator.AnimatorListener, ClipPathView {
|
||||
|
||||
public static final float SHAPE_PROGRESS_DURATION = 0.15f;
|
||||
@@ -186,14 +188,16 @@ public class FloatingIconView extends View implements Animator.AnimatorListener,
|
||||
* @param v The view to copy
|
||||
* @param positionOut Rect that will hold the size and position of v.
|
||||
*/
|
||||
private void matchPositionOf(Launcher launcher, View v, Rect positionOut) {
|
||||
Utilities.getLocationBoundsForView(launcher, v, positionOut);
|
||||
final LayoutParams lp = new LayoutParams(positionOut.width(), positionOut.height());
|
||||
private void matchPositionOf(Launcher launcher, View v, RectF positionOut) {
|
||||
getLocationBoundsForView(launcher, v, positionOut);
|
||||
final LayoutParams lp = new LayoutParams(
|
||||
Math.round(positionOut.width()),
|
||||
Math.round(positionOut.height()));
|
||||
lp.ignoreInsets = true;
|
||||
|
||||
// Position the floating view exactly on top of the original
|
||||
lp.leftMargin = positionOut.left;
|
||||
lp.topMargin = positionOut.top;
|
||||
lp.leftMargin = Math.round(positionOut.left);
|
||||
lp.topMargin = Math.round(positionOut.top);
|
||||
setLayoutParams(lp);
|
||||
// Set the properties here already to make sure they are available when running the first
|
||||
// animation frame.
|
||||
@@ -201,6 +205,57 @@ public class FloatingIconView extends View implements Animator.AnimatorListener,
|
||||
+ lp.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location bounds of a view.
|
||||
* - For DeepShortcutView, we return the bounds of the icon view.
|
||||
* - For BubbleTextView, we return the icon bounds.
|
||||
*/
|
||||
private void getLocationBoundsForView(Launcher launcher, View v, RectF outRect) {
|
||||
final boolean isBubbleTextView = v instanceof BubbleTextView;
|
||||
final boolean isFolderIcon = v instanceof FolderIcon;
|
||||
|
||||
// Deep shortcut views have their icon drawn in a separate view.
|
||||
final boolean fromDeepShortcutView = v.getParent() instanceof DeepShortcutView;
|
||||
|
||||
final View targetView;
|
||||
boolean ignoreTransform = false;
|
||||
|
||||
if (v instanceof DeepShortcutView) {
|
||||
targetView = ((DeepShortcutView) v).getIconView();
|
||||
} else if (fromDeepShortcutView) {
|
||||
DeepShortcutView view = (DeepShortcutView) v.getParent();
|
||||
targetView = view.getIconView();
|
||||
} else if ((isBubbleTextView || isFolderIcon) && v.getTag() instanceof ItemInfo
|
||||
&& (((ItemInfo) v.getTag()).container == CONTAINER_DESKTOP
|
||||
|| ((ItemInfo) v.getTag()).container == CONTAINER_HOTSEAT)) {
|
||||
targetView = v;
|
||||
ignoreTransform = true;
|
||||
} else {
|
||||
targetView = v;
|
||||
}
|
||||
|
||||
float[] points = new float[] {0, 0, targetView.getWidth(), targetView.getHeight()};
|
||||
Utilities.getDescendantCoordRelativeToAncestor(targetView, launcher.getDragLayer(), points,
|
||||
false, ignoreTransform);
|
||||
|
||||
float viewLocationLeft = Math.min(points[0], points[2]);
|
||||
float viewLocationTop = Math.min(points[1], points[3]);
|
||||
|
||||
final Rect iconRect = new Rect();
|
||||
if (isBubbleTextView && !fromDeepShortcutView) {
|
||||
((BubbleTextView) v).getIconBounds(iconRect);
|
||||
} else if (isFolderIcon) {
|
||||
((FolderIcon) v).getPreviewBounds(iconRect);
|
||||
} else {
|
||||
iconRect.set(0, 0, Math.abs(Math.round(points[2] - points[0])),
|
||||
Math.abs(Math.round(points[3] - points[1])));
|
||||
}
|
||||
viewLocationLeft += iconRect.left;
|
||||
viewLocationTop += iconRect.top;
|
||||
outRect.set(viewLocationLeft, viewLocationTop, viewLocationLeft + iconRect.width(),
|
||||
viewLocationTop + iconRect.height());
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private void getIcon(Launcher launcher, View v, ItemInfo info, boolean isOpening,
|
||||
Runnable onIconLoadedRunnable, CancellationSignal loadIconSignal) {
|
||||
@@ -411,7 +466,7 @@ public class FloatingIconView extends View implements Animator.AnimatorListener,
|
||||
* @param isOpening True if this view replaces the icon for app open animation.
|
||||
*/
|
||||
public static FloatingIconView getFloatingIconView(Launcher launcher, View originalView,
|
||||
boolean hideOriginal, Rect positionOut, boolean isOpening, FloatingIconView recycle) {
|
||||
boolean hideOriginal, RectF positionOut, boolean isOpening, FloatingIconView recycle) {
|
||||
if (recycle != null) {
|
||||
recycle.recycle();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
|
||||
/**
|
||||
* Indicates that a view can be transposed.
|
||||
*/
|
||||
public interface Transposable {
|
||||
|
||||
RotationMode getRotationMode();
|
||||
}
|
||||
Reference in New Issue
Block a user