Merge "Refactoring floating view opening/closing logic" into ub-launcher3-master
This commit is contained in:
commit
631ffbda64
|
@ -91,6 +91,9 @@
|
|||
<!-- View ID used by cell layout to jail its content -->
|
||||
<item type="id" name="cell_layout_jail_id" />
|
||||
|
||||
<!-- View ID used by PreviewImageView to cache its instance -->
|
||||
<item type="id" name="preview_image_id" />
|
||||
|
||||
<!-- Deep shortcuts -->
|
||||
<integer name="config_deepShortcutOpenDuration">220</integer>
|
||||
<integer name="config_deepShortcutArrowOpenDuration">80</integer>
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Base class for a View which shows a floating UI on top of the launcher UI.
|
||||
*/
|
||||
public abstract class AbstractFloatingView extends LinearLayout {
|
||||
|
||||
@IntDef(flag = true, value = {TYPE_FOLDER, TYPE_DEEPSHORTCUT_CONTAINER})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface FloatingViewType {}
|
||||
public static final int TYPE_FOLDER = 1 << 0;
|
||||
public static final int TYPE_DEEPSHORTCUT_CONTAINER = 1 << 1;
|
||||
|
||||
protected boolean mIsOpen;
|
||||
|
||||
public AbstractFloatingView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public AbstractFloatingView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public final void close(boolean animate) {
|
||||
animate &= !Utilities.isPowerSaverOn(getContext());
|
||||
handleClose(animate);
|
||||
Launcher.getLauncher(getContext()).getUserEventDispatcher().resetElapsedContainerMillis();
|
||||
}
|
||||
|
||||
protected abstract void handleClose(boolean animate);
|
||||
|
||||
/**
|
||||
* If the view is current handling keyboard, return the active target, null otherwise
|
||||
*/
|
||||
public ExtendedEditText getActiveTextView() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Any additional view (outside of this container) where touch should be allowed while this
|
||||
* view is visible.
|
||||
*/
|
||||
public View getExtendedTouchView() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final boolean isOpen() {
|
||||
return mIsOpen;
|
||||
}
|
||||
|
||||
protected abstract boolean isOfType(@FloatingViewType int type);
|
||||
|
||||
protected static <T extends AbstractFloatingView> T getOpenView(
|
||||
Launcher launcher, @FloatingViewType int type) {
|
||||
DragLayer dragLayer = launcher.getDragLayer();
|
||||
// Iterate in reverse order. AbstractFloatingView is added later to the dragLayer,
|
||||
// and will be one of the last views.
|
||||
for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = dragLayer.getChildAt(i);
|
||||
if (child instanceof AbstractFloatingView) {
|
||||
AbstractFloatingView view = (AbstractFloatingView) child;
|
||||
if (view.isOfType(type) && view.isOpen()) {
|
||||
return (T) view;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static void closeOpenContainer(Launcher launcher, @FloatingViewType int type) {
|
||||
AbstractFloatingView view = getOpenView(launcher, type);
|
||||
if (view != null) {
|
||||
view.close(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeAllOpenViews(Launcher launcher, boolean animate) {
|
||||
DragLayer dragLayer = launcher.getDragLayer();
|
||||
// Iterate in reverse order. AbstractFloatingView is added later to the dragLayer,
|
||||
// and will be one of the last views.
|
||||
for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = dragLayer.getChildAt(i);
|
||||
if (child instanceof AbstractFloatingView) {
|
||||
((AbstractFloatingView) child).close(animate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeAllOpenViews(Launcher launcher) {
|
||||
closeAllOpenViews(launcher, true);
|
||||
}
|
||||
|
||||
public static AbstractFloatingView getTopOpenView(Launcher launcher) {
|
||||
return getOpenView(launcher, TYPE_FOLDER | TYPE_DEEPSHORTCUT_CONTAINER);
|
||||
}
|
||||
}
|
|
@ -99,4 +99,12 @@ public class ExtendedEditText extends EditText {
|
|||
((InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE))
|
||||
.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
|
||||
public void dispatchBackKey() {
|
||||
((InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE))
|
||||
.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
if (mBackKeyListener != null) {
|
||||
mBackKeyListener.onBackKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,11 +45,6 @@ public class FolderInfo extends ItemInfo {
|
|||
*/
|
||||
public static final int FLAG_MULTI_PAGE_ANIMATION = 0x00000004;
|
||||
|
||||
/**
|
||||
* Whether this folder has been opened
|
||||
*/
|
||||
public boolean opened;
|
||||
|
||||
public int options;
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,9 +18,7 @@ package com.android.launcher3;
|
|||
|
||||
import android.Manifest;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
|
@ -47,8 +45,6 @@ import android.content.pm.PackageManager;
|
|||
import android.content.res.Configuration;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -79,10 +75,8 @@ import android.view.ViewGroup;
|
|||
import android.view.ViewTreeObserver;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -295,13 +289,6 @@ public class Launcher extends Activity
|
|||
// it from the context.
|
||||
private SharedPreferences mSharedPrefs;
|
||||
|
||||
// Holds the page that we need to animate to, and the icon views that we need to animate up
|
||||
// when we scroll to that page on resume.
|
||||
@Thunk ImageView mFolderIconImageView;
|
||||
private Bitmap mFolderIconBitmap;
|
||||
private Canvas mFolderIconCanvas;
|
||||
private Rect mRectForFolderAnimation = new Rect();
|
||||
|
||||
private DeviceProfile mDeviceProfile;
|
||||
|
||||
private boolean mMoveToDefaultScreenFromNewIntent;
|
||||
|
@ -1231,11 +1218,8 @@ public class Launcher extends Activity
|
|||
if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
// Ignore the menu key if we are currently dragging or are on the custom content screen
|
||||
if (!isOnCustomContent() && !mDragController.isDragging()) {
|
||||
// Close any open folders
|
||||
closeFolder();
|
||||
|
||||
// Close any shortcuts containers
|
||||
closeShortcutsContainer();
|
||||
// Close any open floating view
|
||||
AbstractFloatingView.closeAllOpenViews(this);
|
||||
|
||||
// Stop resizing any widgets
|
||||
mWorkspace.exitWidgetResizeMode();
|
||||
|
@ -1705,7 +1689,7 @@ public class Launcher extends Activity
|
|||
|
||||
// Check this condition before handling isActionMain, as this will get reset.
|
||||
boolean shouldMoveToDefaultScreen = alreadyOnHome &&
|
||||
mState == State.WORKSPACE && getTopFloatingView() == null;
|
||||
mState == State.WORKSPACE && AbstractFloatingView.getTopOpenView(this) == null;
|
||||
|
||||
boolean isActionMain = Intent.ACTION_MAIN.equals(intent.getAction());
|
||||
if (isActionMain) {
|
||||
|
@ -1719,8 +1703,7 @@ public class Launcher extends Activity
|
|||
// In all these cases, only animate if we're already on home
|
||||
mWorkspace.exitWidgetResizeMode();
|
||||
|
||||
closeFolder(alreadyOnHome);
|
||||
closeShortcutsContainer(alreadyOnHome);
|
||||
AbstractFloatingView.closeAllOpenViews(this, alreadyOnHome);
|
||||
exitSpringLoadedDragMode();
|
||||
|
||||
// If we are already on home, then just animate back to the workspace,
|
||||
|
@ -1803,11 +1786,9 @@ public class Launcher extends Activity
|
|||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putInt(RUNTIME_STATE, mState.ordinal());
|
||||
// We close any open folder since it will not be re-opened, and we need to make sure
|
||||
// this state is reflected.
|
||||
// TODO: Move folderInfo.isOpened out of the model and make it a UI state.
|
||||
closeFolder(false);
|
||||
closeShortcutsContainer(false);
|
||||
// We close any open folders and shortcut containers since they will not be re-opened,
|
||||
// and we need to make sure this state is reflected.
|
||||
AbstractFloatingView.closeAllOpenViews(this, false);
|
||||
|
||||
if (mPendingRequestArgs != null) {
|
||||
outState.putParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS, mPendingRequestArgs);
|
||||
|
@ -2036,7 +2017,7 @@ public class Launcher extends Activity
|
|||
|
||||
protected void moveToCustomContentScreen(boolean animate) {
|
||||
// Close any folders that may be open.
|
||||
closeFolder();
|
||||
AbstractFloatingView.closeAllOpenViews(this, animate);
|
||||
mWorkspace.moveToCustomContentScreen(animate);
|
||||
}
|
||||
|
||||
|
@ -2227,21 +2208,19 @@ public class Launcher extends Activity
|
|||
return;
|
||||
}
|
||||
|
||||
if (getOpenShortcutsContainer() != null) {
|
||||
closeShortcutsContainer();
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
|
||||
if (topView != null) {
|
||||
if (topView.getActiveTextView() != null) {
|
||||
topView.getActiveTextView().dispatchBackKey();
|
||||
} else {
|
||||
topView.close(true);
|
||||
}
|
||||
} else if (isAppsViewVisible()) {
|
||||
showWorkspace(true);
|
||||
} else if (isWidgetsViewVisible()) {
|
||||
showOverviewMode(true);
|
||||
} else if (mWorkspace.isInOverviewMode()) {
|
||||
showWorkspace(true);
|
||||
} else if (mWorkspace.getOpenFolder() != null) {
|
||||
Folder openFolder = mWorkspace.getOpenFolder();
|
||||
if (openFolder.isEditingName()) {
|
||||
openFolder.dismissEditingName();
|
||||
} else {
|
||||
closeFolder();
|
||||
}
|
||||
} else {
|
||||
mWorkspace.exitWidgetResizeMode();
|
||||
|
||||
|
@ -2491,10 +2470,10 @@ public class Launcher extends Activity
|
|||
throw new IllegalArgumentException("Input must be a FolderIcon");
|
||||
}
|
||||
|
||||
FolderIcon folderIcon = (FolderIcon) v;
|
||||
if (!folderIcon.getFolderInfo().opened && !folderIcon.getFolder().isDestroyed()) {
|
||||
Folder folder = ((FolderIcon) v).getFolder();
|
||||
if (!folder.isOpen() && !folder.isDestroyed()) {
|
||||
// Open the requested folder
|
||||
openFolder(folderIcon);
|
||||
folder.animateOpen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2735,233 +2714,6 @@ public class Launcher extends Activity
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method draws the FolderIcon to an ImageView and then adds and positions that ImageView
|
||||
* in the DragLayer in the exact absolute location of the original FolderIcon.
|
||||
*/
|
||||
private void copyFolderIconToImage(FolderIcon fi) {
|
||||
final int width = fi.getMeasuredWidth();
|
||||
final int height = fi.getMeasuredHeight();
|
||||
|
||||
// Lazy load ImageView, Bitmap and Canvas
|
||||
if (mFolderIconImageView == null) {
|
||||
mFolderIconImageView = new ImageView(this);
|
||||
}
|
||||
if (mFolderIconBitmap == null || mFolderIconBitmap.getWidth() != width ||
|
||||
mFolderIconBitmap.getHeight() != height) {
|
||||
mFolderIconBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
mFolderIconCanvas = new Canvas(mFolderIconBitmap);
|
||||
}
|
||||
|
||||
DragLayer.LayoutParams lp;
|
||||
if (mFolderIconImageView.getLayoutParams() instanceof DragLayer.LayoutParams) {
|
||||
lp = (DragLayer.LayoutParams) mFolderIconImageView.getLayoutParams();
|
||||
} else {
|
||||
lp = new DragLayer.LayoutParams(width, height);
|
||||
}
|
||||
|
||||
// The layout from which the folder is being opened may be scaled, adjust the starting
|
||||
// view size by this scale factor.
|
||||
float scale = mDragLayer.getDescendantRectRelativeToSelf(fi, mRectForFolderAnimation);
|
||||
lp.customPosition = true;
|
||||
lp.x = mRectForFolderAnimation.left;
|
||||
lp.y = mRectForFolderAnimation.top;
|
||||
lp.width = (int) (scale * width);
|
||||
lp.height = (int) (scale * height);
|
||||
|
||||
mFolderIconCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
fi.draw(mFolderIconCanvas);
|
||||
mFolderIconImageView.setImageBitmap(mFolderIconBitmap);
|
||||
if (fi.getFolder() != null) {
|
||||
mFolderIconImageView.setPivotX(fi.getFolder().getPivotXForIconAnimation());
|
||||
mFolderIconImageView.setPivotY(fi.getFolder().getPivotYForIconAnimation());
|
||||
}
|
||||
// Just in case this image view is still in the drag layer from a previous animation,
|
||||
// we remove it and re-add it.
|
||||
if (mDragLayer.indexOfChild(mFolderIconImageView) != -1) {
|
||||
mDragLayer.removeView(mFolderIconImageView);
|
||||
}
|
||||
mDragLayer.addView(mFolderIconImageView, lp);
|
||||
if (fi.getFolder() != null) {
|
||||
fi.getFolder().bringToFront();
|
||||
}
|
||||
}
|
||||
|
||||
private void growAndFadeOutFolderIcon(FolderIcon fi) {
|
||||
if (fi == null) return;
|
||||
FolderInfo info = (FolderInfo) fi.getTag();
|
||||
if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
|
||||
CellLayout cl = (CellLayout) fi.getParent().getParent();
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) fi.getLayoutParams();
|
||||
cl.setFolderLeaveBehindCell(lp.cellX, lp.cellY);
|
||||
}
|
||||
|
||||
// Push an ImageView copy of the FolderIcon into the DragLayer and hide the original
|
||||
copyFolderIconToImage(fi);
|
||||
fi.setVisibility(View.INVISIBLE);
|
||||
|
||||
ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(
|
||||
mFolderIconImageView, 0, 1.5f, 1.5f);
|
||||
if (Utilities.ATLEAST_LOLLIPOP) {
|
||||
oa.setInterpolator(new LogDecelerateInterpolator(100, 0));
|
||||
}
|
||||
oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
|
||||
oa.start();
|
||||
}
|
||||
|
||||
private void shrinkAndFadeInFolderIcon(final FolderIcon fi, boolean animate) {
|
||||
if (fi == null) return;
|
||||
final CellLayout cl = (CellLayout) fi.getParent().getParent();
|
||||
|
||||
// We remove and re-draw the FolderIcon in-case it has changed
|
||||
mDragLayer.removeView(mFolderIconImageView);
|
||||
copyFolderIconToImage(fi);
|
||||
|
||||
if (cl != null) {
|
||||
cl.clearFolderLeaveBehind();
|
||||
}
|
||||
|
||||
ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(mFolderIconImageView, 1, 1, 1);
|
||||
oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
|
||||
oa.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (cl != null) {
|
||||
// Remove the ImageView copy of the FolderIcon and make the original visible.
|
||||
mDragLayer.removeView(mFolderIconImageView);
|
||||
fi.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
oa.start();
|
||||
if (!animate) {
|
||||
oa.end();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param folderIcon The FolderIcon describing the folder to open.
|
||||
*/
|
||||
public void openFolder(FolderIcon folderIcon) {
|
||||
|
||||
Folder folder = folderIcon.getFolder();
|
||||
Folder openFolder = mWorkspace != null ? mWorkspace.getOpenFolder() : null;
|
||||
if (openFolder != null && openFolder != folder) {
|
||||
// Close any open folder before opening a folder.
|
||||
closeFolder();
|
||||
}
|
||||
|
||||
FolderInfo info = folder.mInfo;
|
||||
|
||||
info.opened = true;
|
||||
|
||||
// While the folder is open, the position of the icon cannot change.
|
||||
((CellLayout.LayoutParams) folderIcon.getLayoutParams()).canReorder = false;
|
||||
|
||||
// Just verify that the folder hasn't already been added to the DragLayer.
|
||||
// There was a one-off crash where the folder had a parent already.
|
||||
if (folder.getParent() == null) {
|
||||
mDragLayer.addView(folder);
|
||||
mDragController.addDropTarget(folder);
|
||||
} else {
|
||||
Log.w(TAG, "Opening folder (" + folder + ") which already has a parent (" +
|
||||
folder.getParent() + ").");
|
||||
}
|
||||
folder.animateOpen();
|
||||
|
||||
growAndFadeOutFolderIcon(folderIcon);
|
||||
|
||||
// Notify the accessibility manager that this folder "window" has appeared and occluded
|
||||
// the workspace items
|
||||
folder.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
getDragLayer().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
||||
|
||||
getUserEventDispatcher().resetElapsedContainerMillis();
|
||||
}
|
||||
|
||||
public void closeFolder() {
|
||||
closeFolder(true);
|
||||
}
|
||||
|
||||
public void closeFolder(boolean animate) {
|
||||
Folder folder = mWorkspace != null ? mWorkspace.getOpenFolder() : null;
|
||||
if (folder != null) {
|
||||
if (folder.isEditingName()) {
|
||||
folder.dismissEditingName();
|
||||
}
|
||||
closeFolder(folder, animate);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeFolder(Folder folder, boolean animate) {
|
||||
animate &= !Utilities.isPowerSaverOn(this);
|
||||
|
||||
folder.getInfo().opened = false;
|
||||
|
||||
ViewGroup parent = (ViewGroup) folder.getParent().getParent();
|
||||
if (parent != null) {
|
||||
FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
|
||||
shrinkAndFadeInFolderIcon(fi, animate);
|
||||
if (fi != null) {
|
||||
((CellLayout.LayoutParams) fi.getLayoutParams()).canReorder = true;
|
||||
}
|
||||
}
|
||||
if (animate) {
|
||||
folder.animateClosed();
|
||||
} else {
|
||||
folder.close(false);
|
||||
}
|
||||
|
||||
// Notify the accessibility manager that this folder "window" has disappeared and no
|
||||
// longer occludes the workspace items
|
||||
getDragLayer().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
|
||||
getUserEventDispatcher().resetElapsedContainerMillis();
|
||||
}
|
||||
|
||||
public void closeShortcutsContainer() {
|
||||
closeShortcutsContainer(true);
|
||||
}
|
||||
|
||||
public void closeShortcutsContainer(boolean animate) {
|
||||
DeepShortcutsContainer deepShortcutsContainer = getOpenShortcutsContainer();
|
||||
if (deepShortcutsContainer != null) {
|
||||
if (animate) {
|
||||
deepShortcutsContainer.animateClose();
|
||||
} else {
|
||||
deepShortcutsContainer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public View getTopFloatingView() {
|
||||
View topView = getOpenShortcutsContainer();
|
||||
if (topView == null) {
|
||||
topView = getWorkspace().getOpenFolder();
|
||||
}
|
||||
return topView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The open shortcuts container, or null if there is none
|
||||
*/
|
||||
public DeepShortcutsContainer getOpenShortcutsContainer() {
|
||||
// Iterate in reverse order. Shortcuts container is added later to the dragLayer,
|
||||
// and will be one of the last views.
|
||||
for (int i = mDragLayer.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = mDragLayer.getChildAt(i);
|
||||
if (child instanceof DeepShortcutsContainer
|
||||
&& ((DeepShortcutsContainer) child).isOpen()) {
|
||||
return (DeepShortcutsContainer) child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
mLastDispatchTouchEventX = ev.getX();
|
||||
|
@ -3220,9 +2972,7 @@ public class Launcher extends Activity
|
|||
|
||||
// Change the state *after* we've called all the transition code
|
||||
mState = toState;
|
||||
|
||||
closeFolder();
|
||||
closeShortcutsContainer();
|
||||
AbstractFloatingView.closeAllOpenViews(this);
|
||||
|
||||
// Send an accessibility event to announce the context change
|
||||
getWindow().getDecorView()
|
||||
|
@ -4379,7 +4129,7 @@ public class Launcher extends Activity
|
|||
&& mAccessibilityDelegate.performAction(focusedView,
|
||||
(ItemInfo) focusedView.getTag(),
|
||||
LauncherAccessibilityDelegate.DEEP_SHORTCUTS)) {
|
||||
getOpenShortcutsContainer().requestFocus();
|
||||
DeepShortcutsContainer.getOpen(this).requestFocus();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -102,7 +102,7 @@ public class PinchToOverviewListener extends ScaleGestureDetector.SimpleOnScaleG
|
|||
// once the state switching animation is complete.
|
||||
return false;
|
||||
}
|
||||
if (mLauncher.getTopFloatingView() != null) {
|
||||
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
|
||||
// Don't listen for the pinch gesture if a floating view is open.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -553,24 +553,6 @@ public class Workspace extends PagedView
|
|||
cl.getBackgroundAlpha() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The open folder on the current screen, or null if there is none
|
||||
*/
|
||||
public Folder getOpenFolder() {
|
||||
DragLayer dragLayer = mLauncher.getDragLayer();
|
||||
// Iterate in reverse order. Folder is added later to the dragLayer,
|
||||
// and will be one of the last views.
|
||||
for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = dragLayer.getChildAt(i);
|
||||
if (child instanceof Folder) {
|
||||
Folder folder = (Folder) child;
|
||||
if (folder.getInfo().opened)
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isTouchActive() {
|
||||
return mTouchState != TOUCH_STATE_REST;
|
||||
}
|
||||
|
@ -3811,7 +3793,7 @@ public class Workspace extends PagedView
|
|||
if (!workspaceInModalState() && !mIsSwitchingState) {
|
||||
super.scrollLeft();
|
||||
}
|
||||
Folder openFolder = getOpenFolder();
|
||||
Folder openFolder = Folder.getOpen(mLauncher);
|
||||
if (openFolder != null) {
|
||||
openFolder.completeDragExit();
|
||||
}
|
||||
|
@ -3822,7 +3804,7 @@ public class Workspace extends PagedView
|
|||
if (!workspaceInModalState() && !mIsSwitchingState) {
|
||||
super.scrollRight();
|
||||
}
|
||||
Folder openFolder = getOpenFolder();
|
||||
Folder openFolder = Folder.getOpen(mLauncher);
|
||||
if (openFolder != null) {
|
||||
openFolder.completeDragExit();
|
||||
}
|
||||
|
@ -3841,7 +3823,7 @@ public class Workspace extends PagedView
|
|||
}
|
||||
|
||||
boolean result = false;
|
||||
if (!workspaceInModalState() && !mIsSwitchingState && getOpenFolder() == null) {
|
||||
if (!workspaceInModalState() && !mIsSwitchingState && Folder.getOpen(mLauncher) == null) {
|
||||
mInScrollArea = true;
|
||||
|
||||
final int page = getNextPage() +
|
||||
|
|
|
@ -192,8 +192,8 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||
});
|
||||
return true;
|
||||
} else if (action == MOVE_TO_WORKSPACE) {
|
||||
Folder folder = mLauncher.getWorkspace().getOpenFolder();
|
||||
mLauncher.closeFolder(folder, true);
|
||||
Folder folder = Folder.getOpen(mLauncher);
|
||||
folder.close(true);
|
||||
ShortcutInfo info = (ShortcutInfo) item;
|
||||
folder.getInfo().remove(info, false);
|
||||
|
||||
|
@ -373,12 +373,10 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||
mLauncher.getDragLayer().getDescendantRectRelativeToSelf(item, pos);
|
||||
mLauncher.getDragController().prepareAccessibleDrag(pos.centerX(), pos.centerY());
|
||||
|
||||
Workspace workspace = mLauncher.getWorkspace();
|
||||
|
||||
Folder folder = workspace.getOpenFolder();
|
||||
Folder folder = Folder.getOpen(mLauncher);
|
||||
if (folder != null) {
|
||||
if (!folder.getItemsInReadingOrder().contains(item)) {
|
||||
mLauncher.closeFolder();
|
||||
folder.close(true);
|
||||
folder = null;
|
||||
}
|
||||
}
|
||||
|
@ -390,7 +388,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||
if (folder != null) {
|
||||
folder.startDrag(cellInfo.cell, options);
|
||||
} else {
|
||||
workspace.startDrag(cellInfo, options);
|
||||
mLauncher.getWorkspace().startDrag(cellInfo, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.android.launcher3.accessibility;
|
|||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherModel;
|
||||
|
@ -64,7 +65,7 @@ public class ShortcutMenuAccessibilityDelegate extends LauncherAccessibilityDele
|
|||
ArrayList<ItemInfo> itemList = new ArrayList<>();
|
||||
itemList.add(info);
|
||||
mLauncher.bindItems(itemList, 0, itemList.size(), true);
|
||||
mLauncher.closeShortcutsContainer();
|
||||
AbstractFloatingView.closeAllOpenViews(mLauncher);
|
||||
announceConfirmation(R.string.item_added_to_workspace);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -52,6 +52,7 @@ import com.android.launcher3.dragndrop.DragOptions;
|
|||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.graphics.TintedDrawableSpan;
|
||||
import com.android.launcher3.keyboard.FocusedItemDecorator;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutsContainer;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
|
@ -265,7 +266,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
}
|
||||
|
||||
// IF a shortcuts container is open, container should not be pulled down.
|
||||
if (mLauncher.getOpenShortcutsContainer() != null) {
|
||||
if (DeepShortcutsContainer.getOpen(mLauncher) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,9 +49,11 @@ import android.view.animation.Interpolator;
|
|||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.AppWidgetResizeFrame;
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DropTargetBar;
|
||||
import com.android.launcher3.ExtendedEditText;
|
||||
import com.android.launcher3.InsettableFrameLayout;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppWidgetHostView;
|
||||
|
@ -66,7 +68,6 @@ import com.android.launcher3.config.FeatureFlags;
|
|||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutsContainer;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
|
||||
|
@ -178,18 +179,13 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
}
|
||||
|
||||
public boolean isEventOverPageIndicator(MotionEvent ev) {
|
||||
getDescendantRectRelativeToSelf(mLauncher.getWorkspace().getPageIndicator(), mHitRect);
|
||||
return mHitRect.contains((int) ev.getX(), (int) ev.getY());
|
||||
return isEventOverView(mLauncher.getWorkspace().getPageIndicator(), ev);
|
||||
}
|
||||
|
||||
public boolean isEventOverHotseat(MotionEvent ev) {
|
||||
return isEventOverView(mLauncher.getHotseat(), ev);
|
||||
}
|
||||
|
||||
private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
|
||||
return isEventOverView(folder.getEditTextRegion(), ev);
|
||||
}
|
||||
|
||||
private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
|
||||
return isEventOverView(folder, ev);
|
||||
}
|
||||
|
@ -204,45 +200,27 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
}
|
||||
|
||||
private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
|
||||
// Remove the shortcuts container when touching outside of it.
|
||||
DeepShortcutsContainer deepShortcutsContainer = mLauncher.getOpenShortcutsContainer();
|
||||
if (deepShortcutsContainer != null) {
|
||||
if (isEventOverView(deepShortcutsContainer, ev)) {
|
||||
// Let the container handle the event.
|
||||
return false;
|
||||
} else {
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topView != null && intercept) {
|
||||
ExtendedEditText textView = topView.getActiveTextView();
|
||||
if (textView != null) {
|
||||
if (!isEventOverView(textView, ev)) {
|
||||
textView.dispatchBackKey();
|
||||
return true;
|
||||
}
|
||||
} else if (!isEventOverView(topView, ev)) {
|
||||
if (isInAccessibleDrag()) {
|
||||
// Do not close the container if in drag and drop.
|
||||
if (!isEventOverDropTargetBar(ev)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
mLauncher.closeShortcutsContainer();
|
||||
topView.close(true);
|
||||
|
||||
// We let touches on the original icon go through so that users can launch
|
||||
// the app with one tap if they don't find a shortcut they want.
|
||||
return !isEventOverView(deepShortcutsContainer.getOriginalIcon(), ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
|
||||
if (currentFolder != null && intercept) {
|
||||
if (currentFolder.isEditingName()) {
|
||||
if (!isEventOverFolderTextRegion(currentFolder, ev)) {
|
||||
currentFolder.dismissEditingName();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEventOverFolder(currentFolder, ev)) {
|
||||
if (isInAccessibleDrag()) {
|
||||
// Do not close the folder if in drag and drop.
|
||||
if (!isEventOverDropTargetBar(ev)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
mLauncher.closeFolder();
|
||||
return true;
|
||||
View extendedTouch = topView.getExtendedTouchView();
|
||||
return extendedTouch == null || !isEventOverView(extendedTouch, ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -300,7 +278,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
if (mLauncher == null || mLauncher.getWorkspace() == null) {
|
||||
return false;
|
||||
}
|
||||
Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
|
||||
Folder currentFolder = Folder.getOpen(mLauncher);
|
||||
if (currentFolder == null) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -350,7 +328,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
@Override
|
||||
public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
|
||||
// Shortcuts can appear above folder
|
||||
View topView = mLauncher.getTopFloatingView();
|
||||
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topView != null) {
|
||||
if (child == topView) {
|
||||
return super.onRequestSendAccessibilityEvent(child, event);
|
||||
|
@ -367,7 +345,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
|
||||
@Override
|
||||
public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
|
||||
View topView = mLauncher.getTopFloatingView();
|
||||
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topView != null) {
|
||||
// Only add the top view as a child for accessibility when it is open
|
||||
childrenForAccessibility.add(topView);
|
||||
|
@ -522,7 +500,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
@Override
|
||||
public boolean dispatchUnhandledMove(View focused, int direction) {
|
||||
// Consume the unhandled move if a container is open, to avoid switching pages underneath.
|
||||
boolean isContainerOpen = mLauncher.getTopFloatingView() != null;
|
||||
boolean isContainerOpen = AbstractFloatingView.getTopOpenView(mLauncher) != null;
|
||||
return isContainerOpen || mDragController.dispatchUnhandledMove(focused, direction);
|
||||
}
|
||||
|
||||
|
@ -1031,7 +1009,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
|
||||
@Override
|
||||
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
|
||||
View topView = mLauncher.getTopFloatingView();
|
||||
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topView != null) {
|
||||
return topView.requestFocus(direction, previouslyFocusedRect);
|
||||
} else {
|
||||
|
@ -1041,7 +1019,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
|
||||
@Override
|
||||
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
|
||||
View topView = mLauncher.getTopFloatingView();
|
||||
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topView != null) {
|
||||
topView.addFocusables(views, direction);
|
||||
} else {
|
||||
|
|
|
@ -46,9 +46,9 @@ import android.view.animation.AccelerateInterpolator;
|
|||
import android.view.animation.AnimationUtils;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Alarm;
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
|
@ -73,6 +73,7 @@ import com.android.launcher3.Utilities;
|
|||
import com.android.launcher3.Workspace.ItemOperator;
|
||||
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.config.ProviderConfig;
|
||||
import com.android.launcher3.dragndrop.DragController;
|
||||
import com.android.launcher3.dragndrop.DragController.DragListener;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
|
@ -91,9 +92,10 @@ import java.util.Comparator;
|
|||
/**
|
||||
* Represents a set of icons chosen by the user or generated by the system.
|
||||
*/
|
||||
public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
|
||||
public class Folder extends AbstractFloatingView implements DragSource, View.OnClickListener,
|
||||
View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
|
||||
View.OnFocusChangeListener, DragListener, DropTargetSource {
|
||||
View.OnFocusChangeListener, DragListener, DropTargetSource,
|
||||
ExtendedEditText.OnBackKeyListener {
|
||||
private static final String TAG = "Launcher.Folder";
|
||||
|
||||
/**
|
||||
|
@ -227,14 +229,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
|
||||
mPageIndicator = (PageIndicatorDots) findViewById(R.id.folder_page_indicator);
|
||||
mFolderName = (ExtendedEditText) findViewById(R.id.folder_name);
|
||||
mFolderName.setOnBackKeyListener(new ExtendedEditText.OnBackKeyListener() {
|
||||
@Override
|
||||
public boolean onBackKey() {
|
||||
// Close the activity on back key press
|
||||
doneEditingFolderName(true);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
mFolderName.setOnBackKeyListener(this);
|
||||
mFolderName.setOnFocusChangeListener(this);
|
||||
|
||||
if (!Utilities.ATLEAST_MARSHMALLOW) {
|
||||
|
@ -357,12 +352,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
});
|
||||
}
|
||||
|
||||
public void dismissEditingName() {
|
||||
mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
doneEditingFolderName(true);
|
||||
}
|
||||
|
||||
public void doneEditingFolderName(boolean commit) {
|
||||
@Override
|
||||
public boolean onBackKey() {
|
||||
mFolderName.setHint(sHintText);
|
||||
// Convert to a string here to ensure that no other state associated with the text field
|
||||
// gets saved.
|
||||
|
@ -370,30 +362,30 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
mInfo.setTitle(newTitle);
|
||||
LauncherModel.updateItemInDatabase(mLauncher, mInfo);
|
||||
|
||||
if (commit) {
|
||||
Utilities.sendCustomAccessibilityEvent(
|
||||
this, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
|
||||
getContext().getString(R.string.folder_renamed, newTitle));
|
||||
}
|
||||
Utilities.sendCustomAccessibilityEvent(
|
||||
this, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
|
||||
getContext().getString(R.string.folder_renamed, newTitle));
|
||||
|
||||
// This ensures that focus is gained every time the field is clicked, which selects all
|
||||
// the text and brings up the soft keyboard if necessary.
|
||||
mFolderName.clearFocus();
|
||||
|
||||
Selection.setSelection((Spannable) mFolderName.getText(), 0, 0);
|
||||
Selection.setSelection(mFolderName.getText(), 0, 0);
|
||||
mIsEditingName = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
dismissEditingName();
|
||||
mFolderName.dispatchBackKey();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public View getEditTextRegion() {
|
||||
return mFolderName;
|
||||
@Override
|
||||
public ExtendedEditText getActiveTextView() {
|
||||
return isEditingName() ? mFolderName : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -518,8 +510,33 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
mState = STATE_SMALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void animateOpen() {
|
||||
if (!(getParent() instanceof DragLayer)) return;
|
||||
Folder openFolder = getOpen(mLauncher);
|
||||
if (openFolder != null && openFolder != this) {
|
||||
// Close any open folder before opening a folder.
|
||||
openFolder.close(true);
|
||||
}
|
||||
|
||||
DragLayer dragLayer = mLauncher.getDragLayer();
|
||||
// Just verify that the folder hasn't already been added to the DragLayer.
|
||||
// There was a one-off crash where the folder had a parent already.
|
||||
if (getParent() == null) {
|
||||
dragLayer.addView(this);
|
||||
mDragController.addDropTarget(this);
|
||||
} else {
|
||||
if (ProviderConfig.IS_DOGFOOD_BUILD) {
|
||||
Log.e(TAG, "Opening folder (" + this + ") which already has a parent:"
|
||||
+ getParent());
|
||||
}
|
||||
}
|
||||
|
||||
mIsOpen = true;
|
||||
mFolderIcon.growAndFadeOut();
|
||||
|
||||
mContent.completePendingPageChanges();
|
||||
if (!mDragInProgress) {
|
||||
|
@ -532,83 +549,63 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
// dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice.
|
||||
mDeleteFolderOnDropCompleted = false;
|
||||
|
||||
Animator openFolderAnim = null;
|
||||
final Runnable onCompleteRunnable;
|
||||
if (!Utilities.ATLEAST_LOLLIPOP) {
|
||||
positionAndSizeAsIcon();
|
||||
centerAboutIcon();
|
||||
prepareReveal();
|
||||
centerAboutIcon();
|
||||
|
||||
final ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(this, 1, 1, 1);
|
||||
oa.setDuration(mExpandDuration);
|
||||
openFolderAnim = oa;
|
||||
AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
|
||||
int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
|
||||
int height = getFolderHeight();
|
||||
|
||||
setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
onCompleteRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setLayerType(LAYER_TYPE_NONE, null);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
prepareReveal();
|
||||
centerAboutIcon();
|
||||
float transX = - 0.075f * (width / 2 - getPivotX());
|
||||
float transY = - 0.075f * (height / 2 - getPivotY());
|
||||
setTranslationX(transX);
|
||||
setTranslationY(transY);
|
||||
PropertyValuesHolder tx = PropertyValuesHolder.ofFloat(TRANSLATION_X, transX, 0);
|
||||
PropertyValuesHolder ty = PropertyValuesHolder.ofFloat(TRANSLATION_Y, transY, 0);
|
||||
|
||||
AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
|
||||
int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
|
||||
int height = getFolderHeight();
|
||||
Animator drift = ObjectAnimator.ofPropertyValuesHolder(this, tx, ty);
|
||||
drift.setDuration(mMaterialExpandDuration);
|
||||
drift.setStartDelay(mMaterialExpandStagger);
|
||||
drift.setInterpolator(new LogDecelerateInterpolator(100, 0));
|
||||
|
||||
float transX = - 0.075f * (width / 2 - getPivotX());
|
||||
float transY = - 0.075f * (height / 2 - getPivotY());
|
||||
setTranslationX(transX);
|
||||
setTranslationY(transY);
|
||||
PropertyValuesHolder tx = PropertyValuesHolder.ofFloat(TRANSLATION_X, transX, 0);
|
||||
PropertyValuesHolder ty = PropertyValuesHolder.ofFloat(TRANSLATION_Y, transY, 0);
|
||||
int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX());
|
||||
int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY());
|
||||
float radius = (float) Math.hypot(rx, ry);
|
||||
|
||||
Animator drift = ObjectAnimator.ofPropertyValuesHolder(this, tx, ty);
|
||||
drift.setDuration(mMaterialExpandDuration);
|
||||
drift.setStartDelay(mMaterialExpandStagger);
|
||||
drift.setInterpolator(new LogDecelerateInterpolator(100, 0));
|
||||
Animator reveal = new CircleRevealOutlineProvider((int) getPivotX(),
|
||||
(int) getPivotY(), 0, radius).createRevealAnimator(this);
|
||||
reveal.setDuration(mMaterialExpandDuration);
|
||||
reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
|
||||
|
||||
int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX());
|
||||
int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY());
|
||||
float radius = (float) Math.hypot(rx, ry);
|
||||
mContent.setAlpha(0f);
|
||||
Animator iconsAlpha = ObjectAnimator.ofFloat(mContent, "alpha", 0f, 1f);
|
||||
iconsAlpha.setDuration(mMaterialExpandDuration);
|
||||
iconsAlpha.setStartDelay(mMaterialExpandStagger);
|
||||
iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
|
||||
|
||||
Animator reveal = new CircleRevealOutlineProvider((int) getPivotX(),
|
||||
(int) getPivotY(), 0, radius).createRevealAnimator(this);
|
||||
reveal.setDuration(mMaterialExpandDuration);
|
||||
reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
|
||||
mFooter.setAlpha(0f);
|
||||
Animator textAlpha = ObjectAnimator.ofFloat(mFooter, "alpha", 0f, 1f);
|
||||
textAlpha.setDuration(mMaterialExpandDuration);
|
||||
textAlpha.setStartDelay(mMaterialExpandStagger);
|
||||
textAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
|
||||
|
||||
mContent.setAlpha(0f);
|
||||
Animator iconsAlpha = ObjectAnimator.ofFloat(mContent, "alpha", 0f, 1f);
|
||||
iconsAlpha.setDuration(mMaterialExpandDuration);
|
||||
iconsAlpha.setStartDelay(mMaterialExpandStagger);
|
||||
iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
|
||||
anim.play(drift);
|
||||
anim.play(iconsAlpha);
|
||||
anim.play(textAlpha);
|
||||
anim.play(reveal);
|
||||
|
||||
mFooter.setAlpha(0f);
|
||||
Animator textAlpha = ObjectAnimator.ofFloat(mFooter, "alpha", 0f, 1f);
|
||||
textAlpha.setDuration(mMaterialExpandDuration);
|
||||
textAlpha.setStartDelay(mMaterialExpandStagger);
|
||||
textAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
|
||||
|
||||
anim.play(drift);
|
||||
anim.play(iconsAlpha);
|
||||
anim.play(textAlpha);
|
||||
anim.play(reveal);
|
||||
|
||||
openFolderAnim = anim;
|
||||
|
||||
mContent.setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
mFooter.setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
onCompleteRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mContent.setLayerType(LAYER_TYPE_NONE, null);
|
||||
mFooter.setLayerType(LAYER_TYPE_NONE, null);
|
||||
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
|
||||
}
|
||||
};
|
||||
}
|
||||
openFolderAnim.addListener(new AnimatorListenerAdapter() {
|
||||
mContent.setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
mFooter.setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
onCompleteRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mContent.setLayerType(LAYER_TYPE_NONE, null);
|
||||
mFooter.setLayerType(LAYER_TYPE_NONE, null);
|
||||
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
|
||||
}
|
||||
};
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
Utilities.sendCustomAccessibilityEvent(
|
||||
|
@ -639,7 +636,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
// Do not update the flag if we are in drag mode. The flag will be updated, when we
|
||||
// actually drop the icon.
|
||||
final boolean updateAnimationFlag = !mDragInProgress;
|
||||
openFolderAnim.addListener(new AnimatorListenerAdapter() {
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
@Override
|
||||
|
@ -662,7 +659,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
}
|
||||
|
||||
mPageIndicator.stopAllAnimations();
|
||||
openFolderAnim.start();
|
||||
anim.start();
|
||||
|
||||
// Make sure the folder picks up the last drag move even if the finger doesn't move.
|
||||
if (mDragController.isDragging()) {
|
||||
|
@ -670,6 +667,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
}
|
||||
|
||||
mContent.verifyVisibleHighResIcons(mContent.getNextPage());
|
||||
|
||||
// Notify the accessibility manager that this folder "window" has appeared and occluded
|
||||
// the workspace items
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
dragLayer.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
||||
}
|
||||
|
||||
public void beginExternalDrag() {
|
||||
|
@ -682,14 +684,44 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
mDragController.addDragListener(this);
|
||||
}
|
||||
|
||||
public void animateClosed() {
|
||||
@Override
|
||||
protected boolean isOfType(int type) {
|
||||
return (type & TYPE_FOLDER) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleClose(boolean animate) {
|
||||
mIsOpen = false;
|
||||
|
||||
if (isEditingName()) {
|
||||
mFolderName.dispatchBackKey();
|
||||
}
|
||||
|
||||
if (mFolderIcon != null) {
|
||||
mFolderIcon.shrinkAndFadeIn(animate);
|
||||
}
|
||||
|
||||
if (!(getParent() instanceof DragLayer)) return;
|
||||
|
||||
if (animate) {
|
||||
animateClosed();
|
||||
} else {
|
||||
closeComplete(false);
|
||||
}
|
||||
|
||||
// Notify the accessibility manager that this folder "window" has disappeared and no
|
||||
// longer occludes the workspace items
|
||||
((DragLayer) getParent())
|
||||
.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
}
|
||||
|
||||
private void animateClosed() {
|
||||
final ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(this, 0, 0.9f, 0.9f);
|
||||
oa.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
setLayerType(LAYER_TYPE_NONE, null);
|
||||
close(true);
|
||||
closeComplete(true);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
|
@ -705,7 +737,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
oa.start();
|
||||
}
|
||||
|
||||
public void close(boolean wasAnimated) {
|
||||
private void closeComplete(boolean wasAnimated) {
|
||||
// TODO: Clear all active animations.
|
||||
DragLayer parent = (DragLayer) getParent();
|
||||
if (parent != null) {
|
||||
|
@ -840,8 +872,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
};
|
||||
|
||||
public void completeDragExit() {
|
||||
if (mInfo.opened) {
|
||||
mLauncher.closeFolder();
|
||||
if (mIsOpen) {
|
||||
close(true);
|
||||
mRearrangeOnClose = true;
|
||||
} else if (mState == STATE_ANIMATING) {
|
||||
mRearrangeOnClose = true;
|
||||
|
@ -1370,8 +1402,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
rearrangeChildren();
|
||||
}
|
||||
if (getItemCount() <= 1) {
|
||||
if (mInfo.opened) {
|
||||
mLauncher.closeFolder(this, true);
|
||||
if (mIsOpen) {
|
||||
close(true);
|
||||
} else {
|
||||
replaceFolderWithFinalItem();
|
||||
}
|
||||
|
@ -1417,7 +1449,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
if (hasFocus) {
|
||||
startEditingFolderName();
|
||||
} else {
|
||||
dismissEditingName();
|
||||
mFolderName.dispatchBackKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1516,4 +1548,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||
updateTextViewFocus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a folder which is already open or null
|
||||
*/
|
||||
public static Folder getOpen(Launcher launcher) {
|
||||
return getOpenView(launcher, TYPE_FOLDER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.launcher3.folder;
|
|||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
import android.content.Context;
|
||||
|
@ -56,7 +57,6 @@ import com.android.launcher3.IconCache;
|
|||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAnimUtils;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.OnAlarmListener;
|
||||
import com.android.launcher3.PreloadIconDrawable;
|
||||
|
@ -142,6 +142,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
mPreviewLayoutRule = FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON ?
|
||||
new StackFolderIconLayoutRule() :
|
||||
new ClippedFolderIconLayoutRule();
|
||||
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
}
|
||||
|
||||
public static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
|
||||
|
@ -202,16 +203,12 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
updateItemDrawingParams(false);
|
||||
}
|
||||
|
||||
public FolderInfo getFolderInfo() {
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
private boolean willAcceptItem(ItemInfo item) {
|
||||
final int itemType = item.itemType;
|
||||
return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
|
||||
itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
|
||||
itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) &&
|
||||
!mFolder.isFull() && item != mInfo && !mInfo.opened);
|
||||
!mFolder.isFull() && item != mInfo && !mFolder.isOpen());
|
||||
}
|
||||
|
||||
public boolean acceptDrop(ItemInfo dragInfo) {
|
||||
|
@ -243,7 +240,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
OnAlarmListener mOnOpenListener = new OnAlarmListener() {
|
||||
public void onAlarm(Alarm alarm) {
|
||||
mFolder.beginExternalDrag();
|
||||
mLauncher.openFolder(FolderIcon.this);
|
||||
mFolder.animateOpen();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -973,12 +970,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelLongPress() {
|
||||
super.cancelLongPress();
|
||||
|
@ -990,13 +981,76 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
mInfo.removeListener(mFolder);
|
||||
}
|
||||
|
||||
public void shrinkAndFadeIn(boolean animate) {
|
||||
final CellLayout cl = (CellLayout) getParent().getParent();
|
||||
((CellLayout.LayoutParams) getLayoutParams()).canReorder = true;
|
||||
|
||||
// We remove and re-draw the FolderIcon in-case it has changed
|
||||
final PreviewImageView previewImage = PreviewImageView.get(getContext());
|
||||
previewImage.removeFromParent();
|
||||
copyToPreview(previewImage);
|
||||
|
||||
if (cl != null) {
|
||||
cl.clearFolderLeaveBehind();
|
||||
}
|
||||
|
||||
ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(previewImage, 1, 1, 1);
|
||||
oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
|
||||
oa.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (cl != null) {
|
||||
// Remove the ImageView copy of the FolderIcon and make the original visible.
|
||||
previewImage.removeFromParent();
|
||||
setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
oa.start();
|
||||
if (!animate) {
|
||||
oa.end();
|
||||
}
|
||||
}
|
||||
|
||||
public void growAndFadeOut() {
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
|
||||
// While the folder is open, the position of the icon cannot change.
|
||||
lp.canReorder = false;
|
||||
if (mInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
|
||||
CellLayout cl = (CellLayout) getParent().getParent();
|
||||
cl.setFolderLeaveBehindCell(lp.cellX, lp.cellY);
|
||||
}
|
||||
|
||||
// Push an ImageView copy of the FolderIcon into the DragLayer and hide the original
|
||||
PreviewImageView previewImage = PreviewImageView.get(getContext());
|
||||
copyToPreview(previewImage);
|
||||
setVisibility(View.INVISIBLE);
|
||||
|
||||
ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(previewImage, 0, 1.5f, 1.5f);
|
||||
oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
|
||||
oa.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method draws the FolderIcon to an ImageView and then adds and positions that ImageView
|
||||
* in the DragLayer in the exact absolute location of the original FolderIcon.
|
||||
*/
|
||||
private void copyToPreview(PreviewImageView previewImageView) {
|
||||
previewImageView.copy(this);
|
||||
if (mFolder != null) {
|
||||
previewImageView.setPivotX(mFolder.getPivotXForIconAnimation());
|
||||
previewImageView.setPivotY(mFolder.getPivotYForIconAnimation());
|
||||
mFolder.bringToFront();
|
||||
}
|
||||
}
|
||||
|
||||
public interface PreviewLayoutRule {
|
||||
public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
|
||||
PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
|
||||
PreviewItemDrawingParams params);
|
||||
|
||||
public void init(int availableSpace, int intrinsicIconSize, boolean rtl);
|
||||
void init(int availableSpace, int intrinsicIconSize, boolean rtl);
|
||||
|
||||
public int numItems();
|
||||
public boolean clipToBackground();
|
||||
int numItems();
|
||||
boolean clipToBackground();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.folder;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
|
||||
/**
|
||||
* A temporary view which displays the a bitmap (used for folder icon animation)
|
||||
*/
|
||||
public class PreviewImageView extends ImageView {
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final DragLayer mParent;
|
||||
|
||||
private Bitmap mBitmap;
|
||||
private Canvas mCanvas;
|
||||
|
||||
public PreviewImageView(DragLayer parent) {
|
||||
super(parent.getContext());
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
public void copy(View view) {
|
||||
final int width = view.getMeasuredWidth();
|
||||
final int height = view.getMeasuredHeight();
|
||||
|
||||
if (mBitmap == null || mBitmap.getWidth() != width || mBitmap.getHeight() != height) {
|
||||
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
mCanvas = new Canvas(mBitmap);
|
||||
}
|
||||
|
||||
DragLayer.LayoutParams lp;
|
||||
if (getLayoutParams() instanceof DragLayer.LayoutParams) {
|
||||
lp = (DragLayer.LayoutParams) getLayoutParams();
|
||||
} else {
|
||||
lp = new DragLayer.LayoutParams(width, height);
|
||||
}
|
||||
|
||||
// The layout from which the folder is being opened may be scaled, adjust the starting
|
||||
// view size by this scale factor.
|
||||
float scale = mParent.getDescendantRectRelativeToSelf(view, mTempRect);
|
||||
lp.customPosition = true;
|
||||
lp.x = mTempRect.left;
|
||||
lp.y = mTempRect.top;
|
||||
lp.width = (int) (scale * width);
|
||||
lp.height = (int) (scale * height);
|
||||
|
||||
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
view.draw(mCanvas);
|
||||
setImageBitmap(mBitmap);
|
||||
|
||||
// Just in case this image view is still in the drag layer from a previous animation,
|
||||
// we remove it and re-add it.
|
||||
removeFromParent();
|
||||
mParent.addView(this, lp);
|
||||
}
|
||||
|
||||
public void removeFromParent() {
|
||||
if (mParent.indexOfChild(this) != -1) {
|
||||
mParent.removeView(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static PreviewImageView get(Context context) {
|
||||
DragLayer dragLayer = Launcher.getLauncher(context).getDragLayer();
|
||||
PreviewImageView view = (PreviewImageView) dragLayer.getTag(R.id.preview_image_id);
|
||||
if (view == null) {
|
||||
view = new PreviewImageView(dragLayer);
|
||||
dragLayer.setTag(R.id.preview_image_id, view);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@ public class CustomActionsPopup implements OnMenuItemClickListener {
|
|||
public CustomActionsPopup(Launcher launcher, View icon) {
|
||||
mLauncher = launcher;
|
||||
mIcon = icon;
|
||||
DeepShortcutsContainer container = launcher.getOpenShortcutsContainer();
|
||||
DeepShortcutsContainer container = DeepShortcutsContainer.getOpen(launcher);
|
||||
if (container != null) {
|
||||
mDelegate = container.getAccessibilityDelegate();
|
||||
} else {
|
||||
|
|
|
@ -41,6 +41,7 @@ import android.view.accessibility.AccessibilityEvent;
|
|||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.DragSource;
|
||||
import com.android.launcher3.DropTarget;
|
||||
|
@ -73,9 +74,9 @@ import java.util.List;
|
|||
* A container for shortcuts to deep links within apps.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public class DeepShortcutsContainer extends LinearLayout implements View.OnLongClickListener,
|
||||
public class DeepShortcutsContainer extends AbstractFloatingView
|
||||
implements View.OnLongClickListener,
|
||||
View.OnTouchListener, DragSource, DragController.DragListener {
|
||||
private static final String TAG = "ShortcutsContainer";
|
||||
|
||||
private final Point mIconShift = new Point();
|
||||
|
||||
|
@ -94,7 +95,6 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
|
||||
private Animator mOpenCloseAnimator;
|
||||
private boolean mDeferContainerRemoval;
|
||||
private boolean mIsOpen;
|
||||
|
||||
public DeepShortcutsContainer(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
@ -376,7 +376,8 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
return arrowView;
|
||||
}
|
||||
|
||||
public BubbleTextView getOriginalIcon() {
|
||||
@Override
|
||||
public View getExtendedTouchView() {
|
||||
return mOriginalIcon;
|
||||
}
|
||||
|
||||
|
@ -444,7 +445,7 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
dv.animateShift(-mIconShift.x, -mIconShift.y);
|
||||
|
||||
// TODO: support dragging from within folder without having to close it
|
||||
mLauncher.closeFolder();
|
||||
AbstractFloatingView.closeOpenContainer(mLauncher, AbstractFloatingView.TYPE_FOLDER);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -499,7 +500,7 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
} else {
|
||||
// Close animation is not running.
|
||||
if (mDeferContainerRemoval) {
|
||||
close();
|
||||
closeComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -512,7 +513,16 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
targetParent.containerType = LauncherLogProto.DEEPSHORTCUTS;
|
||||
}
|
||||
|
||||
public void animateClose() {
|
||||
@Override
|
||||
protected void handleClose(boolean animate) {
|
||||
if (animate) {
|
||||
animateClose();
|
||||
} else {
|
||||
closeComplete();
|
||||
}
|
||||
}
|
||||
|
||||
private void animateClose() {
|
||||
if (!mIsOpen) {
|
||||
return;
|
||||
}
|
||||
|
@ -592,7 +602,7 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
if (mDeferContainerRemoval) {
|
||||
setVisibility(INVISIBLE);
|
||||
} else {
|
||||
close();
|
||||
closeComplete();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -607,7 +617,7 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
/**
|
||||
* Closes the folder without animation.
|
||||
*/
|
||||
public void close() {
|
||||
private void closeComplete() {
|
||||
if (mOpenCloseAnimator != null) {
|
||||
mOpenCloseAnimator.cancel();
|
||||
mOpenCloseAnimator = null;
|
||||
|
@ -621,8 +631,9 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
mLauncher.getDragLayer().removeView(this);
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return mIsOpen;
|
||||
@Override
|
||||
protected boolean isOfType(int type) {
|
||||
return (type & TYPE_DEEPSHORTCUT_CONTAINER) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -631,7 +642,7 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
*/
|
||||
public static DeepShortcutsContainer showForIcon(BubbleTextView icon) {
|
||||
Launcher launcher = Launcher.getLauncher(icon.getContext());
|
||||
if (launcher.getOpenShortcutsContainer() != null) {
|
||||
if (getOpen(launcher) != null) {
|
||||
// There is already a shortcuts container open, so don't open this one.
|
||||
icon.clearFocus();
|
||||
return null;
|
||||
|
@ -666,4 +677,11 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
|
|||
return unbadgedBitmap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a DeepShortcutsContainer which is already open or null
|
||||
*/
|
||||
public static DeepShortcutsContainer getOpen(Launcher launcher) {
|
||||
return getOpenView(launcher, TYPE_DEEPSHORTCUT_CONTAINER);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue