summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
authorVineet Patil <vpatil@cyngn.com>2015-11-17 14:23:05 -0800
committerTom Powell <zifnab@zifnab06.net>2017-03-26 15:52:40 -0700
commit9090182042fc599a6dbb81b71406cbc7f877dfa0 (patch)
tree579359e3a10e2dc474742de0a69e0b17330f8af5 /src/com/android
parentf630789246e5782b05d5f4035d72ffe256e7abae (diff)
downloadandroid_packages_apps_Trebuchet-9090182042fc599a6dbb81b71406cbc7f877dfa0.tar.gz
android_packages_apps_Trebuchet-9090182042fc599a6dbb81b71406cbc7f877dfa0.tar.bz2
android_packages_apps_Trebuchet-9090182042fc599a6dbb81b71406cbc7f877dfa0.zip
Implementation of folder animation changes as per cm-13.0
Folder animations in parity with cm. Folder Layout Revision Updated the folder layout to reflect design revisions based on community feedback Change-Id: Ica1bb796dfccf779a954cf0903a1ae94a010ea1a Conflicts: res/drawable-hdpi/folder_bg.9.png res/drawable-hdpi/folder_fill_highlight.9.png res/drawable-mdpi/folder_bg.9.png res/drawable-mdpi/folder_fill_highlight.9.png res/drawable-xhdpi/folder_bg.9.png res/drawable-xhdpi/folder_fill_highlight.9.png res/drawable-xxhdpi/folder_bg.9.png res/drawable-xxhdpi/folder_fill_highlight.9.png res/layout-land/launcher.xml res/layout-port/launcher.xml res/layout-sw720dp/launcher.xml res/layout/user_folder.xml res/values/dimens.xml src/com/android/launcher3/Folder.java src/com/android/launcher3/FolderIcon.java src/com/android/launcher3/Launcher.java Folder animation changes as per cm-13.0 Change-Id: I019511a58bd9f6a60a3c9b68c826726881cec83f Implementing folder animations Change-Id: I83f17c996ecc894ce22fd195b9b33caf58e2e822
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/launcher3/CellLayout.java16
-rw-r--r--src/com/android/launcher3/Folder.java231
-rw-r--r--src/com/android/launcher3/FolderIcon.java142
-rw-r--r--src/com/android/launcher3/FolderInfo.java1
-rw-r--r--src/com/android/launcher3/InsettableFrameLayout.java14
-rw-r--r--src/com/android/launcher3/Launcher.java69
-rw-r--r--src/com/android/launcher3/LauncherSettings.java2
7 files changed, 397 insertions, 78 deletions
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 84e2d49c2..a99d791bd 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -504,13 +504,15 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
// Draw inner ring
d = FolderRingAnimator.sSharedInnerRingDrawable;
- width = (int) (fra.getInnerRingSize() * getChildrenScale());
- height = width;
- canvas.save();
- canvas.translate(centerX - width / 2, centerY - width / 2);
- d.setBounds(0, 0, width, height);
- d.draw(canvas);
- canvas.restore();
+ if (d != null) {
+ width = (int) (fra.getInnerRingSize() * getChildrenScale());
+ height = width;
+ canvas.save();
+ canvas.translate(centerX - width / 2, centerY - width / 2);
+ d.setBounds(0, 0, width, height);
+ d.draw(canvas);
+ canvas.restore();
+ }
}
}
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index c1aa35669..994d7d30d 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -25,11 +25,15 @@ import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
+import android.os.PowerManager;
+import android.provider.Settings;
import android.text.InputType;
import android.text.Selection;
import android.text.Spannable;
@@ -46,8 +50,10 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -89,6 +95,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
*/
public static final int SCROLL_HINT_DURATION = DragController.SCROLL_DELAY;
+ private static final int CLOSE_FOLDER_DELAY_MS = 150;
+
+ private static final int ALPHA_DELAY_MULT = 15;
+
/**
* Fraction of icon width which behave as scroll region.
*/
@@ -96,6 +106,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private static final int FOLDER_NAME_ANIMATION_DURATION = 633;
+ private static final int REORDER_ANIMATION_DURATION = 230;
private static final int REORDER_DELAY = 250;
private static final int ON_EXIT_CLOSE_DELAY = 400;
private static final Rect sTempRect = new Rect();
@@ -116,6 +127,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private final InputMethodManager mInputMethodManager;
+ private final PowerManager mPowerManager;
+
protected final Launcher mLauncher;
protected DragController mDragController;
protected FolderInfo mInfo;
@@ -171,6 +184,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mInputMethodManager = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
Resources res = getResources();
mExpandDuration = res.getInteger(R.integer.config_folderExpandDuration);
mMaterialExpandDuration = res.getInteger(R.integer.config_materialFolderExpandDuration);
@@ -440,9 +455,41 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
setScaleY(1f);
setAlpha(1f);
mState = STATE_SMALL;
+
+ View reveal = mLauncher.findViewById(R.id.reveal_fake_page_container);
+ reveal.setVisibility(View.VISIBLE);
+ View revealFolderIcon = mLauncher.findViewById(R.id.reveal_fake_folder_icon);
+ revealFolderIcon.setVisibility(View.INVISIBLE);
+ }
+
+ private void prepareFakeFolderIcon() {
+ mFolderIcon.buildDrawingCache(true);
+
+ Bitmap fakeFolderIcon = Bitmap.createBitmap(mFolderIcon.getDrawingCache());
+ View fakeFolderIconView = mLauncher.findViewById(R.id.reveal_fake_folder_icon);
+ FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams)
+ fakeFolderIconView.getLayoutParams();
+
+ // Get globalVisibleRect of the folderIcon. getWidth and getHeight are inaccurate for
+ // hotseat icons
+ Rect rect = new Rect();
+ mFolderIcon.getGlobalVisibleRect(rect);
+
+ flp.height = rect.height();
+ flp.width = rect.width();
+
+ fakeFolderIconView.setLayoutParams(flp);
+
+ int [] folderIconXY = new int[2];
+ mFolderIcon.getLocationOnScreen(folderIconXY);
+ fakeFolderIconView.setX(folderIconXY[0]);
+ fakeFolderIconView.setY(folderIconXY[1]);
+
+ fakeFolderIconView.setBackground(new BitmapDrawable(null, fakeFolderIcon));
+ fakeFolderIconView.setVisibility(View.INVISIBLE);
}
- public void animateOpen() {
+ public void animateOpen(Workspace workspace, int[] folderTouch) {
if (!(getParent() instanceof DragLayer)) return;
mContent.completePendingPageChanges();
@@ -473,7 +520,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
};
} else {
- prepareReveal();
centerAboutIcon();
AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
@@ -490,7 +536,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
Animator drift = ObjectAnimator.ofPropertyValuesHolder(this, tx, ty);
drift.setDuration(mMaterialExpandDuration);
drift.setStartDelay(mMaterialExpandStagger);
- drift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+ drift.setInterpolator(new LogDecelerateInterpolator(60, 0));
int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX());
int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY());
@@ -513,6 +559,34 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
textAlpha.setStartDelay(mMaterialExpandStagger);
textAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
+ prepareFakeFolderIcon();
+ float iconTransY = getResources().getInteger(R.integer.folder_icon_translate_y_dist);
+
+ final View fakeFolderIconView = mLauncher.findViewById(R.id.reveal_fake_folder_icon);
+ float baseIconTranslationY = fakeFolderIconView.getTranslationY();
+ PropertyValuesHolder iconty = PropertyValuesHolder.ofFloat("translationY",
+ baseIconTranslationY, baseIconTranslationY + iconTransY);
+ PropertyValuesHolder iconAlpha = PropertyValuesHolder.ofFloat("alpha", 1f, 0f);
+
+ Animator fakeFolderIcon = LauncherAnimUtils.ofPropertyValuesHolder(fakeFolderIconView,
+ iconty, iconAlpha);
+ fakeFolderIcon.setDuration(mMaterialExpandDuration);
+ fakeFolderIcon.setInterpolator(new AccelerateInterpolator(1.5f));
+ fakeFolderIcon.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mFolderIcon.setAlpha(0);
+ fakeFolderIconView.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ fakeFolderIconView.setVisibility(View.INVISIBLE);
+ }
+ });
+
+ prepareReveal();
+
anim.play(drift);
anim.play(iconsAlpha);
anim.play(textAlpha);
@@ -526,7 +600,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
@Override
public void run() {
mContentWrapper.setLayerType(LAYER_TYPE_NONE, null);
- mContentWrapper.setLayerType(LAYER_TYPE_NONE, null);
}
};
}
@@ -535,6 +608,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public void onAnimationStart(Animator animation) {
sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
mContent.getAccessibilityDescription());
+ hideWorkspace();
mState = STATE_ANIMATING;
}
@Override
@@ -628,31 +702,120 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
}
- public void animateClosed() {
+ public int getState() {
+ return mState;
+ }
+
+ public void animateClosed(final boolean animate) {
if (!(getParent() instanceof DragLayer)) return;
- PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
- PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
- PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
- final ObjectAnimator oa =
- LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+ AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
- oa.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- onCloseComplete();
- setLayerType(LAYER_TYPE_NONE, null);
- mState = STATE_SMALL;
- }
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
+ float transY = getResources().getInteger(R.integer.folder_translate_y_dist);
+ PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", 0f,
+ transY);
+
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+
+ float animatorDurationScale = Settings.Global.getFloat(getContext().getContentResolver(),
+ Settings.Global.ANIMATOR_DURATION_SCALE, 1);
+ ObjectAnimator oa;
+ if (mPowerManager.isPowerSaveMode() || animatorDurationScale < 0.01f) {
+ // power save mode is no fun - skip alpha animation and just set it to 0
+ // otherwise the icons will stay around until the duration of the animation
+ oa = LauncherAnimUtils.ofPropertyValuesHolder(this, translationY);
+ setAlpha(0f);
+ } else {
+ oa = LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, translationY);
+ }
+
+ oa.setDuration(mMaterialExpandDuration);
+ oa.setInterpolator(new LogDecelerateInterpolator(60, 0));
+ anim.play(oa);
+
+ Animator reverseRevealAnim = null;
+ Animator fakeFolderIconAnim = null;
+
+ if (animate) {
+
+ prepareFakeFolderIcon();
+ float iconTransY = getResources().getInteger(R.integer.folder_icon_translate_y_dist);
+
+ final View fakeFolderIconView = mLauncher.findViewById(R.id.reveal_fake_folder_icon);
+ float baseIconTranslationY = fakeFolderIconView.getTranslationY();
+ PropertyValuesHolder iconty = PropertyValuesHolder.ofFloat("translationY",
+ baseIconTranslationY + iconTransY, baseIconTranslationY);
+ PropertyValuesHolder iconAlpha = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);
+
+ fakeFolderIconAnim = LauncherAnimUtils.ofPropertyValuesHolder(fakeFolderIconView,
+ iconty, iconAlpha);
+ fakeFolderIconAnim.setDuration(mMaterialExpandDuration);
+ fakeFolderIconAnim.setInterpolator(new DecelerateInterpolator(2f));
+ fakeFolderIconAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mFolderIcon.setAlpha(0);
+ fakeFolderIconView.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ fakeFolderIconView.setVisibility(View.INVISIBLE);
+ mFolderIcon.setAlpha(1);
+
+ View revealView = mLauncher.findViewById(R.id.reveal_fake_page_container);
+ revealView.setVisibility(View.INVISIBLE);
+ }
+ });
+ } else {
+ View revealView = mLauncher.findViewById(R.id.reveal_fake_page_container);
+ revealView.setVisibility(View.INVISIBLE);
+ mFolderIcon.setAlpha(1);
+ }
+
+ if (reverseRevealAnim != null) {
+ anim.play(reverseRevealAnim);
+ }
+ if (fakeFolderIconAnim != null) {
+ anim.play(fakeFolderIconAnim);
+ }
+
+ anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
getContext().getString(R.string.folder_closed));
+ unHideWorkspace();
mState = STATE_ANIMATING;
}
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ onCloseComplete();
+ setLayerType(LAYER_TYPE_NONE, null);
+ mState = STATE_SMALL;
+ }
});
- oa.setDuration(mExpandDuration);
- setLayerType(LAYER_TYPE_HARDWARE, null);
- oa.start();
+
+ anim.start();
+ }
+
+ private int mSavedWidgetsVisibilityState = INVISIBLE;
+ private void hideWorkspace() {
+ mSavedWidgetsVisibilityState = mLauncher.getWidgetsView().getVisibility();
+ mLauncher.getWidgetsView().setVisibility(INVISIBLE);
+ mLauncher.getWorkspace().setVisibility(INVISIBLE);
+ mLauncher.getHotseat().setVisibility(INVISIBLE);
+ mLauncher.getSearchDropTargetBar().setVisibility(INVISIBLE);
+ mLauncher.getPageIndicator().setVisibility(INVISIBLE);
+ }
+
+ private void unHideWorkspace() {
+ mLauncher.getWidgetsView().setVisibility(mSavedWidgetsVisibilityState);
+ mLauncher.getWorkspace().setVisibility(VISIBLE);
+ mLauncher.getHotseat().setVisibility(VISIBLE);
+ mLauncher.getSearchDropTargetBar().setVisibility(VISIBLE);
+ mLauncher.getPageIndicator().setVisibility(VISIBLE);
}
public boolean acceptDrop(DragObject d) {
@@ -966,22 +1129,22 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
int centerY = (int) (sTempRect.top + sTempRect.height() * scale / 2);
int centeredLeft = centerX - width / 2;
int centeredTop = centerY - height / 2;
+ int currentPage = mLauncher.getWorkspace().getNextPage();
+
+ // We first fetch the currently visible CellLayoutChildren
+ CellLayout currentLayout = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPage);
+ ShortcutAndWidgetContainer boundingLayout = currentLayout.getShortcutsAndWidgets();
+ Rect bounds = new Rect();
+ parent.getDescendantRectRelativeToSelf(boundingLayout, bounds);
- // We need to bound the folder to the currently visible workspace area
- mLauncher.getWorkspace().getPageAreaRelativeToDragLayer(sTempRect);
- int left = Math.min(Math.max(sTempRect.left, centeredLeft),
- sTempRect.left + sTempRect.width() - width);
- int top = Math.min(Math.max(sTempRect.top, centeredTop),
- sTempRect.top + sTempRect.height() - height);
- if (grid.isPhone && (grid.availableWidthPx - width) < grid.iconSizePx) {
- // Center the folder if it is full (on phones only)
- left = (grid.availableWidthPx - width) / 2;
- } else if (width >= sTempRect.width()) {
+ // Center the folder
+ int left = (grid.availableWidthPx - width) / 2;
+ // Drop the top down a little so it isn't bounded by the page indicators
+ int top = (int) (bounds.top + (bounds.height() * 1.15) - height);
+
+ if (width >= bounds.width()) {
// If the folder doesn't fit within the bounds, center it about the desired bounds
- left = sTempRect.left + (sTempRect.width() - width) / 2;
- }
- if (height >= sTempRect.height()) {
- top = sTempRect.top + (sTempRect.height() - height) / 2;
+ left = bounds.left + (bounds.width() - width) / 2;
}
int folderPivotX = width / 2 + (centeredLeft - left);
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index 8d534d2fe..85e3c3333 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -39,6 +39,7 @@ import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.launcher3.DropTarget.DragObject;
@@ -60,17 +61,17 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private StylusEventHelper mStylusEventHelper;
// The number of icons to display in the
- public static final int NUM_ITEMS_IN_PREVIEW = 3;
+ public static final int NUM_ITEMS_IN_PREVIEW = 4;
private static final int CONSUMPTION_ANIMATION_DURATION = 100;
private static final int DROP_IN_ANIMATION_DURATION = 400;
private static final int INITIAL_ITEM_ANIMATION_DURATION = 350;
private static final int FINAL_ITEM_ANIMATION_DURATION = 200;
// The degree to which the inner ring grows when accepting drop
- private static final float INNER_RING_GROWTH_FACTOR = 0.15f;
+ private static final float INNER_RING_GROWTH_FACTOR = 0.0f;
// The degree to which the outer ring is scaled in its natural state
- private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
+ private static final float OUTER_RING_GROWTH_FACTOR = 0.1f;
// The amount of vertical spread between items in the stack [0...1]
private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f;
@@ -90,7 +91,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
public static Drawable sSharedFolderLeaveBehind = null;
- @Thunk ImageView mPreviewBackground;
+ @Thunk View mPreviewBackground;
@Thunk BubbleTextView mFolderName;
FolderRingAnimator mFolderRingAnimator = null;
@@ -161,11 +162,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
lp.topMargin = grid.iconSizePx + grid.iconDrawablePaddingPx;
// Offset the preview background to center this view accordingly
- icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background);
+ icon.mPreviewBackground = icon.findViewById(R.id.preview_background);
lp = (FrameLayout.LayoutParams) icon.mPreviewBackground.getLayoutParams();
- lp.topMargin = grid.folderBackgroundOffset;
- lp.width = grid.folderIconSizePx;
- lp.height = grid.folderIconSizePx;
+ lp.width = grid.iconSizePx;
+ lp.height = grid.iconSizePx;
+ icon.mPreviewBackground.setLayoutParams(lp);
icon.setTag(folderInfo);
icon.setOnClickListener(launcher);
@@ -183,6 +184,58 @@ public class FolderIcon extends FrameLayout implements FolderListener {
folderInfo.addListener(icon);
icon.setOnFocusChangeListener(launcher.mFocusHandler);
+ icon.setDrawingCacheEnabled(true);
+
+ // get dimen for the icon size
+ // padding is equal to 1/8 of icon size
+ // padding gets used at start and end accounting for 2/8
+ // small icons are separated by 1/2 padding
+ // Total padding equals 2.5/8 leaving 5.5/8 for icons
+ // 5.5/8 remaining, divided by 2 equals 2.75 for each small icon
+ int padding = grid.iconSizePx / 8;
+ int smallIconSize = (int) (padding * 2.75);
+
+ for (int i = NUM_ITEMS_IN_PREVIEW; i >= 0; i--) {
+ ImageView appIcon = null;
+ int marginLeft = 0, marginRight = 0, marginTop = 0, marginBottom = 0;
+ switch(i) {
+ case 0:
+ appIcon = (ImageView) icon.findViewById(R.id.app_0);
+ marginLeft = padding;
+ marginTop = padding;
+ break;
+ case 1:
+ appIcon = (ImageView) icon.findViewById(R.id.app_1);
+ marginTop = padding;
+ marginRight = padding;
+ break;
+ case 2:
+ appIcon = (ImageView) icon.findViewById(R.id.app_2);
+ marginBottom = padding;
+ marginLeft = padding;
+ break;
+ case 3:
+ appIcon = (ImageView) icon.findViewById(R.id.app_3);
+ marginBottom = padding;
+ marginRight = padding;
+ break;
+ }
+
+ if (appIcon != null) {
+ RelativeLayout.LayoutParams layoutParams
+ = (RelativeLayout.LayoutParams) appIcon.getLayoutParams();
+
+ layoutParams.width = smallIconSize;
+ layoutParams.height = smallIconSize;
+ layoutParams.leftMargin = marginLeft;
+ layoutParams.rightMargin = marginRight;
+ layoutParams.topMargin = marginTop;
+ layoutParams.bottomMargin = marginBottom;
+
+ appIcon.setLayoutParams(layoutParams);
+ }
+ }
+
return icon;
}
@@ -220,11 +273,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
DeviceProfile grid = launcher.getDeviceProfile();
- sPreviewSize = grid.folderIconSizePx;
+ sPreviewSize = grid.iconSizePx;
sPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding);
- sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer);
- sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_nolip);
- sSharedFolderLeaveBehind = res.getDrawable(R.drawable.portal_ring_rest);
+ sSharedOuterRingDrawable = res.getDrawable(R.drawable.folder_fill_highlight);
+ sSharedInnerRingDrawable = null;
+ sSharedFolderLeaveBehind = res.getDrawable(R.drawable.folder_bg);
sStaticValuesDirty = false;
}
}
@@ -375,7 +428,14 @@ public class FolderIcon extends FrameLayout implements FolderListener {
item = (ShortcutInfo) mDragInfo;
}
mFolder.beginExternalDrag(item);
- mLauncher.openFolder(FolderIcon.this);
+ mFolderRingAnimator.mCellLayout.hideFolderAccept(mFolderRingAnimator);
+
+ int[] folderTouchXY = new int[2];
+ mFolder.getLocationOnScreen(folderTouchXY);
+ int[] folderTouchXYOffset = {folderTouchXY[0] + mFolder.getWidth() / 2,
+ folderTouchXY[1] + mFolder.getHeight() / 2};
+
+ mLauncher.openFolder(FolderIcon.this, folderTouchXYOffset);
}
};
@@ -482,6 +542,15 @@ public class FolderIcon extends FrameLayout implements FolderListener {
if (d.dragInfo instanceof AppInfo) {
// Came from all apps -- make a copy
item = ((AppInfo) d.dragInfo).makeShortcut();
+ } else if (d.dragInfo instanceof FolderInfo) {
+ FolderInfo folder = (FolderInfo) d.dragInfo;
+ mFolder.notifyDrop();
+ for (ShortcutInfo fItem : folder.contents) {
+ onDrop(fItem, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable, d);
+ }
+ mLauncher.removeFolder(folder);
+ LauncherModel.deleteItemFromDatabase(mLauncher, folder);
+ return;
} else {
item = (ShortcutInfo) d.dragInfo;
}
@@ -511,7 +580,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
mMaxPerspectiveShift = mBaselineIconSize * PERSPECTIVE_SHIFT_FACTOR;
mPreviewOffsetX = (mTotalWidth - mAvailableSpaceInPreview) / 2;
- mPreviewOffsetY = previewPadding + grid.folderBackgroundOffset;
+ mPreviewOffsetY = grid.folderBackgroundOffset;
}
}
@@ -622,13 +691,35 @@ public class FolderIcon extends FrameLayout implements FolderListener {
int nItemsInPreview = Math.min(items.size(), NUM_ITEMS_IN_PREVIEW);
if (!mAnimating) {
- for (int i = nItemsInPreview - 1; i >= 0; i--) {
- v = (TextView) items.get(i);
- if (!mHiddenItems.contains(v.getTag())) {
- d = getTopDrawable(v);
- mParams = computePreviewItemDrawingParams(i, mParams);
- mParams.drawable = d;
- drawPreviewItem(canvas, mParams);
+ for (int i = NUM_ITEMS_IN_PREVIEW; i >= 0; i--) {
+ d = null;
+ if (i < items.size()) {
+ v = (TextView) items.get(i);
+ if (!mHiddenItems.contains(v.getTag())) {
+ d = getTopDrawable(v);
+ mParams = computePreviewItemDrawingParams(i, mParams);
+ mParams.drawable = d;
+ }
+ }
+
+ ImageView appIcon = null;
+ switch(i) {
+ case 0:
+ appIcon = (ImageView) findViewById(R.id.app_0);
+ break;
+ case 1:
+ appIcon = (ImageView) findViewById(R.id.app_1);
+ break;
+ case 2:
+ appIcon = (ImageView) findViewById(R.id.app_2);
+ break;
+ case 3:
+ appIcon = (ImageView) findViewById(R.id.app_3);
+ break;
+ }
+
+ if (appIcon != null) {
+ appIcon.setImageDrawable(d);
}
}
} else {
@@ -645,10 +736,9 @@ public class FolderIcon extends FrameLayout implements FolderListener {
final Runnable onCompleteRunnable) {
final PreviewItemDrawingParams finalParams = computePreviewItemDrawingParams(0, null);
- float iconSize = mLauncher.getDeviceProfile().iconSizePx;
- final float scale0 = iconSize / d.getIntrinsicWidth() ;
- final float transX0 = (mAvailableSpaceInPreview - iconSize) / 2;
- final float transY0 = (mAvailableSpaceInPreview - iconSize) / 2 + getPaddingTop();
+ final float scale0 = 1.0f;
+ final float transX0 = (mAvailableSpaceInPreview - d.getIntrinsicWidth()) / 2;
+ final float transY0 = (mAvailableSpaceInPreview - d.getIntrinsicHeight()) / 2 + getPaddingTop();
mAnimParams.drawable = d;
ValueAnimator va = LauncherAnimUtils.ofFloat(this, 0f, 1.0f);
@@ -675,7 +765,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
public void onAnimationEnd(Animator animation) {
mAnimating = false;
if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
+ mLauncher.runOnUiThread(onCompleteRunnable);
}
}
});
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index aea21c95b..32d752ac0 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -103,7 +103,6 @@ public class FolderInfo extends ItemInfo {
super.onAddToDatabase(context, values);
values.put(LauncherSettings.Favorites.TITLE, title.toString());
values.put(LauncherSettings.Favorites.OPTIONS, options);
-
}
void addListener(FolderListener listener) {
diff --git a/src/com/android/launcher3/InsettableFrameLayout.java b/src/com/android/launcher3/InsettableFrameLayout.java
index 7343bf686..6400a0f89 100644
--- a/src/com/android/launcher3/InsettableFrameLayout.java
+++ b/src/com/android/launcher3/InsettableFrameLayout.java
@@ -24,10 +24,14 @@ public class InsettableFrameLayout extends FrameLayout implements
if (child instanceof Insettable) {
((Insettable) child).setInsets(newInsets);
} else if (!lp.ignoreInsets) {
- lp.topMargin += (newInsets.top - oldInsets.top);
+ if (!lp.ignoreTopInsets) {
+ lp.topMargin += (newInsets.top - oldInsets.top);
+ }
lp.leftMargin += (newInsets.left - oldInsets.left);
lp.rightMargin += (newInsets.right - oldInsets.right);
- lp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
+ if (!lp.ignoreBottomInsets) {
+ lp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
+ }
}
child.setLayoutParams(lp);
}
@@ -65,6 +69,8 @@ public class InsettableFrameLayout extends FrameLayout implements
public static class LayoutParams extends FrameLayout.LayoutParams {
boolean ignoreInsets = false;
+ boolean ignoreTopInsets = false;
+ boolean ignoreBottomInsets = false;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
@@ -72,6 +78,10 @@ public class InsettableFrameLayout extends FrameLayout implements
R.styleable.InsettableFrameLayout_Layout);
ignoreInsets = a.getBoolean(
R.styleable.InsettableFrameLayout_Layout_layout_ignoreInsets, false);
+ ignoreTopInsets = a.getBoolean(
+ R.styleable.InsettableFrameLayout_Layout_layout_ignoreTopInsets, false);
+ ignoreBottomInsets = a.getBoolean(
+ R.styleable.InsettableFrameLayout_Layout_layout_ignoreBottomInsets, false);
a.recycle();
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1f843cb70..6faea2084 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -150,6 +151,8 @@ public class Launcher extends Activity
private static final int REQUEST_BIND_APPWIDGET = 11;
private static final int REQUEST_RECONFIGURE_APPWIDGET = 12;
+ private static final int REQUEST_PERMISSION_CALL_PHONE = 13;
+
private static final int WORKSPACE_BACKGROUND_GRADIENT = 0;
private static final int WORKSPACE_BACKGROUND_TRANSPARENT = 1;
private static final int WORKSPACE_BACKGROUND_BLACK = 2;
@@ -867,6 +870,24 @@ public class Launcher extends Activity
/** @Override for MNC */
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
+ if (requestCode == REQUEST_PERMISSION_CALL_PHONE && sPendingAddItem != null
+ && sPendingAddItem.requestCode == REQUEST_PERMISSION_CALL_PHONE) {
+ View v = null;
+ CellLayout layout = getCellLayout(sPendingAddItem.container, sPendingAddItem.screenId);
+ if (layout != null) {
+ v = layout.getChildAt(sPendingAddItem.cellX, sPendingAddItem.cellY);
+ }
+ Intent intent = sPendingAddItem.intent;
+ sPendingAddItem = null;
+ if (grantResults.length > 0
+ && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ startActivity(v, intent, null);
+ } else {
+ // TODO: Show a snack bar with link to settings
+ Toast.makeText(this, getString(R.string.msg_no_phone_permission,
+ getString(R.string.app_name)), Toast.LENGTH_SHORT).show();
+ }
+ }
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onRequestPermissionsResult(requestCode, permissions,
grantResults);
@@ -1821,6 +1842,10 @@ public class Launcher extends Activity
return mHotseat;
}
+ public View getPageIndicator() {
+ return mPageIndicators;
+ }
+
public ViewGroup getOverviewPanel() {
return mOverviewPanel;
}
@@ -2688,6 +2713,11 @@ public class Launcher extends Activity
final FolderInfo info = folderIcon.getFolderInfo();
Folder openFolder = mWorkspace.getFolderForTag(info);
+ int[] folderTouchXY = new int[2];
+ v.getLocationOnScreen(folderTouchXY);
+ int[] folderTouchXYOffset = {folderTouchXY[0] + v.getWidth() / 2,
+ folderTouchXY[1] + v.getHeight() / 2};
+
// If the folder info reports that the associated folder is open, then verify that
// it is actually opened. There have been a few instances where this gets out of sync.
if (info.opened && openFolder == null) {
@@ -2700,7 +2730,7 @@ public class Launcher extends Activity
// Close any open folder
closeFolder();
// Open the requested folder
- openFolder(folderIcon);
+ openFolder(folderIcon, folderTouchXYOffset);
} else {
// Find the open folder...
int folderScreen;
@@ -2712,7 +2742,7 @@ public class Launcher extends Activity
// Close any folder open on the current screen
closeFolder();
// Pull the folder onto this screen
- openFolder(folderIcon);
+ openFolder(folderIcon, folderTouchXYOffset);
}
}
}
@@ -2926,6 +2956,22 @@ public class Launcher extends Activity
}
return true;
} catch (SecurityException e) {
+ if (Utilities.ATLEAST_MARSHMALLOW && tag instanceof ItemInfo) {
+ // Due to legacy reasons, direct call shortcuts require Launchers to have the
+ // corresponding permission. Show the appropriate permission prompt if that
+ // is the case.
+ if (intent.getComponent() == null
+ && Intent.ACTION_CALL.equals(intent.getAction())
+ && checkSelfPermission(Manifest.permission.CALL_PHONE) !=
+ PackageManager.PERMISSION_GRANTED) {
+ // TODO: Rename sPendingAddItem to a generic name.
+ sPendingAddItem = preparePendingAddArgs(REQUEST_PERMISSION_CALL_PHONE, intent,
+ 0, (ItemInfo) tag);
+ requestPermissions(new String[]{Manifest.permission.CALL_PHONE},
+ REQUEST_PERMISSION_CALL_PHONE);
+ return false;
+ }
+ }
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Launcher does not have the permission to launch " + intent +
". Make sure to create a MAIN intent-filter for the corresponding activity " +
@@ -3063,8 +3109,13 @@ public class Launcher extends Activity
*
* @param folderInfo The FolderInfo describing the folder to open.
*/
- public void openFolder(FolderIcon folderIcon) {
+ public void openFolder(FolderIcon folderIcon, int[] folderTouch) {
Folder folder = folderIcon.getFolder();
+
+ if (folder.getState() == Folder.STATE_ANIMATING) {
+ return;
+ }
+
Folder openFolder = mWorkspace != null ? mWorkspace.getOpenFolder() : null;
if (openFolder != null && openFolder != folder) {
// Close any open folder before opening a folder.
@@ -3087,8 +3138,8 @@ public class Launcher extends Activity
Log.w(TAG, "Opening folder (" + folder + ") which already has a parent (" +
folder.getParent() + ").");
}
- folder.animateOpen();
- growAndFadeOutFolderIcon(folderIcon);
+ folder.animateOpen(getWorkspace(), folderTouch);
+ /*growAndFadeOutFolderIcon(folderIcon);*/
// Notify the accessibility manager that this folder "window" has appeared and occluded
// the workspace items
@@ -3107,17 +3158,21 @@ public class Launcher extends Activity
}
public void closeFolder(Folder folder) {
+ closeFolder(folder, true);
+ }
+
+ public void closeFolder(Folder folder, boolean animate) {
folder.getInfo().opened = false;
ViewGroup parent = (ViewGroup) folder.getParent().getParent();
if (parent != null) {
FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
- shrinkAndFadeInFolderIcon(fi);
+ /*shrinkAndFadeInFolderIcon(fi);*/
if (fi != null) {
((CellLayout.LayoutParams) fi.getLayoutParams()).canReorder = true;
}
}
- folder.animateClosed();
+ folder.animateClosed(animate);
// Notify the accessibility manager that this folder "window" has disappeard and no
// longer occludeds the workspace items
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 8a5804f34..5cde2e588 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -40,7 +40,7 @@ public class LauncherSettings {
* <P>Type: TEXT</P>
*/
public static final String TITLE = "title";
-
+
/**
* The Intent URL of the gesture, describing what it points to. This
* value is given to {@link android.content.Intent#parseUri(String, int)} to create