Render user's actual workspace in ThemePicker preview (Part 2)

With this change, we can also render folders in preview. It's built on top of part 1.

Test: Go to grid options, choose a different grid option, and see user's workspace rendered in the preview
Bug: 144052839
Change-Id: Iaf6d8af6b909ece4147ea250d95dec3d2c0019d3
This commit is contained in:
Tracy Zhou 2019-12-09 13:42:57 -08:00
parent 290f2cb028
commit 4d7b244f3f
6 changed files with 60 additions and 35 deletions

View File

@ -47,7 +47,7 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView {
private static final float RING_EFFECT_RATIO = 0.11f; private static final float RING_EFFECT_RATIO = 0.11f;
private DeviceProfile mDeviceProfile; private final DeviceProfile mDeviceProfile;
private final Paint mIconRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint mIconRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private boolean mIsPinned = false; private boolean mIsPinned = false;
private int mNormalizedIconRadius; private int mNormalizedIconRadius;
@ -65,7 +65,7 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView {
mDeviceProfile = Launcher.getLauncher(context).getDeviceProfile(); mDeviceProfile = Launcher.getLauncher(context).getDeviceProfile();
mNormalizedIconRadius = IconNormalizer.getNormalizedCircleSize(getIconSize()) / 2; mNormalizedIconRadius = IconNormalizer.getNormalizedCircleSize(getIconSize()) / 2;
setOnClickListener(ItemClickHandler.INSTANCE); setOnClickListener(ItemClickHandler.INSTANCE);
setOnFocusChangeListener(Launcher.getLauncher(context).mFocusHandler); setOnFocusChangeListener(Launcher.getLauncher(context).getFocusHandler());
} }
@Override @Override

View File

