Lazily binding folder pages and icons
Folders are bound before they are opened and unbound on close. This allows us to recycle the views in folders Bug: 139051851 Change-Id: Ic1ed3265c0f583af54d73dab6f2751bc95266ea9
This commit is contained in:
parent
72fddba837
commit
ac6f69f78d
|
@ -20,4 +20,5 @@
|
||||||
style="@style/BaseIcon"
|
style="@style/BaseIcon"
|
||||||
android:textColor="?attr/folderTextColor"
|
android:textColor="?attr/folderTextColor"
|
||||||
android:includeFontPadding="false"
|
android:includeFontPadding="false"
|
||||||
|
android:hapticFeedbackEnabled="false"
|
||||||
launcher:iconDisplay="folder" />
|
launcher:iconDisplay="folder" />
|
||||||
|
|
|
@ -93,13 +93,6 @@ public class FolderInfo extends ItemInfo {
|
||||||
itemsChanged(animate);
|
itemsChanged(animate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTitle(CharSequence title) {
|
|
||||||
this.title = title;
|
|
||||||
for (int i = 0; i < mListeners.size(); i++) {
|
|
||||||
mListeners.get(i).onTitleChanged(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAddToDatabase(ContentWriter writer) {
|
public void onAddToDatabase(ContentWriter writer) {
|
||||||
super.onAddToDatabase(writer);
|
super.onAddToDatabase(writer);
|
||||||
|
@ -121,18 +114,10 @@ public class FolderInfo extends ItemInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepareAutoUpdate() {
|
|
||||||
for (int i = 0; i < mListeners.size(); i++) {
|
|
||||||
mListeners.get(i).prepareAutoUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface FolderListener {
|
public interface FolderListener {
|
||||||
public void onAdd(WorkspaceItemInfo item, int rank);
|
public void onAdd(WorkspaceItemInfo item, int rank);
|
||||||
public void onRemove(WorkspaceItemInfo item);
|
public void onRemove(WorkspaceItemInfo item);
|
||||||
public void onTitleChanged(CharSequence title);
|
|
||||||
public void onItemsChanged(boolean animate);
|
public void onItemsChanged(boolean animate);
|
||||||
public void prepareAutoUpdate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasOption(int optionFlag) {
|
public boolean hasOption(int optionFlag) {
|
||||||
|
|
|
@ -2340,6 +2340,11 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||||
// override the previous page so we don't log the page switch.
|
// override the previous page so we don't log the page switch.
|
||||||
mWorkspace.setCurrentPage(pageBoundFirst, pageBoundFirst /* overridePrevPage */);
|
mWorkspace.setCurrentPage(pageBoundFirst, pageBoundFirst /* overridePrevPage */);
|
||||||
|
|
||||||
|
// Cache one page worth of icons
|
||||||
|
getViewCache().setCacheSize(R.layout.folder_application,
|
||||||
|
mDeviceProfile.inv.numFolderColumns * mDeviceProfile.inv.numFolderRows);
|
||||||
|
getViewCache().setCacheSize(R.layout.folder_page, 2);
|
||||||
|
|
||||||
TraceHelper.endSection("finishBindingItems");
|
TraceHelper.endSection("finishBindingItems");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,6 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||||
import com.android.launcher3.util.Executors;
|
import com.android.launcher3.util.Executors;
|
||||||
import com.android.launcher3.util.IntArray;
|
import com.android.launcher3.util.IntArray;
|
||||||
import com.android.launcher3.util.IntSet;
|
|
||||||
import com.android.launcher3.util.IntSparseArrayMap;
|
import com.android.launcher3.util.IntSparseArrayMap;
|
||||||
import com.android.launcher3.util.ItemInfoMatcher;
|
import com.android.launcher3.util.ItemInfoMatcher;
|
||||||
import com.android.launcher3.util.PackageUserKey;
|
import com.android.launcher3.util.PackageUserKey;
|
||||||
|
@ -134,9 +133,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
|
|
||||||
private static final int DEFAULT_PAGE = 0;
|
private static final int DEFAULT_PAGE = 0;
|
||||||
|
|
||||||
public static final boolean MAP_NO_RECURSE = false;
|
|
||||||
public static final boolean MAP_RECURSE = true;
|
|
||||||
|
|
||||||
private LayoutTransition mLayoutTransition;
|
private LayoutTransition mLayoutTransition;
|
||||||
@Thunk final WallpaperManager mWallpaperManager;
|
@Thunk final WallpaperManager mWallpaperManager;
|
||||||
|
|
||||||
|
@ -2809,7 +2805,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
* Removes all folder listeners
|
* Removes all folder listeners
|
||||||
*/
|
*/
|
||||||
public void removeFolderListeners() {
|
public void removeFolderListeners() {
|
||||||
mapOverItems(false, new ItemOperator() {
|
mapOverItems(new ItemOperator() {
|
||||||
@Override
|
@Override
|
||||||
public boolean evaluate(ItemInfo info, View view) {
|
public boolean evaluate(ItemInfo info, View view) {
|
||||||
if (view instanceof FolderIcon) {
|
if (view instanceof FolderIcon) {
|
||||||
|
@ -2961,7 +2957,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
|
|
||||||
public View getFirstMatch(final ItemOperator operator) {
|
public View getFirstMatch(final ItemOperator operator) {
|
||||||
final View[] value = new View[1];
|
final View[] value = new View[1];
|
||||||
mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
|
mapOverItems(new ItemOperator() {
|
||||||
@Override
|
@Override
|
||||||
public boolean evaluate(ItemInfo info, View v) {
|
public boolean evaluate(ItemInfo info, View v) {
|
||||||
if (operator.evaluate(info, v)) {
|
if (operator.evaluate(info, v)) {
|
||||||
|
@ -2984,7 +2980,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
final View[] matches = new View[operators.length];
|
final View[] matches = new View[operators.length];
|
||||||
// For efficiency, the outer loop should be CellLayout.
|
// For efficiency, the outer loop should be CellLayout.
|
||||||
for (CellLayout cellLayout : cellLayouts) {
|
for (CellLayout cellLayout : cellLayouts) {
|
||||||
mapOverCellLayout(MAP_NO_RECURSE, cellLayout, (info, v) -> {
|
mapOverCellLayout(cellLayout, (info, v) -> {
|
||||||
for (int i = 0; i < operators.length; ++i) {
|
for (int i = 0; i < operators.length; ++i) {
|
||||||
if (matches[i] == null && operators[i].evaluate(info, v)) {
|
if (matches[i] == null && operators[i].evaluate(info, v)) {
|
||||||
matches[i] = v;
|
matches[i] = v;
|
||||||
|
@ -3009,7 +3005,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearDropTargets() {
|
void clearDropTargets() {
|
||||||
mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
|
mapOverItems(new ItemOperator() {
|
||||||
@Override
|
@Override
|
||||||
public boolean evaluate(ItemInfo info, View v) {
|
public boolean evaluate(ItemInfo info, View v) {
|
||||||
if (v instanceof DropTarget) {
|
if (v instanceof DropTarget) {
|
||||||
|
@ -3054,10 +3050,12 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
} else if (itemToRemove.container >= 0) {
|
} else if (itemToRemove.container >= 0) {
|
||||||
// The item may belong to a folder.
|
// The item may belong to a folder.
|
||||||
View parent = idToViewMap.get(itemToRemove.container);
|
View parent = idToViewMap.get(itemToRemove.container);
|
||||||
if (parent != null) {
|
if (parent instanceof FolderIcon) {
|
||||||
FolderInfo folderInfo = (FolderInfo) parent.getTag();
|
FolderInfo folderInfo = (FolderInfo) parent.getTag();
|
||||||
folderInfo.prepareAutoUpdate();
|
|
||||||
folderInfo.remove((WorkspaceItemInfo) itemToRemove, false);
|
folderInfo.remove((WorkspaceItemInfo) itemToRemove, false);
|
||||||
|
if (((FolderIcon) parent).getFolder().isOpen()) {
|
||||||
|
((FolderIcon) parent).getFolder().close(false /* animate */);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3081,18 +3079,17 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
/**
|
/**
|
||||||
* Map the operator over the shortcuts and widgets, return the first-non-null value.
|
* Map the operator over the shortcuts and widgets, return the first-non-null value.
|
||||||
*
|
*
|
||||||
* @param recurse true: iterate over folder children. false: op get the folders themselves.
|
|
||||||
* @param op the operator to map over the shortcuts
|
* @param op the operator to map over the shortcuts
|
||||||
*/
|
*/
|
||||||
public void mapOverItems(boolean recurse, ItemOperator op) {
|
public void mapOverItems(ItemOperator op) {
|
||||||
for (CellLayout layout : getWorkspaceAndHotseatCellLayouts()) {
|
for (CellLayout layout : getWorkspaceAndHotseatCellLayouts()) {
|
||||||
if (mapOverCellLayout(recurse, layout, op)) {
|
if (mapOverCellLayout(layout, op)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mapOverCellLayout(boolean recurse, CellLayout layout, ItemOperator op) {
|
private boolean mapOverCellLayout(CellLayout layout, ItemOperator op) {
|
||||||
// TODO(b/128460496) Potential race condition where layout is not yet loaded
|
// TODO(b/128460496) Potential race condition where layout is not yet loaded
|
||||||
if (layout == null) {
|
if (layout == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -3102,103 +3099,68 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
final int itemCount = container.getChildCount();
|
final int itemCount = container.getChildCount();
|
||||||
for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
|
for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
|
||||||
View item = container.getChildAt(itemIdx);
|
View item = container.getChildAt(itemIdx);
|
||||||
ItemInfo info = (ItemInfo) item.getTag();
|
if (op.evaluate((ItemInfo) item.getTag(), item)) {
|
||||||
if (recurse && info instanceof FolderInfo && item instanceof FolderIcon) {
|
|
||||||
FolderIcon folder = (FolderIcon) item;
|
|
||||||
ArrayList<View> folderChildren = folder.getFolder().getIconsInReadingOrder();
|
|
||||||
// map over all the children in the folder
|
|
||||||
final int childCount = folderChildren.size();
|
|
||||||
for (int childIdx = 0; childIdx < childCount; childIdx++) {
|
|
||||||
View child = folderChildren.get(childIdx);
|
|
||||||
info = (ItemInfo) child.getTag();
|
|
||||||
if (op.evaluate(info, child)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (op.evaluate(info, item)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateShortcuts(ArrayList<WorkspaceItemInfo> shortcuts) {
|
void updateShortcuts(ArrayList<WorkspaceItemInfo> shortcuts) {
|
||||||
int total = shortcuts.size();
|
final HashSet<WorkspaceItemInfo> updates = new HashSet<>(shortcuts);
|
||||||
final HashSet<WorkspaceItemInfo> updates = new HashSet<>(total);
|
ItemOperator op = (info, v) -> {
|
||||||
final IntSet folderIds = new IntSet();
|
if (v instanceof BubbleTextView && updates.contains(info)) {
|
||||||
|
|
||||||
for (int i = 0; i < total; i++) {
|
|
||||||
WorkspaceItemInfo s = shortcuts.get(i);
|
|
||||||
updates.add(s);
|
|
||||||
folderIds.add(s.container);
|
|
||||||
}
|
|
||||||
|
|
||||||
mapOverItems(MAP_RECURSE, new ItemOperator() {
|
|
||||||
@Override
|
|
||||||
public boolean evaluate(ItemInfo info, View v) {
|
|
||||||
if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView &&
|
|
||||||
updates.contains(info)) {
|
|
||||||
WorkspaceItemInfo si = (WorkspaceItemInfo) info;
|
WorkspaceItemInfo si = (WorkspaceItemInfo) info;
|
||||||
BubbleTextView shortcut = (BubbleTextView) v;
|
BubbleTextView shortcut = (BubbleTextView) v;
|
||||||
Drawable oldIcon = shortcut.getIcon();
|
Drawable oldIcon = shortcut.getIcon();
|
||||||
boolean oldPromiseState = (oldIcon instanceof PreloadIconDrawable)
|
boolean oldPromiseState = (oldIcon instanceof PreloadIconDrawable)
|
||||||
&& ((PreloadIconDrawable) oldIcon).hasNotCompleted();
|
&& ((PreloadIconDrawable) oldIcon).hasNotCompleted();
|
||||||
shortcut.applyFromWorkspaceItem(si, si.isPromise() != oldPromiseState);
|
shortcut.applyFromWorkspaceItem(si, si.isPromise() != oldPromiseState);
|
||||||
|
} else if (info instanceof FolderInfo && v instanceof FolderIcon) {
|
||||||
|
((FolderIcon) v).updatePreviewItems(updates::contains);
|
||||||
}
|
}
|
||||||
// process all the shortcuts
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update folder icons
|
// Iterate all items
|
||||||
mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
|
|
||||||
@Override
|
|
||||||
public boolean evaluate(ItemInfo info, View v) {
|
|
||||||
if (info instanceof FolderInfo && folderIds.contains(info.id)) {
|
|
||||||
((FolderInfo) info).itemsChanged(false);
|
|
||||||
}
|
|
||||||
// process all the shortcuts
|
|
||||||
return false;
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
mapOverItems(op);
|
||||||
|
Folder openFolder = Folder.getOpen(mLauncher);
|
||||||
|
if (openFolder != null) {
|
||||||
|
openFolder.iterateOverItems(op);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
|
public void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
|
||||||
final PackageUserKey packageUserKey = new PackageUserKey(null, null);
|
final PackageUserKey packageUserKey = new PackageUserKey(null, null);
|
||||||
final IntSet folderIds = new IntSet();
|
Predicate<ItemInfo> matcher = info -> !packageUserKey.updateFromItemInfo(info)
|
||||||
mapOverItems(MAP_RECURSE, new ItemOperator() {
|
|| updatedDots.test(packageUserKey);
|
||||||
@Override
|
|
||||||
public boolean evaluate(ItemInfo info, View v) {
|
|
||||||
if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView) {
|
|
||||||
if (!packageUserKey.updateFromItemInfo(info)
|
|
||||||
|| updatedDots.test(packageUserKey)) {
|
|
||||||
((BubbleTextView) v).applyDotState(info, true /* animate */);
|
|
||||||
folderIds.add(info.container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// process all the shortcuts
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update folder icons
|
ItemOperator op = (info, v) -> {
|
||||||
mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
|
if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView) {
|
||||||
@Override
|
if (matcher.test(info)) {
|
||||||
public boolean evaluate(ItemInfo info, View v) {
|
((BubbleTextView) v).applyDotState(info, true /* animate */);
|
||||||
if (info instanceof FolderInfo && folderIds.contains(info.id)
|
}
|
||||||
&& v instanceof FolderIcon) {
|
} else if (info instanceof FolderInfo && v instanceof FolderIcon) {
|
||||||
|
FolderInfo fi = (FolderInfo) info;
|
||||||
|
if (fi.contents.stream().anyMatch(matcher)) {
|
||||||
FolderDotInfo folderDotInfo = new FolderDotInfo();
|
FolderDotInfo folderDotInfo = new FolderDotInfo();
|
||||||
for (WorkspaceItemInfo si : ((FolderInfo) info).contents) {
|
for (WorkspaceItemInfo si : fi.contents) {
|
||||||
folderDotInfo.addDotInfo(mLauncher.getDotInfoForItem(si));
|
folderDotInfo.addDotInfo(mLauncher.getDotInfoForItem(si));
|
||||||
}
|
}
|
||||||
((FolderIcon) v).setDotInfo(folderDotInfo);
|
((FolderIcon) v).setDotInfo(folderDotInfo);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// process all the shortcuts
|
// process all the shortcuts
|
||||||
return false;
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
mapOverItems(op);
|
||||||
|
Folder folder = Folder.getOpen(mLauncher);
|
||||||
|
if (folder != null) {
|
||||||
|
folder.iterateOverItems(op);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAbandonedPromise(String packageName, UserHandle user) {
|
public void removeAbandonedPromise(String packageName, UserHandle user) {
|
||||||
|
@ -3210,9 +3172,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRestoreItems(final HashSet<ItemInfo> updates) {
|
public void updateRestoreItems(final HashSet<ItemInfo> updates) {
|
||||||
mapOverItems(MAP_RECURSE, new ItemOperator() {
|
ItemOperator op = (info, v) -> {
|
||||||
@Override
|
|
||||||
public boolean evaluate(ItemInfo info, View v) {
|
|
||||||
if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView
|
if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView
|
||||||
&& updates.contains(info)) {
|
&& updates.contains(info)) {
|
||||||
((BubbleTextView) v).applyPromiseState(false /* promiseStateChanged */);
|
((BubbleTextView) v).applyPromiseState(false /* promiseStateChanged */);
|
||||||
|
@ -3220,11 +3180,17 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
&& info instanceof LauncherAppWidgetInfo
|
&& info instanceof LauncherAppWidgetInfo
|
||||||
&& updates.contains(info)) {
|
&& updates.contains(info)) {
|
||||||
((PendingAppWidgetHostView) v).applyState();
|
((PendingAppWidgetHostView) v).applyState();
|
||||||
|
} else if (v instanceof FolderIcon && info instanceof FolderInfo) {
|
||||||
|
((FolderIcon) v).updatePreviewItems(updates::contains);
|
||||||
}
|
}
|
||||||
// process all the shortcuts
|
// process all the shortcuts
|
||||||
return false;
|
return false;
|
||||||
|
};
|
||||||
|
mapOverItems(op);
|
||||||
|
Folder folder = Folder.getOpen(mLauncher);
|
||||||
|
if (folder != null) {
|
||||||
|
folder.iterateOverItems(op);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void widgetsRestored(final ArrayList<LauncherAppWidgetInfo> changedInfo) {
|
public void widgetsRestored(final ArrayList<LauncherAppWidgetInfo> changedInfo) {
|
||||||
|
@ -3248,7 +3214,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
} else {
|
} else {
|
||||||
// widgetRefresh will automatically run when the packages are updated.
|
// widgetRefresh will automatically run when the packages are updated.
|
||||||
// For now just update the progress bars
|
// For now just update the progress bars
|
||||||
mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
|
mapOverItems(new ItemOperator() {
|
||||||
@Override
|
@Override
|
||||||
public boolean evaluate(ItemInfo info, View view) {
|
public boolean evaluate(ItemInfo info, View view) {
|
||||||
if (view instanceof PendingAppWidgetHostView
|
if (view instanceof PendingAppWidgetHostView
|
||||||
|
@ -3372,7 +3338,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
mRefreshPending = false;
|
mRefreshPending = false;
|
||||||
|
|
||||||
ArrayList<PendingAppWidgetHostView> views = new ArrayList<>(mInfos.size());
|
ArrayList<PendingAppWidgetHostView> views = new ArrayList<>(mInfos.size());
|
||||||
mapOverItems(MAP_NO_RECURSE, (info, view) -> {
|
mapOverItems((info, view) -> {
|
||||||
if (view instanceof PendingAppWidgetHostView && mInfos.contains(info)) {
|
if (view instanceof PendingAppWidgetHostView && mInfos.contains(info)) {
|
||||||
views.add((PendingAppWidgetHostView) view);
|
views.add((PendingAppWidgetHostView) view);
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,8 +170,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
private boolean mDeleteFolderOnDropCompleted = false;
|
private boolean mDeleteFolderOnDropCompleted = false;
|
||||||
private boolean mSuppressFolderDeletion = false;
|
private boolean mSuppressFolderDeletion = false;
|
||||||
private boolean mItemAddedBackToSelfViaIcon = false;
|
private boolean mItemAddedBackToSelfViaIcon = false;
|
||||||
@Thunk float mFolderIconPivotX;
|
|
||||||
@Thunk float mFolderIconPivotY;
|
|
||||||
private boolean mIsEditingName = false;
|
private boolean mIsEditingName = false;
|
||||||
|
|
||||||
@ViewDebug.ExportedProperty(category = "launcher")
|
@ViewDebug.ExportedProperty(category = "launcher")
|
||||||
|
@ -310,7 +308,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
// Convert to a string here to ensure that no other state associated with the text field
|
// Convert to a string here to ensure that no other state associated with the text field
|
||||||
// gets saved.
|
// gets saved.
|
||||||
String newTitle = mFolderName.getText().toString();
|
String newTitle = mFolderName.getText().toString();
|
||||||
mInfo.setTitle(newTitle);
|
mInfo.title = newTitle;
|
||||||
|
mFolderIcon.onTitleChanged(newTitle);
|
||||||
mLauncher.getModelWriter().updateItemInDatabase(mInfo);
|
mLauncher.getModelWriter().updateItemInDatabase(mInfo);
|
||||||
|
|
||||||
if (TextUtils.isEmpty(mInfo.title)) {
|
if (TextUtils.isEmpty(mInfo.title)) {
|
||||||
|
@ -385,7 +384,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
ArrayList<WorkspaceItemInfo> children = info.contents;
|
ArrayList<WorkspaceItemInfo> children = info.contents;
|
||||||
Collections.sort(children, ITEM_POS_COMPARATOR);
|
Collections.sort(children, ITEM_POS_COMPARATOR);
|
||||||
updateItemLocationsInDatabaseBatch();
|
updateItemLocationsInDatabaseBatch();
|
||||||
mContent.bindItems(children);
|
|
||||||
|
|
||||||
DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
|
DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
|
||||||
if (lp == null) {
|
if (lp == null) {
|
||||||
|
@ -393,13 +391,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
lp.customPosition = true;
|
lp.customPosition = true;
|
||||||
setLayoutParams(lp);
|
setLayoutParams(lp);
|
||||||
}
|
}
|
||||||
centerAboutIcon();
|
|
||||||
|
|
||||||
mItemsInvalidated = true;
|
mItemsInvalidated = true;
|
||||||
updateTextViewFocus();
|
|
||||||
mInfo.addListener(this);
|
mInfo.addListener(this);
|
||||||
|
|
||||||
if (TextUtils.isEmpty(mInfo.title)) {
|
if (!TextUtils.isEmpty(mInfo.title)) {
|
||||||
mFolderName.setText(mInfo.title);
|
mFolderName.setText(mInfo.title);
|
||||||
mFolderName.setHint(null);
|
mFolderName.setHint(null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -408,12 +403,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case any children didn't come across during loading, clean up the folder accordingly
|
// In case any children didn't come across during loading, clean up the folder accordingly
|
||||||
mFolderIcon.post(new Runnable() {
|
mFolderIcon.post(() -> {
|
||||||
public void run() {
|
|
||||||
if (getItemCount() <= 1) {
|
if (getItemCount() <= 1) {
|
||||||
replaceFolderWithFinalItem();
|
replaceFolderWithFinalItem();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,18 +465,50 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
return folderCount >= MIN_FOLDERS_FOR_HARDWARE_OPTIMIZATION;
|
return folderCount >= MIN_FOLDERS_FOR_HARDWARE_OPTIMIZATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the folder as part of a drag operation
|
||||||
|
*/
|
||||||
|
public void beginExternalDrag() {
|
||||||
|
mIsExternalDrag = true;
|
||||||
|
mDragInProgress = true;
|
||||||
|
|
||||||
|
// Since this folder opened by another controller, it might not get onDrop or
|
||||||
|
// onDropComplete. Perform cleanup once drag-n-drop ends.
|
||||||
|
mDragController.addDragListener(this);
|
||||||
|
|
||||||
|
ArrayList<WorkspaceItemInfo> items = new ArrayList<>(mInfo.contents);
|
||||||
|
mEmptyCellRank = items.size();
|
||||||
|
items.add(null); // Add an empty spot at the end
|
||||||
|
|
||||||
|
animateOpen(items, mEmptyCellRank / mContent.itemsPerPage());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the user folder described by the specified tag. The opening of the folder
|
* Opens the user folder described by the specified tag. The opening of the folder
|
||||||
* is animated relative to the specified View. If the View is null, no animation
|
* is animated relative to the specified View. If the View is null, no animation
|
||||||
* is played.
|
* is played.
|
||||||
*/
|
*/
|
||||||
public void animateOpen() {
|
public void animateOpen() {
|
||||||
|
animateOpen(mInfo.contents, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the user folder described by the specified tag. The opening of the folder
|
||||||
|
* is animated relative to the specified View. If the View is null, no animation
|
||||||
|
* is played.
|
||||||
|
*/
|
||||||
|
private void animateOpen(List<WorkspaceItemInfo> items, int pageNo) {
|
||||||
Folder openFolder = getOpen(mLauncher);
|
Folder openFolder = getOpen(mLauncher);
|
||||||
if (openFolder != null && openFolder != this) {
|
if (openFolder != null && openFolder != this) {
|
||||||
// Close any open folder before opening a folder.
|
// Close any open folder before opening a folder.
|
||||||
openFolder.close(true);
|
openFolder.close(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mContent.bindItems(items);
|
||||||
|
centerAboutIcon();
|
||||||
|
mItemsInvalidated = true;
|
||||||
|
updateTextViewFocus();
|
||||||
|
|
||||||
mIsOpen = true;
|
mIsOpen = true;
|
||||||
|
|
||||||
DragLayer dragLayer = mLauncher.getDragLayer();
|
DragLayer dragLayer = mLauncher.getDragLayer();
|
||||||
|
@ -500,10 +525,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
}
|
}
|
||||||
|
|
||||||
mContent.completePendingPageChanges();
|
mContent.completePendingPageChanges();
|
||||||
if (!mDragInProgress) {
|
mContent.snapToPageImmediately(pageNo);
|
||||||
// Open on the first page.
|
|
||||||
mContent.snapToPageImmediately(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is set to true in close(), but isn't reset to false until onDropCompleted(). This
|
// This is set to true in close(), but isn't reset to false until onDropCompleted(). This
|
||||||
// leads to an inconsistent state if you drag out of the folder and drag back in without
|
// leads to an inconsistent state if you drag out of the folder and drag back in without
|
||||||
|
@ -574,16 +596,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
mContent.verifyVisibleHighResIcons(mContent.getNextPage());
|
mContent.verifyVisibleHighResIcons(mContent.getNextPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginExternalDrag() {
|
|
||||||
mEmptyCellRank = mContent.allocateRankForNewItem();
|
|
||||||
mIsExternalDrag = true;
|
|
||||||
mDragInProgress = true;
|
|
||||||
|
|
||||||
// Since this folder opened by another controller, it might not get onDrop or
|
|
||||||
// onDropComplete. Perform cleanup once drag-n-drop ends.
|
|
||||||
mDragController.addDragListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isOfType(int type) {
|
protected boolean isOfType(int type) {
|
||||||
return (type & TYPE_FOLDER) != 0;
|
return (type & TYPE_FOLDER) != 0;
|
||||||
|
@ -668,6 +680,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
} else if (mDragInProgress) {
|
} else if (mDragInProgress) {
|
||||||
mDeleteFolderOnDropCompleted = true;
|
mDeleteFolderOnDropCompleted = true;
|
||||||
}
|
}
|
||||||
|
} else if (!mDragInProgress) {
|
||||||
|
mContent.unbindItems();
|
||||||
}
|
}
|
||||||
mSuppressFolderDeletion = false;
|
mSuppressFolderDeletion = false;
|
||||||
clearDragInfo();
|
clearDragInfo();
|
||||||
|
@ -953,24 +967,12 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
setPivotX(folderPivotX);
|
setPivotX(folderPivotX);
|
||||||
setPivotY(folderPivotY);
|
setPivotY(folderPivotY);
|
||||||
|
|
||||||
mFolderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
|
|
||||||
(1.0f * folderPivotX / width));
|
|
||||||
mFolderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
|
|
||||||
(1.0f * folderPivotY / height));
|
|
||||||
|
|
||||||
lp.width = width;
|
lp.width = width;
|
||||||
lp.height = height;
|
lp.height = height;
|
||||||
lp.x = left;
|
lp.x = left;
|
||||||
lp.y = top;
|
lp.y = top;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getPivotXForIconAnimation() {
|
|
||||||
return mFolderIconPivotX;
|
|
||||||
}
|
|
||||||
public float getPivotYForIconAnimation() {
|
|
||||||
return mFolderIconPivotY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getContentAreaHeight() {
|
private int getContentAreaHeight() {
|
||||||
DeviceProfile grid = mLauncher.getDeviceProfile();
|
DeviceProfile grid = mLauncher.getDeviceProfile();
|
||||||
int maxContentAreaHeight = grid.availableHeightPx
|
int maxContentAreaHeight = grid.availableHeightPx
|
||||||
|
@ -1031,7 +1033,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return mContent.getItemCount();
|
return mInfo.contents.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Thunk void replaceFolderWithFinalItem() {
|
@Thunk void replaceFolderWithFinalItem() {
|
||||||
|
@ -1039,7 +1041,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
Runnable onCompleteRunnable = new Runnable() {
|
Runnable onCompleteRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
int itemCount = mInfo.contents.size();
|
int itemCount = getItemCount();
|
||||||
if (itemCount <= 1) {
|
if (itemCount <= 1) {
|
||||||
View newIcon = null;
|
View newIcon = null;
|
||||||
|
|
||||||
|
@ -1116,6 +1118,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
setOnKeyListener(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1242,9 +1246,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
item.cellY);
|
item.cellY);
|
||||||
updateItemLocationsInDatabaseBatch();
|
updateItemLocationsInDatabaseBatch();
|
||||||
|
|
||||||
ArrayList<View> items = new ArrayList<>(getIconsInReadingOrder());
|
if (mContent.areViewsBound()) {
|
||||||
items.add(rank, mContent.createAndAddViewForRank(item, rank));
|
mContent.createAndAddViewForRank(item, rank);
|
||||||
mContent.arrangeChildren(items);
|
}
|
||||||
mItemsInvalidated = true;
|
mItemsInvalidated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,12 +1279,11 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
updateTextViewFocus();
|
updateTextViewFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void prepareAutoUpdate() {
|
* Utility methods to iterate over items of the view
|
||||||
close(false);
|
*/
|
||||||
}
|
public void iterateOverItems(ItemOperator op) {
|
||||||
|
mContent.iterateOverItems(op);
|
||||||
public void onTitleChanged(CharSequence title) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1289,14 +1292,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||||
public ArrayList<View> getIconsInReadingOrder() {
|
public ArrayList<View> getIconsInReadingOrder() {
|
||||||
if (mItemsInvalidated) {
|
if (mItemsInvalidated) {
|
||||||
mItemsInReadingOrder.clear();
|
mItemsInReadingOrder.clear();
|
||||||
mContent.iterateOverItems(new ItemOperator() {
|
mContent.iterateOverItems((i, v) -> !mItemsInReadingOrder.add(v));
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean evaluate(ItemInfo info, View view) {
|
|
||||||
mItemsInReadingOrder.add(view);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mItemsInvalidated = false;
|
mItemsInvalidated = false;
|
||||||
}
|
}
|
||||||
return mItemsInReadingOrder;
|
return mItemsInReadingOrder;
|
||||||
|
|
|
@ -69,6 +69,7 @@ import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An icon that can appear on in the workspace representing an {@link Folder}.
|
* An icon that can appear on in the workspace representing an {@link Folder}.
|
||||||
|
@ -99,7 +100,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||||
ClippedFolderIconLayoutRule mPreviewLayoutRule;
|
ClippedFolderIconLayoutRule mPreviewLayoutRule;
|
||||||
private PreviewItemManager mPreviewItemManager;
|
private PreviewItemManager mPreviewItemManager;
|
||||||
private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
|
private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
|
||||||
private List<BubbleTextView> mCurrentPreviewItems = new ArrayList<>();
|
private List<WorkspaceItemInfo> mCurrentPreviewItems = new ArrayList<>();
|
||||||
|
|
||||||
boolean mAnimating = false;
|
boolean mAnimating = false;
|
||||||
|
|
||||||
|
@ -255,7 +256,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||||
OnAlarmListener mOnOpenListener = new OnAlarmListener() {
|
OnAlarmListener mOnOpenListener = new OnAlarmListener() {
|
||||||
public void onAlarm(Alarm alarm) {
|
public void onAlarm(Alarm alarm) {
|
||||||
mFolder.beginExternalDrag();
|
mFolder.beginExternalDrag();
|
||||||
mFolder.animateOpen();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -321,18 +321,17 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||||
int numItemsInPreview = Math.min(MAX_NUM_ITEMS_IN_PREVIEW, index + 1);
|
int numItemsInPreview = Math.min(MAX_NUM_ITEMS_IN_PREVIEW, index + 1);
|
||||||
boolean itemAdded = false;
|
boolean itemAdded = false;
|
||||||
if (itemReturnedOnFailedDrop || index >= MAX_NUM_ITEMS_IN_PREVIEW) {
|
if (itemReturnedOnFailedDrop || index >= MAX_NUM_ITEMS_IN_PREVIEW) {
|
||||||
List<BubbleTextView> oldPreviewItems = new ArrayList<>(mCurrentPreviewItems);
|
List<WorkspaceItemInfo> oldPreviewItems = new ArrayList<>(mCurrentPreviewItems);
|
||||||
mInfo.add(item, index, false);
|
mInfo.add(item, index, false);
|
||||||
mCurrentPreviewItems.clear();
|
mCurrentPreviewItems.clear();
|
||||||
mCurrentPreviewItems.addAll(getPreviewIconsOnPage(0));
|
mCurrentPreviewItems.addAll(getPreviewItemsOnPage(0));
|
||||||
|
|
||||||
if (!oldPreviewItems.equals(mCurrentPreviewItems)) {
|
if (!oldPreviewItems.equals(mCurrentPreviewItems)) {
|
||||||
for (int i = 0; i < mCurrentPreviewItems.size(); ++i) {
|
int newIndex = mCurrentPreviewItems.indexOf(item);
|
||||||
if (mCurrentPreviewItems.get(i).getTag().equals(item)) {
|
if (newIndex >= 0) {
|
||||||
// If the item dropped is going to be in the preview, we update the
|
// If the item dropped is going to be in the preview, we update the
|
||||||
// index here to reflect its position in the preview.
|
// index here to reflect its position in the preview.
|
||||||
index = i;
|
index = newIndex;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mPreviewItemManager.hidePreviewItem(index, true);
|
mPreviewItemManager.hidePreviewItem(index, true);
|
||||||
|
@ -531,11 +530,10 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of "preview items" on {@param page}.
|
* Returns the list of items which should be visible in the preview
|
||||||
*/
|
*/
|
||||||
public List<BubbleTextView> getPreviewIconsOnPage(int page) {
|
public List<WorkspaceItemInfo> getPreviewItemsOnPage(int page) {
|
||||||
return mPreviewVerifier.setFolderInfo(mFolder.mInfo)
|
return mPreviewVerifier.setFolderInfo(mInfo).previewItemsForPage(page, mInfo.contents);
|
||||||
.previewItemsForPage(page, mFolder.getIconsInReadingOrder());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -553,11 +551,14 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||||
private void updatePreviewItems(boolean animate) {
|
private void updatePreviewItems(boolean animate) {
|
||||||
mPreviewItemManager.updatePreviewItems(animate);
|
mPreviewItemManager.updatePreviewItems(animate);
|
||||||
mCurrentPreviewItems.clear();
|
mCurrentPreviewItems.clear();
|
||||||
mCurrentPreviewItems.addAll(getPreviewIconsOnPage(0));
|
mCurrentPreviewItems.addAll(getPreviewItemsOnPage(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void prepareAutoUpdate() {
|
* Updates the preview items which match the provided condition
|
||||||
|
*/
|
||||||
|
public void updatePreviewItems(Predicate<WorkspaceItemInfo> itemCheck) {
|
||||||
|
mPreviewItemManager.updatePreviewItems(itemCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -580,7 +581,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||||
requestLayout();
|
requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTitleChanged(CharSequence title) {
|
public void onTitleChanged(CharSequence title) {
|
||||||
mFolderName.setText(title);
|
mFolderName.setText(title);
|
||||||
setContentDescription(getContext().getString(R.string.folder_name_format, title));
|
setContentDescription(getContext().getString(R.string.folder_name_format, title));
|
||||||
|
|
|
@ -24,10 +24,10 @@ import android.util.ArrayMap;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewDebug;
|
import android.view.ViewDebug;
|
||||||
|
|
||||||
|
import com.android.launcher3.BaseActivity;
|
||||||
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;
|
||||||
|
@ -46,11 +46,14 @@ import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||||
import com.android.launcher3.pageindicators.PageIndicatorDots;
|
import com.android.launcher3.pageindicators.PageIndicatorDots;
|
||||||
import com.android.launcher3.touch.ItemClickHandler;
|
import com.android.launcher3.touch.ItemClickHandler;
|
||||||
import com.android.launcher3.util.Thunk;
|
import com.android.launcher3.util.Thunk;
|
||||||
|
import com.android.launcher3.util.ViewCache;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.ToIntFunction;
|
import java.util.function.ToIntFunction;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
|
|
||||||
|
@ -69,12 +72,12 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
|
|
||||||
public final boolean mIsRtl;
|
public final boolean mIsRtl;
|
||||||
|
|
||||||
private final LayoutInflater mInflater;
|
|
||||||
private final ViewGroupFocusHelper mFocusIndicatorHelper;
|
private final ViewGroupFocusHelper mFocusIndicatorHelper;
|
||||||
|
|
||||||
@Thunk final ArrayMap<View, Runnable> mPendingAnimations = new ArrayMap<>();
|
@Thunk final ArrayMap<View, Runnable> mPendingAnimations = new ArrayMap<>();
|
||||||
|
|
||||||
private final FolderGridOrganizer mOrganizer;
|
private final FolderGridOrganizer mOrganizer;
|
||||||
|
private final ViewCache mViewCache;
|
||||||
|
|
||||||
private int mAllocatedContentSize;
|
private int mAllocatedContentSize;
|
||||||
@ViewDebug.ExportedProperty(category = "launcher")
|
@ViewDebug.ExportedProperty(category = "launcher")
|
||||||
|
@ -84,17 +87,20 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
|
|
||||||
private Folder mFolder;
|
private Folder mFolder;
|
||||||
|
|
||||||
|
// If the views are attached to the folder or not. A folder should be bound when its
|
||||||
|
// animating or is open.
|
||||||
|
private boolean mViewsBound = false;
|
||||||
|
|
||||||
public FolderPagedView(Context context, AttributeSet attrs) {
|
public FolderPagedView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
InvariantDeviceProfile profile = LauncherAppState.getIDP(context);
|
InvariantDeviceProfile profile = LauncherAppState.getIDP(context);
|
||||||
mOrganizer = new FolderGridOrganizer(profile);
|
mOrganizer = new FolderGridOrganizer(profile);
|
||||||
|
|
||||||
mInflater = LayoutInflater.from(context);
|
|
||||||
|
|
||||||
mIsRtl = Utilities.isRtl(getResources());
|
mIsRtl = Utilities.isRtl(getResources());
|
||||||
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
|
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
|
||||||
|
|
||||||
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
|
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
|
||||||
|
mViewCache = BaseActivity.fromContext(context).getViewCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFolder(Folder folder) {
|
public void setFolder(Folder folder) {
|
||||||
|
@ -127,35 +133,50 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
/**
|
/**
|
||||||
* Binds items to the layout.
|
* Binds items to the layout.
|
||||||
*/
|
*/
|
||||||
public void bindItems(ArrayList<WorkspaceItemInfo> items) {
|
public void bindItems(List<WorkspaceItemInfo> items) {
|
||||||
ArrayList<View> icons = new ArrayList<>();
|
if (mViewsBound) {
|
||||||
for (WorkspaceItemInfo item : items) {
|
unbindItems();
|
||||||
icons.add(createNewView(item));
|
|
||||||
}
|
}
|
||||||
arrangeChildren(icons);
|
arrangeChildren(items.stream().map(this::createNewView).collect(Collectors.toList()));
|
||||||
}
|
mViewsBound = true;
|
||||||
|
|
||||||
public void allocateSpaceForRank(int rank) {
|
|
||||||
ArrayList<View> views = new ArrayList<>(mFolder.getIconsInReadingOrder());
|
|
||||||
views.add(rank, null);
|
|
||||||
arrangeChildren(views);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create space for a new item at the end, and returns the rank for that item.
|
* Removes all the icons from the folder
|
||||||
* Also sets the current page to the last page.
|
|
||||||
*/
|
*/
|
||||||
public int allocateRankForNewItem() {
|
public void unbindItems() {
|
||||||
int rank = getItemCount();
|
for (int i = getChildCount() - 1; i >= 0; i--) {
|
||||||
allocateSpaceForRank(rank);
|
CellLayout page = (CellLayout) getChildAt(i);
|
||||||
setCurrentPage(rank / mOrganizer.getMaxItemsPerPage());
|
ShortcutAndWidgetContainer container = page.getShortcutsAndWidgets();
|
||||||
return rank;
|
for (int j = container.getChildCount() - 1; j >= 0; j--) {
|
||||||
|
mViewCache.recycleView(R.layout.folder_application, container.getChildAt(j));
|
||||||
|
}
|
||||||
|
page.removeAllViews();
|
||||||
|
mViewCache.recycleView(R.layout.folder_page, page);
|
||||||
|
}
|
||||||
|
removeAllViews();
|
||||||
|
mViewsBound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the icons are bound to the folder
|
||||||
|
*/
|
||||||
|
public boolean areViewsBound() {
|
||||||
|
return mViewsBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and adds an icon corresponding to the provided rank
|
||||||
|
* @return the created icon
|
||||||
|
*/
|
||||||
public View createAndAddViewForRank(WorkspaceItemInfo item, int rank) {
|
public View createAndAddViewForRank(WorkspaceItemInfo item, int rank) {
|
||||||
View icon = createNewView(item);
|
View icon = createNewView(item);
|
||||||
allocateSpaceForRank(rank);
|
if (!mViewsBound) {
|
||||||
addViewForRank(icon, item, rank);
|
return icon;
|
||||||
|
}
|
||||||
|
ArrayList<View> views = new ArrayList<>(mFolder.getIconsInReadingOrder());
|
||||||
|
views.add(rank, icon);
|
||||||
|
arrangeChildren(views);
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,16 +194,24 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
|
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
public View createNewView(WorkspaceItemInfo item) {
|
public View createNewView(WorkspaceItemInfo item) {
|
||||||
final BubbleTextView textView = (BubbleTextView) mInflater.inflate(
|
if (item == null) {
|
||||||
R.layout.folder_application, null, false);
|
return null;
|
||||||
|
}
|
||||||
|
final BubbleTextView textView = mViewCache.getView(
|
||||||
|
R.layout.folder_application, getContext(), null);
|
||||||
textView.applyFromWorkspaceItem(item);
|
textView.applyFromWorkspaceItem(item);
|
||||||
textView.setHapticFeedbackEnabled(false);
|
|
||||||
textView.setOnClickListener(ItemClickHandler.INSTANCE);
|
textView.setOnClickListener(ItemClickHandler.INSTANCE);
|
||||||
textView.setOnLongClickListener(mFolder);
|
textView.setOnLongClickListener(mFolder);
|
||||||
textView.setOnFocusChangeListener(mFocusIndicatorHelper);
|
textView.setOnFocusChangeListener(mFocusIndicatorHelper);
|
||||||
|
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) textView.getLayoutParams();
|
||||||
|
if (lp == null) {
|
||||||
textView.setLayoutParams(new CellLayout.LayoutParams(
|
textView.setLayoutParams(new CellLayout.LayoutParams(
|
||||||
item.cellX, item.cellY, item.spanX, item.spanY));
|
item.cellX, item.cellY, item.spanX, item.spanY));
|
||||||
|
} else {
|
||||||
|
lp.cellX = item.cellX;
|
||||||
|
lp.cellY = item.cellY;
|
||||||
|
lp.cellHSpan = lp.cellVSpan = 1;
|
||||||
|
}
|
||||||
return textView;
|
return textView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +226,7 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
|
|
||||||
private CellLayout createAndAddNewPage() {
|
private CellLayout createAndAddNewPage() {
|
||||||
DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
|
DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
|
||||||
CellLayout page = (CellLayout) mInflater.inflate(R.layout.folder_page, this, false);
|
CellLayout page = mViewCache.getView(R.layout.folder_page, getContext(), this);
|
||||||
page.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
|
page.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
|
||||||
page.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
|
page.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
|
||||||
page.setInvertIfRtl(true);
|
page.setInvertIfRtl(true);
|
||||||
|
@ -240,7 +269,7 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
* @param list the ordered list of children.
|
* @param list the ordered list of children.
|
||||||
*/
|
*/
|
||||||
@SuppressLint("RtlHardcoded")
|
@SuppressLint("RtlHardcoded")
|
||||||
public void arrangeChildren(ArrayList<View> list) {
|
public void arrangeChildren(List<View> list) {
|
||||||
int itemCount = list.size();
|
int itemCount = list.size();
|
||||||
ArrayList<CellLayout> pages = new ArrayList<>();
|
ArrayList<CellLayout> pages = new ArrayList<>();
|
||||||
for (int i = 0; i < getChildCount(); i++) {
|
for (int i = 0; i < getChildCount(); i++) {
|
||||||
|
@ -313,16 +342,6 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
(getPageAt(0).getDesiredHeight() + getPaddingTop() + getPaddingBottom()) : 0;
|
(getPageAt(0).getDesiredHeight() + getPaddingTop() + getPaddingBottom()) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getItemCount() {
|
|
||||||
int lastPageIndex = getChildCount() - 1;
|
|
||||||
if (lastPageIndex < 0) {
|
|
||||||
// If there are no pages, nothing has yet been added to the folder.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return getPageAt(lastPageIndex).getShortcutsAndWidgets().getChildCount()
|
|
||||||
+ lastPageIndex * mOrganizer.getMaxItemsPerPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the rank of the cell nearest to the provided pixel position.
|
* @return the rank of the cell nearest to the provided pixel position.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,6 +17,8 @@ package com.android.launcher3.folder;
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
import com.android.launcher3.WorkspaceItemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the parameters used to draw a Folder preview item.
|
* Manages the parameters used to draw a Folder preview item.
|
||||||
*/
|
*/
|
||||||
|
@ -25,9 +27,10 @@ class PreviewItemDrawingParams {
|
||||||
float transY;
|
float transY;
|
||||||
float scale;
|
float scale;
|
||||||
float overlayAlpha;
|
float overlayAlpha;
|
||||||
FolderPreviewItemAnim anim;
|
public FolderPreviewItemAnim anim;
|
||||||
public boolean hidden;
|
public boolean hidden;
|
||||||
Drawable drawable;
|
public Drawable drawable;
|
||||||
|
public WorkspaceItemInfo item;
|
||||||
|
|
||||||
PreviewItemDrawingParams(float transX, float transY, float scale, float overlayAlpha) {
|
PreviewItemDrawingParams(float transX, float transY, float scale, float overlayAlpha) {
|
||||||
this.transX = transX;
|
this.transX = transX;
|
||||||
|
|
|
@ -23,28 +23,51 @@ import static com.android.launcher3.folder.FolderIcon.DROP_IN_ANIMATION_DURATION
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.FloatProperty;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.launcher3.BubbleTextView;
|
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.DrawableFactory;
|
||||||
|
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the drawing and animations of {@link PreviewItemDrawingParams} for a {@link FolderIcon}.
|
* Manages the drawing and animations of {@link PreviewItemDrawingParams} for a {@link FolderIcon}.
|
||||||
*/
|
*/
|
||||||
public class PreviewItemManager {
|
public class PreviewItemManager {
|
||||||
|
|
||||||
private FolderIcon mIcon;
|
private static final FloatProperty<PreviewItemManager> CURRENT_PAGE_ITEMS_TRANS_X =
|
||||||
|
new FloatProperty<PreviewItemManager>("currentPageItemsTransX") {
|
||||||
|
@Override
|
||||||
|
public void setValue(PreviewItemManager manager, float v) {
|
||||||
|
manager.mCurrentPageItemsTransX = v;
|
||||||
|
manager.onParamsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Float get(PreviewItemManager manager) {
|
||||||
|
return manager.mCurrentPageItemsTransX;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final FolderIcon mIcon;
|
||||||
|
private final DrawableFactory mDrawableFactory;
|
||||||
|
private final int mIconSize;
|
||||||
|
|
||||||
// These variables are all associated with the drawing of the preview; they are stored
|
// These variables are all associated with the drawing of the preview; they are stored
|
||||||
// as member variables for shared usage and to avoid computation on each frame
|
// as member variables for shared usage and to avoid computation on each frame
|
||||||
|
@ -69,7 +92,10 @@ public class PreviewItemManager {
|
||||||
private static final int ITEM_SLIDE_IN_OUT_DISTANCE_PX = 200;
|
private static final int ITEM_SLIDE_IN_OUT_DISTANCE_PX = 200;
|
||||||
|
|
||||||
public PreviewItemManager(FolderIcon icon) {
|
public PreviewItemManager(FolderIcon icon) {
|
||||||
|
mContext = icon.getContext();
|
||||||
mIcon = icon;
|
mIcon = icon;
|
||||||
|
mDrawableFactory = DrawableFactory.INSTANCE.get(mContext);
|
||||||
|
mIconSize = Launcher.getLauncher(mContext).getDeviceProfile().folderChildIconSizePx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -200,7 +226,7 @@ public class PreviewItemManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildParamsForPage(int page, ArrayList<PreviewItemDrawingParams> params, boolean animate) {
|
void buildParamsForPage(int page, ArrayList<PreviewItemDrawingParams> params, boolean animate) {
|
||||||
List<BubbleTextView> items = mIcon.getPreviewIconsOnPage(page);
|
List<WorkspaceItemInfo> items = mIcon.getPreviewItemsOnPage(page);
|
||||||
int prevNumItems = params.size();
|
int prevNumItems = params.size();
|
||||||
|
|
||||||
// We adjust the size of the list to match the number of items in the preview.
|
// We adjust the size of the list to match the number of items in the preview.
|
||||||
|
@ -214,13 +240,7 @@ public class PreviewItemManager {
|
||||||
int numItemsInFirstPagePreview = page == 0 ? items.size() : MAX_NUM_ITEMS_IN_PREVIEW;
|
int numItemsInFirstPagePreview = page == 0 ? items.size() : MAX_NUM_ITEMS_IN_PREVIEW;
|
||||||
for (int i = 0; i < params.size(); i++) {
|
for (int i = 0; i < params.size(); i++) {
|
||||||
PreviewItemDrawingParams p = params.get(i);
|
PreviewItemDrawingParams p = params.get(i);
|
||||||
p.drawable = items.get(i).getCompoundDrawables()[1];
|
setDrawable(p, items.get(i));
|
||||||
|
|
||||||
if (p.drawable != null && !mIcon.mFolder.isOpen()) {
|
|
||||||
// Set the callback to FolderIcon as it is responsible to drawing the icon. The
|
|
||||||
// callback will be released when the folder is opened.
|
|
||||||
p.drawable.setCallback(mIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!animate) {
|
if (!animate) {
|
||||||
computePreviewItemDrawingParams(i, numItemsInFirstPagePreview, p);
|
computePreviewItemDrawingParams(i, numItemsInFirstPagePreview, p);
|
||||||
|
@ -253,14 +273,8 @@ public class PreviewItemManager {
|
||||||
buildParamsForPage(currentPage, mCurrentPageParams, false);
|
buildParamsForPage(currentPage, mCurrentPageParams, false);
|
||||||
onParamsChanged();
|
onParamsChanged();
|
||||||
|
|
||||||
ValueAnimator slideAnimator = ValueAnimator.ofFloat(0, ITEM_SLIDE_IN_OUT_DISTANCE_PX);
|
ValueAnimator slideAnimator = ObjectAnimator
|
||||||
slideAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
.ofFloat(this, CURRENT_PAGE_ITEMS_TRANS_X, 0, ITEM_SLIDE_IN_OUT_DISTANCE_PX);
|
||||||
@Override
|
|
||||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
|
||||||
mCurrentPageItemsTransX = (float) valueAnimator.getAnimatedValue();
|
|
||||||
onParamsChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
slideAnimator.addListener(new AnimatorListenerAdapter() {
|
slideAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
@ -277,6 +291,25 @@ public class PreviewItemManager {
|
||||||
buildParamsForPage(0, mFirstPageParams, animate);
|
buildParamsForPage(0, mFirstPageParams, animate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updatePreviewItems(Predicate<WorkspaceItemInfo> itemCheck) {
|
||||||
|
boolean modified = false;
|
||||||
|
for (PreviewItemDrawingParams param : mFirstPageParams) {
|
||||||
|
if (itemCheck.test(param.item)) {
|
||||||
|
setDrawable(param, param.item);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (PreviewItemDrawingParams param : mCurrentPageParams) {
|
||||||
|
if (itemCheck.test(param.item)) {
|
||||||
|
setDrawable(param, param.item);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (modified) {
|
||||||
|
mIcon.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean verifyDrawable(@NonNull Drawable who) {
|
boolean verifyDrawable(@NonNull Drawable who) {
|
||||||
for (int i = 0; i < mFirstPageParams.size(); i++) {
|
for (int i = 0; i < mFirstPageParams.size(); i++) {
|
||||||
if (mFirstPageParams.get(i).drawable == who) {
|
if (mFirstPageParams.get(i).drawable == who) {
|
||||||
|
@ -296,46 +329,46 @@ public class PreviewItemManager {
|
||||||
* - Moving into a new position
|
* - Moving into a new position
|
||||||
* - Moving out of the preview
|
* - Moving out of the preview
|
||||||
*
|
*
|
||||||
* @param oldParams The list of items in the old preview.
|
* @param oldItems The list of items in the old preview.
|
||||||
* @param newParams The list of items in the new preview.
|
* @param newItems The list of items in the new preview.
|
||||||
* @param dropped The item that was dropped onto the FolderIcon.
|
* @param dropped The item that was dropped onto the FolderIcon.
|
||||||
*/
|
*/
|
||||||
public void onDrop(List<BubbleTextView> oldParams, List<BubbleTextView> newParams,
|
public void onDrop(List<WorkspaceItemInfo> oldItems, List<WorkspaceItemInfo> newItems,
|
||||||
WorkspaceItemInfo dropped) {
|
WorkspaceItemInfo dropped) {
|
||||||
int numItems = newParams.size();
|
int numItems = newItems.size();
|
||||||
final ArrayList<PreviewItemDrawingParams> params = mFirstPageParams;
|
final ArrayList<PreviewItemDrawingParams> params = mFirstPageParams;
|
||||||
buildParamsForPage(0, params, false);
|
buildParamsForPage(0, params, false);
|
||||||
|
|
||||||
// New preview items for items that are moving in (except for the dropped item).
|
// New preview items for items that are moving in (except for the dropped item).
|
||||||
List<BubbleTextView> moveIn = new ArrayList<>();
|
List<WorkspaceItemInfo> moveIn = new ArrayList<>();
|
||||||
for (BubbleTextView btv : newParams) {
|
for (WorkspaceItemInfo newItem : newItems) {
|
||||||
if (!oldParams.contains(btv) && !btv.getTag().equals(dropped)) {
|
if (!oldItems.contains(newItem) && !newItem.equals(dropped)) {
|
||||||
moveIn.add(btv);
|
moveIn.add(newItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < moveIn.size(); ++i) {
|
for (int i = 0; i < moveIn.size(); ++i) {
|
||||||
int prevIndex = newParams.indexOf(moveIn.get(i));
|
int prevIndex = newItems.indexOf(moveIn.get(i));
|
||||||
PreviewItemDrawingParams p = params.get(prevIndex);
|
PreviewItemDrawingParams p = params.get(prevIndex);
|
||||||
computePreviewItemDrawingParams(prevIndex, numItems, p);
|
computePreviewItemDrawingParams(prevIndex, numItems, p);
|
||||||
updateTransitionParam(p, moveIn.get(i), ENTER_INDEX, newParams.indexOf(moveIn.get(i)),
|
updateTransitionParam(p, moveIn.get(i), ENTER_INDEX, newItems.indexOf(moveIn.get(i)),
|
||||||
numItems);
|
numItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Items that are moving into new positions within the preview.
|
// Items that are moving into new positions within the preview.
|
||||||
for (int newIndex = 0; newIndex < newParams.size(); ++newIndex) {
|
for (int newIndex = 0; newIndex < newItems.size(); ++newIndex) {
|
||||||
int oldIndex = oldParams.indexOf(newParams.get(newIndex));
|
int oldIndex = oldItems.indexOf(newItems.get(newIndex));
|
||||||
if (oldIndex >= 0 && newIndex != oldIndex) {
|
if (oldIndex >= 0 && newIndex != oldIndex) {
|
||||||
PreviewItemDrawingParams p = params.get(newIndex);
|
PreviewItemDrawingParams p = params.get(newIndex);
|
||||||
updateTransitionParam(p, newParams.get(newIndex), oldIndex, newIndex, numItems);
|
updateTransitionParam(p, newItems.get(newIndex), oldIndex, newIndex, numItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old preview items that need to be moved out.
|
// Old preview items that need to be moved out.
|
||||||
List<BubbleTextView> moveOut = new ArrayList<>(oldParams);
|
List<WorkspaceItemInfo> moveOut = new ArrayList<>(oldItems);
|
||||||
moveOut.removeAll(newParams);
|
moveOut.removeAll(newItems);
|
||||||
for (int i = 0; i < moveOut.size(); ++i) {
|
for (int i = 0; i < moveOut.size(); ++i) {
|
||||||
BubbleTextView item = moveOut.get(i);
|
WorkspaceItemInfo item = moveOut.get(i);
|
||||||
int oldIndex = oldParams.indexOf(item);
|
int oldIndex = oldItems.indexOf(item);
|
||||||
PreviewItemDrawingParams p = computePreviewItemDrawingParams(oldIndex, numItems, null);
|
PreviewItemDrawingParams p = computePreviewItemDrawingParams(oldIndex, numItems, null);
|
||||||
updateTransitionParam(p, item, oldIndex, EXIT_INDEX, numItems);
|
updateTransitionParam(p, item, oldIndex, EXIT_INDEX, numItems);
|
||||||
params.add(0, p); // We want these items first so that they are on drawn last.
|
params.add(0, p); // We want these items first so that they are on drawn last.
|
||||||
|
@ -348,14 +381,9 @@ public class PreviewItemManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTransitionParam(final PreviewItemDrawingParams p, BubbleTextView btv,
|
private void updateTransitionParam(final PreviewItemDrawingParams p, WorkspaceItemInfo item,
|
||||||
int prevIndex, int newIndex, int numItems) {
|
int prevIndex, int newIndex, int numItems) {
|
||||||
p.drawable = btv.getCompoundDrawables()[1];
|
setDrawable(p, item);
|
||||||
if (!mIcon.mFolder.isOpen()) {
|
|
||||||
// Set the callback to FolderIcon as it is responsible to drawing the icon. The
|
|
||||||
// callback will be released when the folder is opened.
|
|
||||||
p.drawable.setCallback(mIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, prevIndex, numItems,
|
FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, prevIndex, numItems,
|
||||||
newIndex, numItems, DROP_IN_ANIMATION_DURATION, null);
|
newIndex, numItems, DROP_IN_ANIMATION_DURATION, null);
|
||||||
|
@ -364,4 +392,20 @@ public class PreviewItemManager {
|
||||||
}
|
}
|
||||||
p.anim = anim;
|
p.anim = anim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setDrawable(PreviewItemDrawingParams p, WorkspaceItemInfo item) {
|
||||||
|
if (item.hasPromiseIconUi()) {
|
||||||
|
PreloadIconDrawable drawable = mDrawableFactory.newPendingIcon(mContext, item);
|
||||||
|
drawable.setLevel(item.getInstallProgress());
|
||||||
|
p.drawable = drawable;
|
||||||
|
} else {
|
||||||
|
p.drawable = mDrawableFactory.newIcon(mContext, item);
|
||||||
|
}
|
||||||
|
p.drawable.setBounds(0, 0, mIconSize, mIconSize);
|
||||||
|
p.item = item;
|
||||||
|
|
||||||
|
// Set the callback to FolderIcon as it is responsible to drawing the icon. The
|
||||||
|
// callback will be released when the folder is opened.
|
||||||
|
p.drawable.setCallback(mIcon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue