summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTony <twickham@google.com>2016-07-22 12:46:51 -0700
committerTony <twickham@google.com>2016-07-26 17:10:05 -0700
commiteec1f9a839e8c58a96f16f61e998891433e0eb6b (patch)
tree4ade448d4e5eeec4bb130d583acceffcb32f0945 /src
parente9381d60cc18bac394c1e59196cf764bb3a49527 (diff)
downloadandroid_packages_apps_Trebuchet-eec1f9a839e8c58a96f16f61e998891433e0eb6b.tar.gz
android_packages_apps_Trebuchet-eec1f9a839e8c58a96f16f61e998891433e0eb6b.tar.bz2
android_packages_apps_Trebuchet-eec1f9a839e8c58a96f16f61e998891433e0eb6b.zip
Add arrow view to deep shortcuts container.
- We create a trangular path, which we use as the view's outline (for the shadow) and as its PathShape background. - We scale up the arrow as the container opens. Bug: 28980830 Change-Id: I71e566552f063dfdb69067bb7e3cee659988f934
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/graphics/TriangleShape.java56
-rw-r--r--src/com/android/launcher3/shortcuts/DeepShortcutView.java8
-rw-r--r--src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java86
3 files changed, 135 insertions, 15 deletions
diff --git a/src/com/android/launcher3/graphics/TriangleShape.java b/src/com/android/launcher3/graphics/TriangleShape.java
new file mode 100644
index 000000000..cce4e3cd9
--- /dev/null
+++ b/src/com/android/launcher3/graphics/TriangleShape.java
@@ -0,0 +1,56 @@
+/*
+ * 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.graphics;
+
+import android.graphics.Outline;
+import android.graphics.Path;
+import android.graphics.drawable.shapes.PathShape;
+import android.support.annotation.NonNull;
+
+/**
+ * Wrapper around {@link android.graphics.drawable.shapes.PathShape}
+ * that creates a shape with a triangular path (pointing up or down).
+ */
+public class TriangleShape extends PathShape {
+ private Path mTriangularPath;
+
+ public TriangleShape(Path path, float stdWidth, float stdHeight) {
+ super(path, stdWidth, stdHeight);
+ mTriangularPath = path;
+ }
+
+ public static TriangleShape create(float width, float height, boolean isPointingUp) {
+ Path triangularPath = new Path();
+ if (isPointingUp) {
+ triangularPath.moveTo(0, height);
+ triangularPath.lineTo(width, height);
+ triangularPath.lineTo(width / 2, 0);
+ triangularPath.close();
+ } else {
+ triangularPath.moveTo(0, 0);
+ triangularPath.lineTo(width / 2, height);
+ triangularPath.lineTo(width, 0);
+ triangularPath.close();
+ }
+ return new TriangleShape(triangularPath, width, height);
+ }
+
+ @Override
+ public void getOutline(@NonNull Outline outline) {
+ outline.setConvexPath(mTriangularPath);
+ }
+}
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutView.java b/src/com/android/launcher3/shortcuts/DeepShortcutView.java
index f6fcdde2e..7cb2d43d7 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutView.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutView.java
@@ -89,11 +89,8 @@ public class DeepShortcutView extends FrameLayout {
/**
* Creates an animator to play when the shortcut container is being opened.
- *
- * @param animationIndex The index at which this animation will be started
- * relative to other DeepShortcutView open animations.
*/
- public Animator createOpenAnimation(int animationIndex, boolean isContainerAboveIcon) {
+ public Animator createOpenAnimation(long animationDelay, boolean isContainerAboveIcon) {
final Resources res = getResources();
setVisibility(INVISIBLE);
@@ -119,8 +116,7 @@ public class DeepShortcutView extends FrameLayout {
.scaleX(1).scaleY(1);
openAnimation.playTogether(reveal, translationY, scale);
- openAnimation.setStartDelay(animationIndex * res.getInteger(
- R.integer.config_deepShortcutOpenStagger));
+ openAnimation.setStartDelay(animationDelay);
openAnimation.setDuration(res.getInteger(R.integer.config_deepShortcutOpenDuration));
openAnimation.setInterpolator(new DecelerateInterpolator());
return openAnimation;
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index 4cbbe97cf..c881c8c4b 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -16,19 +16,24 @@
package com.android.launcher3.shortcuts;
+import android.animation.Animator;
import android.animation.AnimatorSet;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ShapeDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -44,6 +49,7 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
+import com.android.launcher3.LauncherViewPropertyAnimator;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
@@ -54,6 +60,7 @@ import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.graphics.ScaledPreviewProvider;
+import com.android.launcher3.graphics.TriangleShape;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
@@ -88,6 +95,7 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
private Point mIconLastTouchPos = new Point();
private boolean mIsLeftAligned;
private boolean mIsAboveIcon;
+ private View mArrow;
private boolean mSrcIconDragStarted;
@@ -210,27 +218,56 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
}
private DeepShortcutView getShortcutAt(int index) {
+ if (!mIsAboveIcon) {
+ // Opening down, so arrow is the first view.
+ index++;
+ }
return (DeepShortcutView) getChildAt(index);
}
+ private int getShortcutCount() {
+ // All children except the arrow are shortcuts.
+ return getChildCount() - 1;
+ }
+
private void animateOpen(BubbleTextView originalIcon) {
orientAboutIcon(originalIcon);
+ final Resources resources = getResources();
+ final int arrowWidth = resources.getDimensionPixelSize(R.dimen.deep_shortcuts_arrow_width);
+ final int arrowHeight = resources.getDimensionPixelSize(R.dimen.deep_shortcuts_arrow_height);
+ int iconWidth = originalIcon.getWidth() - originalIcon.getTotalPaddingLeft()
+ - originalIcon.getTotalPaddingRight();
+ iconWidth *= originalIcon.getScaleX();
+ final int arrowHorizontalOffset = iconWidth / 2 - arrowWidth / 2;
+ final int arrowVerticalOffset = resources.getDimensionPixelSize(
+ R.dimen.deep_shortcuts_arrow_vertical_offset);
+ mArrow = addArrowView(arrowHorizontalOffset, arrowVerticalOffset, arrowWidth, arrowHeight);
setVisibility(View.VISIBLE);
final AnimatorSet shortcutAnims = LauncherAnimUtils.createAnimatorSet();
- final int numShortcuts = getChildCount();
- final int arrowOffset = getResources().getDimensionPixelSize(
- R.dimen.deep_shortcuts_arrow_horizontal_offset);
- final int pivotX = mIsLeftAligned ? arrowOffset : getMeasuredWidth() - arrowOffset;
+ final int shortcutCount = getShortcutCount();
+ final int pivotX = mIsLeftAligned ? arrowHorizontalOffset
+ : getMeasuredWidth() - arrowHorizontalOffset;
final int pivotY = getShortcutAt(0).getMeasuredHeight() / 2;
- for (int i = 0; i < numShortcuts; i++) {
+ for (int i = 0; i < shortcutCount; i++) {
DeepShortcutView deepShortcutView = getShortcutAt(i);
deepShortcutView.setPivotX(pivotX);
deepShortcutView.setPivotY(pivotY);
- int animationIndex = mIsAboveIcon ? numShortcuts - i - 1 : i;
- shortcutAnims.play(deepShortcutView.createOpenAnimation(animationIndex, mIsAboveIcon));
+ int animationIndex = mIsAboveIcon ? shortcutCount - i - 1 : i;
+ long animationDelay = animationIndex * getResources().getInteger(
+ R.integer.config_deepShortcutOpenStagger);
+ shortcutAnims.play(deepShortcutView.createOpenAnimation(animationDelay, mIsAboveIcon));
}
+ mArrow.setScaleX(0);
+ mArrow.setScaleY(0);
+ final long shortcutAnimDuration = shortcutAnims.getChildAnimations().get(0).getDuration();
+ final long arrowScaleDelay = shortcutAnimDuration / 6;
+ final long arrowScaleDuration = shortcutAnimDuration - arrowScaleDelay;
+ Animator arrowScale = new LauncherViewPropertyAnimator(mArrow).scaleX(1).scaleY(1);
+ arrowScale.setStartDelay(arrowScaleDelay);
+ arrowScale.setDuration(arrowScaleDuration);
+ shortcutAnims.play(arrowScale);
shortcutAnims.start();
}
@@ -245,8 +282,6 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
*
* So we always align left if there is enough horizontal space
* and align above if there is enough vertical space.
- *
- * TODO: draw arrow based on orientation.
*/
private void orientAboutIcon(BubbleTextView icon) {
int width = getMeasuredWidth();
@@ -285,6 +320,36 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
setY(y);
}
+ /**
+ * Adds an arrow view pointing at the original icon.
+ * @param horizontalOffset the horizontal offset of the arrow, so that it
+ * points at the center of the original icon
+ */
+ private View addArrowView(int horizontalOffset, int verticalOffset, int width, int height) {
+ LinearLayout.LayoutParams layoutParams = new LayoutParams(width, height);
+ if (mIsLeftAligned) {
+ layoutParams.gravity = Gravity.LEFT;
+ layoutParams.leftMargin = horizontalOffset;
+ } else {
+ layoutParams.gravity = Gravity.RIGHT;
+ layoutParams.rightMargin = horizontalOffset;
+ }
+ if (mIsAboveIcon) {
+ layoutParams.topMargin = verticalOffset;
+ } else {
+ layoutParams.bottomMargin = verticalOffset;
+ }
+
+ View arrowView = new View(getContext());
+ ShapeDrawable arrowDrawable = new ShapeDrawable(TriangleShape.create(
+ width, height, !mIsAboveIcon));
+ arrowDrawable.getPaint().setColor(Color.WHITE);
+ arrowView.setBackground(arrowDrawable);
+ arrowView.setElevation(getElevation());
+ addView(arrowView, mIsAboveIcon ? getChildCount() : 0, layoutParams);
+ return arrowView;
+ }
+
private void deferDrag(BubbleTextView originalIcon) {
mDeferredDragIcon = originalIcon;
showDragView(originalIcon);
@@ -339,6 +404,7 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
Utilities.translateEventCoordinates(this, mLauncher.getDragLayer(), ev);
final int dragLayerX = (int) ev.getX();
final int dragLayerY = (int) ev.getY();
+ int shortcutCount = getShortcutCount();
if (action == MotionEvent.ACTION_MOVE) {
if (mLastX != 0 || mLastY != 0) {
mDistanceDragged += Math.hypot(mLastX - x, mLastY - y);
@@ -347,6 +413,8 @@ public class DeepShortcutsContainer extends LinearLayout implements View.OnLongC
mLastY = y;
if (shouldStartDeferredDrag((int) x, (int) y)) {
+ DeepShortcutView topShortcut = getShortcutAt(0);
+ DeepShortcutView bottomShortcut = getShortcutAt(shortcutCount - 1);
mSrcIconDragStarted = true;
cleanupDeferredDrag(true);
mDeferredDragIcon.getParent().requestDisallowInterceptTouchEvent(false);