diff options
Diffstat (limited to 'src/com/android/launcher3/ButtonDropTarget.java')
-rw-r--r-- | src/com/android/launcher3/ButtonDropTarget.java | 225 |
1 files changed, 190 insertions, 35 deletions
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java index 019f86c21..b7f89d02a 100644 --- a/src/com/android/launcher3/ButtonDropTarget.java +++ b/src/com/android/launcher3/ButtonDropTarget.java @@ -16,26 +16,41 @@ package com.android.launcher3; +import android.animation.AnimatorSet; +import android.animation.FloatArrayEvaluator; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.TargetApi; import android.content.Context; -import android.content.res.Resources; +import android.content.res.ColorStateList; +import android.content.res.Configuration; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Build; import android.util.AttributeSet; import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.LinearInterpolator; import android.widget.TextView; +import com.android.launcher3.util.Thunk; /** * Implements a DropTarget. */ -public class ButtonDropTarget extends TextView implements DropTarget, DragController.DragListener { +public abstract class ButtonDropTarget extends TextView + implements DropTarget, DragController.DragListener, OnClickListener { - protected final int mTransitionDuration; + private static int DRAG_VIEW_DROP_DURATION = 285; protected Launcher mLauncher; private int mBottomDragPadding; - protected TextView mText; protected SearchDropTargetBar mSearchDropTargetBar; /** Whether this drop target is active for the current drag */ @@ -44,72 +59,197 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro /** The paint applied to the drag view on hover */ protected int mHoverColor = 0; + protected ColorStateList mOriginalTextColor; + protected Drawable mDrawable; + + private AnimatorSet mCurrentColorAnim; + @Thunk ColorMatrix mSrcFilter, mDstFilter, mCurrentFilter; + + public ButtonDropTarget(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ButtonDropTarget(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + mBottomDragPadding = getResources().getDimensionPixelSize(R.dimen.drop_target_drag_padding); + } - Resources r = getResources(); - mTransitionDuration = r.getInteger(R.integer.config_dropTargetBgTransitionDuration); - mBottomDragPadding = r.getDimensionPixelSize(R.dimen.drop_target_drag_padding); + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mOriginalTextColor = getTextColors(); + + // Remove the text in the Phone UI in landscape + DeviceProfile grid = ((Launcher) getContext()).getDeviceProfile(); + if (grid.isVerticalBarLayout()) { + setText(""); + } } - void setLauncher(Launcher launcher) { - mLauncher = launcher; + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + protected void setDrawable(int resId) { + // We do not set the drawable in the xml as that inflates two drawables corresponding to + // drawableLeft and drawableStart. + mDrawable = getResources().getDrawable(resId); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + setCompoundDrawablesRelativeWithIntrinsicBounds(mDrawable, null, null, null); + } else { + setCompoundDrawablesWithIntrinsicBounds(mDrawable, null, null, null); + } } - public boolean acceptDrop(DragObject d) { - return false; + public void setLauncher(Launcher launcher) { + mLauncher = launcher; } public void setSearchDropTargetBar(SearchDropTargetBar searchDropTargetBar) { mSearchDropTargetBar = searchDropTargetBar; } - protected Drawable getCurrentDrawable() { - Drawable[] drawables = getCompoundDrawablesRelative(); - for (int i = 0; i < drawables.length; ++i) { - if (drawables[i] != null) { - return drawables[i]; + @Override + public void onFlingToDelete(DragObject d, PointF vec) { } + + @Override + public final void onDragEnter(DragObject d) { + d.dragView.setColor(mHoverColor); + if (Utilities.isLmpOrAbove()) { + animateTextColor(mHoverColor); + } else { + if (mCurrentFilter == null) { + mCurrentFilter = new ColorMatrix(); } + DragView.setColorScale(mHoverColor, mCurrentFilter); + mDrawable.setColorFilter(new ColorMatrixColorFilter(mCurrentFilter)); + setTextColor(mHoverColor); } - return null; } - public void onDrop(DragObject d) { + @Override + public void onDragOver(DragObject d) { + // Do nothing } - public void onFlingToDelete(DragObject d, int x, int y, PointF vec) { - // Do nothing + protected void resetHoverColor() { + if (Utilities.isLmpOrAbove()) { + animateTextColor(mOriginalTextColor.getDefaultColor()); + } else { + mDrawable.setColorFilter(null); + setTextColor(mOriginalTextColor); + } } - public void onDragEnter(DragObject d) { - d.dragView.setColor(mHoverColor); + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private void animateTextColor(int targetColor) { + if (mCurrentColorAnim != null) { + mCurrentColorAnim.cancel(); + } + + mCurrentColorAnim = new AnimatorSet(); + mCurrentColorAnim.setDuration(DragView.COLOR_CHANGE_DURATION); + + if (mSrcFilter == null) { + mSrcFilter = new ColorMatrix(); + mDstFilter = new ColorMatrix(); + mCurrentFilter = new ColorMatrix(); + } + + DragView.setColorScale(getTextColor(), mSrcFilter); + DragView.setColorScale(targetColor, mDstFilter); + ValueAnimator anim1 = ValueAnimator.ofObject( + new FloatArrayEvaluator(mCurrentFilter.getArray()), + mSrcFilter.getArray(), mDstFilter.getArray()); + anim1.addUpdateListener(new AnimatorUpdateListener() { + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mDrawable.setColorFilter(new ColorMatrixColorFilter(mCurrentFilter)); + invalidate(); + } + }); + + mCurrentColorAnim.play(anim1); + mCurrentColorAnim.play(ObjectAnimator.ofArgb(this, "textColor", targetColor)); + mCurrentColorAnim.start(); } - public void onDragOver(DragObject d) { - // Do nothing + @Override + public final void onDragExit(DragObject d) { + if (!d.dragComplete) { + d.dragView.setColor(0); + resetHoverColor(); + } else { + // Restore the hover color + d.dragView.setColor(mHoverColor); + } } - public void onDragExit(DragObject d) { - d.dragView.setColor(0); + @Override + public final void onDragStart(DragSource source, Object info, int dragAction) { + mActive = supportsDrop(source, info); + mDrawable.setColorFilter(null); + if (mCurrentColorAnim != null) { + mCurrentColorAnim.cancel(); + mCurrentColorAnim = null; + } + setTextColor(mOriginalTextColor); + ((ViewGroup) getParent()).setVisibility(mActive ? View.VISIBLE : View.GONE); } - public void onDragStart(DragSource source, Object info, int dragAction) { - // Do nothing + @Override + public final boolean acceptDrop(DragObject dragObject) { + return supportsDrop(dragObject.dragSource, dragObject.dragInfo); } + protected abstract boolean supportsDrop(DragSource source, Object info); + + @Override public boolean isDropEnabled() { return mActive; } + @Override public void onDragEnd() { - // Do nothing + mActive = false; + } + + /** + * On drop animate the dropView to the icon. + */ + @Override + public void onDrop(final DragObject d) { + final DragLayer dragLayer = mLauncher.getDragLayer(); + final Rect from = new Rect(); + dragLayer.getViewRectRelativeToSelf(d.dragView, from); + + int width = mDrawable.getIntrinsicWidth(); + int height = mDrawable.getIntrinsicHeight(); + final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(), + width, height); + final float scale = (float) to.width() / from.width(); + mSearchDropTargetBar.deferOnDragEnd(); + + Runnable onAnimationEndRunnable = new Runnable() { + @Override + public void run() { + completeDrop(d); + mSearchDropTargetBar.onDragEnd(); + mLauncher.exitSpringLoadedDragModeDelayed(true, 0, null); + } + }; + dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f, + DRAG_VIEW_DROP_DURATION, new DecelerateInterpolator(2), + new LinearInterpolator(), onAnimationEndRunnable, + DragLayer.ANIMATION_END_DISAPPEAR, null); } @Override + public void prepareAccessibilityDrop() { } + + @Thunk abstract void completeDrop(DragObject d); + + @Override public void getHitRectRelativeToDragLayer(android.graphics.Rect outRect) { super.getHitRect(outRect); outRect.bottom += mBottomDragPadding; @@ -119,11 +259,7 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro outRect.offsetTo(coords[0], coords[1]); } - private boolean isRtl() { - return (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); - } - - Rect getIconRect(int viewWidth, int viewHeight, int drawableWidth, int drawableHeight) { + protected Rect getIconRect(int viewWidth, int viewHeight, int drawableWidth, int drawableHeight) { DragLayer dragLayer = mLauncher.getDragLayer(); // Find the rect to animate to (the view is center aligned) @@ -136,7 +272,7 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro final int left; final int right; - if (isRtl()) { + if (Utilities.isRtl(getResources())) { right = to.right - getPaddingRight(); left = right - width; } else { @@ -157,7 +293,26 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro return to; } + @Override public void getLocationInDragLayer(int[] loc) { mLauncher.getDragLayer().getLocationInDragLayer(this, loc); } + + public void enableAccessibleDrag(boolean enable) { + setOnClickListener(enable ? this : null); + } + + protected String getAccessibilityDropConfirmation() { + return null; + } + + @Override + public void onClick(View v) { + LauncherAppState.getInstance().getAccessibilityDelegate() + .handleAccessibleDrop(this, null, getAccessibilityDropConfirmation()); + } + + public int getTextColor() { + return getTextColors().getDefaultColor(); + } } |