@ -307,7 +307,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
// Request id for any pending activity result // Request id for any pending activity result
protected int mPendingActivityRequestCode = -1; protected int mPendingActivityRequestCode = -1;
public ViewGroupFocusHelper mFocusHandler; private ViewGroupFocusHelper mFocusHandler;
private RotationHelper mRotationHelper; private RotationHelper mRotationHelper;
@ -617,6 +617,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
return mRotationHelper; return mRotationHelper;
} }
public ViewGroupFocusHelper getFocusHandler() {
return mFocusHandler;
}
public LauncherStateManager getStateManager() { public LauncherStateManager getStateManager() {
return mStateManager; return mStateManager;
} }
@ -1740,7 +1744,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
getModelWriter().addItemToDatabase(folderInfo, container, screenId, cellX, cellY); getModelWriter().addItemToDatabase(folderInfo, container, screenId, cellX, cellY);
// Create the view // Create the view
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo); FolderIcon newFolder = FolderIcon.inflateFolderAndIcon(R.layout.folder_icon, this, layout, folderInfo);
mWorkspace.addInScreen(newFolder, folderInfo); mWorkspace.addInScreen(newFolder, folderInfo);
// Force measure the new folder icon // Force measure the new folder icon
CellLayout parent = mWorkspace.getParentCellLayoutForView(newFolder); CellLayout parent = mWorkspace.getParentCellLayoutForView(newFolder);
@ -2101,7 +2105,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
break; break;
} }
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: { case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: {
view = FolderIcon.fromXml(R.layout.folder_icon, this, view = FolderIcon.inflateFolderAndIcon(R.layout.folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()), (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
(FolderInfo) item); (FolderInfo) item);
break; break;

View File

@ -83,7 +83,6 @@ import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.pageindicators.WorkspacePageIndicator; import com.android.launcher3.pageindicators.WorkspacePageIndicator;
import com.android.launcher3.popup.PopupContainerWithArrow; import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider; import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.WorkspaceTouchListener; import com.android.launcher3.touch.WorkspaceTouchListener;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@ -2547,7 +2546,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
view = mLauncher.createShortcut(cellLayout, (WorkspaceItemInfo) info); view = mLauncher.createShortcut(cellLayout, (WorkspaceItemInfo) info);
break; break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout, view = FolderIcon.inflateFolderAndIcon(R.layout.folder_icon, mLauncher, cellLayout,
(FolderInfo) info); (FolderInfo) info);
break; break;
default: default:

View File

@ -67,6 +67,7 @@ import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Executors; import com.android.launcher3.util.Executors;
import com.android.launcher3.util.Thunk; import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.IconLabelDotView; import com.android.launcher3.views.IconLabelDotView;
import com.android.launcher3.widget.PendingAddShortcutInfo; import com.android.launcher3.widget.PendingAddShortcutInfo;
@ -79,7 +80,7 @@ import java.util.function.Predicate;
*/ */
public class FolderIcon extends FrameLayout implements FolderListener, IconLabelDotView { public class FolderIcon extends FrameLayout implements FolderListener, IconLabelDotView {
@Thunk Launcher mLauncher; @Thunk ActivityContext mActivity;
@Thunk Folder mFolder; @Thunk Folder mFolder;
private FolderInfo mInfo; private FolderInfo mInfo;
@ -153,7 +154,21 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
mDotParams = new DotRenderer.DrawParams(); mDotParams = new DotRenderer.DrawParams();
} }
public static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group, public static FolderIcon inflateFolderAndIcon(int resId, Launcher launcher, ViewGroup group,
FolderInfo folderInfo) {
Folder folder = Folder.fromXml(launcher);
folder.setDragController(launcher.getDragController());
FolderIcon icon = inflateIcon(resId, launcher, group, folderInfo);
folder.setFolderIcon(icon);
folder.bind(folderInfo);
icon.setFolder(folder);
icon.setOnFocusChangeListener(launcher.getFocusHandler());
return icon;
}
public static FolderIcon inflateIcon(int resId, ActivityContext activity, ViewGroup group,
FolderInfo folderInfo) { FolderInfo folderInfo) {
@SuppressWarnings("all") // suppress dead code warning @SuppressWarnings("all") // suppress dead code warning
final boolean error = INITIAL_ITEM_ANIMATION_DURATION >= DROP_IN_ANIMATION_DURATION; final boolean error = INITIAL_ITEM_ANIMATION_DURATION >= DROP_IN_ANIMATION_DURATION;
@ -163,7 +178,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
"is dependent on this"); "is dependent on this");
} }
DeviceProfile grid = launcher.getWallpaperDeviceProfile(); DeviceProfile grid = activity.getWallpaperDeviceProfile();
FolderIcon icon = (FolderIcon) LayoutInflater.from(group.getContext()) FolderIcon icon = (FolderIcon) LayoutInflater.from(group.getContext())
.inflate(resId, group, false); .inflate(resId, group, false);
@ -177,27 +192,27 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
icon.setTag(folderInfo); icon.setTag(folderInfo);
icon.setOnClickListener(ItemClickHandler.INSTANCE); icon.setOnClickListener(ItemClickHandler.INSTANCE);
icon.mInfo = folderInfo; icon.mInfo = folderInfo;
icon.mLauncher = launcher; icon.mActivity = activity;
icon.mDotRenderer = grid.mDotRendererWorkSpace; icon.mDotRenderer = grid.mDotRendererWorkSpace;
icon.setContentDescription(launcher.getString(R.string.folder_name_format, folderInfo.title));
icon.setContentDescription(
group.getContext().getString(R.string.folder_name_format, folderInfo.title));
// Keep the notification dot up to date with the sum of all the content's dots. // Keep the notification dot up to date with the sum of all the content's dots.
FolderDotInfo folderDotInfo = new FolderDotInfo(); FolderDotInfo folderDotInfo = new FolderDotInfo();
for (WorkspaceItemInfo si : folderInfo.contents) { for (WorkspaceItemInfo si : folderInfo.contents) {
folderDotInfo.addDotInfo(launcher.getDotInfoForItem(si)); folderDotInfo.addDotInfo(activity.getDotInfoForItem(si));
} }
icon.setDotInfo(folderDotInfo); icon.setDotInfo(folderDotInfo);
Folder folder = Folder.fromXml(launcher); icon.setAccessibilityDelegate(activity.getAccessibilityDelegate());
folder.setDragController(launcher.getDragController());
folder.setFolderIcon(icon); icon.mPreviewVerifier = new FolderGridOrganizer(activity.getDeviceProfile().inv);
folder.bind(folderInfo); icon.mPreviewVerifier.setFolderInfo(folderInfo);
icon.setFolder(folder); icon.updatePreviewItems(false);
icon.setAccessibilityDelegate(launcher.getAccessibilityDelegate());
folderInfo.addListener(icon); folderInfo.addListener(icon);
icon.setOnFocusChangeListener(launcher.mFocusHandler);
return icon; return icon;
} }
@ -225,9 +240,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
private void setFolder(Folder folder) { private void setFolder(Folder folder) {
mFolder = folder; mFolder = folder;
mPreviewVerifier = new FolderGridOrganizer(mLauncher.getDeviceProfile().inv);
mPreviewVerifier.setFolderInfo(mFolder.getInfo());
updatePreviewItems(false);
} }
private boolean willAcceptItem(ItemInfo item) { private boolean willAcceptItem(ItemInfo item) {
@ -309,14 +321,15 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
// Typically, the animateView corresponds to the DragView; however, if this is being done // Typically, the animateView corresponds to the DragView; however, if this is being done
// after a configuration activity (ie. for a Shortcut being dragged from AllApps) we // after a configuration activity (ie. for a Shortcut being dragged from AllApps) we
// will not have a view to animate // will not have a view to animate
if (animateView != null) { if (animateView != null && mActivity instanceof Launcher) {
DragLayer dragLayer = mLauncher.getDragLayer(); final Launcher launcher = (Launcher) mActivity;
DragLayer dragLayer = launcher.getDragLayer();
Rect from = new Rect(); Rect from = new Rect();
dragLayer.getViewRectRelativeToSelf(animateView, from); dragLayer.getViewRectRelativeToSelf(animateView, from);
Rect to = finalRect; Rect to = finalRect;
if (to == null) { if (to == null) {
to = new Rect(); to = new Rect();
Workspace workspace = mLauncher.getWorkspace(); Workspace workspace = launcher.getWorkspace();
// Set cellLayout and this to it's final state to compute final animation locations // Set cellLayout and this to it's final state to compute final animation locations
workspace.setFinalTransitionTransform(); workspace.setFinalTransitionTransform();
float scaleX = getScaleX(); float scaleX = getScaleX();
@ -382,7 +395,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
String[] suggestedNameOut = new String[FolderNameProvider.SUGGEST_MAX]; String[] suggestedNameOut = new String[FolderNameProvider.SUGGEST_MAX];
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
Executors.UI_HELPER_EXECUTOR.post(() -> { Executors.UI_HELPER_EXECUTOR.post(() -> {
mLauncher.getFolderNameProvider().getSuggestedFolderName( launcher.getFolderNameProvider().getSuggestedFolderName(
getContext(), mInfo.contents, suggestedNameOut); getContext(), mInfo.contents, suggestedNameOut);
showFinalView(finalIndex, item, suggestedNameOut); showFinalView(finalIndex, item, suggestedNameOut);
}); });
@ -547,7 +560,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
if (!mForceHideDot && ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0)) { if (!mForceHideDot && ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0)) {
Rect iconBounds = mDotParams.iconBounds; Rect iconBounds = mDotParams.iconBounds;
BubbleTextView.getIconBounds(this, iconBounds, BubbleTextView.getIconBounds(this, iconBounds,
mLauncher.getWallpaperDeviceProfile().iconSizePx); mActivity.getWallpaperDeviceProfile().iconSizePx);
float iconScale = (float) mBackground.previewSize / iconBounds.width(); float iconScale = (float) mBackground.previewSize / iconBounds.width();
Utilities.scaleRectAboutCenter(iconBounds, iconScale); Utilities.scaleRectAboutCenter(iconBounds, iconScale);
@ -605,7 +618,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
@Override @Override
public void onAdd(WorkspaceItemInfo item, int rank) { public void onAdd(WorkspaceItemInfo item, int rank) {
boolean wasDotted = mDotInfo.hasDot(); boolean wasDotted = mDotInfo.hasDot();
mDotInfo.addDotInfo(mLauncher.getDotInfoForItem(item)); mDotInfo.addDotInfo(mActivity.getDotInfoForItem(item));
boolean isDotted = mDotInfo.hasDot(); boolean isDotted = mDotInfo.hasDot();
updateDotScale(wasDotted, isDotted); updateDotScale(wasDotted, isDotted);
invalidate(); invalidate();
@ -615,7 +628,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
@Override @Override
public void onRemove(WorkspaceItemInfo item) { public void onRemove(WorkspaceItemInfo item) {
boolean wasDotted = mDotInfo.hasDot(); boolean wasDotted = mDotInfo.hasDot();
mDotInfo.subtractDotInfo(mLauncher.getDotInfoForItem(item)); mDotInfo.subtractDotInfo(mActivity.getDotInfoForItem(item));
boolean isDotted = mDotInfo.hasDot(); boolean isDotted = mDotInfo.hasDot();
updateDotScale(wasDotted, isDotted); updateDotScale(wasDotted, isDotted);
invalidate(); invalidate();

View File

@ -37,10 +37,10 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.graphics.PreloadIconDrawable; import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -94,7 +94,8 @@ public class PreviewItemManager {
public PreviewItemManager(FolderIcon icon) { public PreviewItemManager(FolderIcon icon) {
mContext = icon.getContext(); mContext = icon.getContext();
mIcon = icon; mIcon = icon;
mIconSize = Launcher.getLauncher(mContext).getDeviceProfile().folderChildIconSizePx; mIconSize = ActivityContext.lookupContext(
mContext).getDeviceProfile().folderChildIconSizePx;
} }
/** /**
@ -132,7 +133,7 @@ public class PreviewItemManager {
mTotalWidth = totalSize; mTotalWidth = totalSize;
mPrevTopPadding = mIcon.getPaddingTop(); mPrevTopPadding = mIcon.getPaddingTop();
mIcon.mBackground.setup(mIcon.mLauncher, mIcon.mLauncher, mIcon, mTotalWidth, mIcon.mBackground.setup(mIcon.getContext(), mIcon.mActivity, mIcon, mTotalWidth,
mIcon.getPaddingTop()); mIcon.getPaddingTop());
mIcon.mPreviewLayoutRule.init(mIcon.mBackground.previewSize, mIntrinsicIconSize, mIcon.mPreviewLayoutRule.init(mIcon.mBackground.previewSize, mIntrinsicIconSize,
Utilities.isRtl(mIcon.getResources())); Utilities.isRtl(mIcon.getResources()));
@ -152,7 +153,7 @@ public class PreviewItemManager {
} }
private PreviewItemDrawingParams getFinalIconParams(PreviewItemDrawingParams params) { private PreviewItemDrawingParams getFinalIconParams(PreviewItemDrawingParams params) {
float iconSize = mIcon.mLauncher.getDeviceProfile().iconSizePx; float iconSize = mIcon.mActivity.getDeviceProfile().iconSizePx;
final float scale = iconSize / mReferenceDrawable.getIntrinsicWidth(); final float scale = iconSize / mReferenceDrawable.getIntrinsicWidth();
final float trans = (mIcon.mBackground.previewSize - iconSize) / 2; final float trans = (mIcon.mBackground.previewSize - iconSize) / 2;

View File

@ -49,6 +49,7 @@ import android.widget.TextClock;
import com.android.launcher3.BubbleTextView; import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout; import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.FolderInfo;
import com.android.launcher3.Hotseat; import com.android.launcher3.Hotseat;
import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.InvariantDeviceProfile;
@ -63,6 +64,7 @@ import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.WorkspaceLayoutManager; import com.android.launcher3.WorkspaceLayoutManager;
import com.android.launcher3.allapps.SearchUiManager; import com.android.launcher3.allapps.SearchUiManager;
import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.BitmapRenderer; import com.android.launcher3.icons.BitmapRenderer;
@ -239,6 +241,12 @@ public class LauncherPreviewRenderer implements Callable<Bitmap> {
addInScreenFromBind(icon, info); addInScreenFromBind(icon, info);
} }
private void inflateAndAddFolder(FolderInfo info) {
FolderIcon folderIcon = FolderIcon.inflateIcon(R.layout.folder_icon, this, mWorkspace,
info);
addInScreenFromBind(folderIcon, info);
}
private void dispatchVisibilityAggregated(View view, boolean isVisible) { private void dispatchVisibilityAggregated(View view, boolean isVisible) {
// Similar to View.dispatchVisibilityAggregated implementation. // Similar to View.dispatchVisibilityAggregated implementation.
final boolean thisVisible = view.getVisibility() == VISIBLE; final boolean thisVisible = view.getVisibility() == VISIBLE;
@ -288,7 +296,7 @@ public class LauncherPreviewRenderer implements Callable<Bitmap> {
inflateAndAddIcon((WorkspaceItemInfo) itemInfo); inflateAndAddIcon((WorkspaceItemInfo) itemInfo);
break; break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
// TODO: for folder implementation here. inflateAndAddFolder((FolderInfo) itemInfo);
break; break;
default: default:
break; break;