DeepShortcutView.java revision 1bce7fd342875be8f7c1f82c8cf21d0199c8d544
11bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham/*
21bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * Copyright (C) 2016 The Android Open Source Project
31bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham *
41bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * Licensed under the Apache License, Version 2.0 (the "License");
51bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * you may not use this file except in compliance with the License.
61bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * You may obtain a copy of the License at
71bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham *
81bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham *      http://www.apache.org/licenses/LICENSE-2.0
91bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham *
101bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * Unless required by applicable law or agreed to in writing, software
111bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * distributed under the License is distributed on an "AS IS" BASIS,
121bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * See the License for the specific language governing permissions and
141bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * limitations under the License.
151bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham */
161bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
171bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhampackage com.android.launcher3.shortcuts;
181bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
191bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport android.content.Context;
201bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport android.support.annotation.IntDef;
211bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport android.util.AttributeSet;
221bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
231bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport com.android.launcher3.BubbleTextView;
241bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport com.android.launcher3.R;
251bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
261bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham/**
271bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham * A {@link BubbleTextView} that represents a deep shortcut within an app.
281bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham */
291bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhampublic class DeepShortcutView extends BubbleTextView {
301bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
311bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    private static final float HOVER_SCALE = 1.1f;
321bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    // The direction this view should translate when animating the hover state.
331bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    // This allows hovered shortcuts to "push" other shortcuts away.
341bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    @IntDef({DIRECTION_UP, DIRECTION_NONE, DIRECTION_DOWN})
351bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public @interface TranslationDirection {}
361bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
371bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public static final int DIRECTION_UP = -1;
381bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public static final int DIRECTION_NONE = 0;
391bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public static final int DIRECTION_DOWN = 1;
401bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    @TranslationDirection
411bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    private int mTranslationDirection = DIRECTION_NONE;
421bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
431bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    private int mSpacing;
441bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    private int mTop;
451bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    private boolean mIsHoveringOver = false;
461bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
471bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public DeepShortcutView(Context context) {
481bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        this(context, null, 0);
491bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
501bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
511bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public DeepShortcutView(Context context, AttributeSet attrs) {
521bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        this(context, attrs, 0);
531bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
541bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
551bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public DeepShortcutView(Context context, AttributeSet attrs, int defStyle) {
561bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        super(context, attrs, defStyle);
571bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
581bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        mSpacing = getResources().getDimensionPixelSize(R.dimen.deep_shortcuts_spacing);
591bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
601bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
611bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public int getSpacing() {
621bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return mSpacing;
631bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
641bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
651bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    /**
661bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     * Updates the state of this view based on touches over the container before user lifts finger.
671bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     *
681bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     * @param containerContainsTouch whether the {@link DeepShortcutsContainer} this shortcut
691bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     *                               is inside contains the current touch
701bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     * @param isBelowHoveredShortcut whether a sibling shortcut before this one in the
711bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     *                               view hierarchy is being hovered over
721bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     * @param touchY the y coordinate of the touch, relative to the {@link DeepShortcutsContainer}
731bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     *               this shortcut is inside
741bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     * @return whether this shortcut is being hovered over
751bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     */
761bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public boolean updateHoverState(boolean containerContainsTouch, boolean isBelowHoveredShortcut,
771bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            float touchY) {
781bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        if (!containerContainsTouch) {
791bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            mIsHoveringOver = false;
801bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            mTranslationDirection = DIRECTION_NONE;
811bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        } else if (isBelowHoveredShortcut) {
821bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            mIsHoveringOver = false;
831bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            mTranslationDirection = DIRECTION_DOWN;
841bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        } else {
851bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            // Include space around the view when determining hover state to avoid gaps.
861bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            mTop = (int) (getY() - getTranslationY());
871bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            mIsHoveringOver = (touchY >= mTop - mSpacing / 2)
881bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham                    && (touchY < mTop + getHeight() + mSpacing / 2);
891bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham            mTranslationDirection = mIsHoveringOver ? DIRECTION_NONE : DIRECTION_UP;
901bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        }
911bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        animateHoverState();
921bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return mIsHoveringOver;
931bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
941bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
951bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    /**
961bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     * If this shortcut is being hovered over, we scale it up. If another shortcut is being hovered
971bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     * over, we translate this one away from it to account for its increased size.
981bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     *
991bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     * TODO: apply motion spec here
1001bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham     */
1011bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    private void animateHoverState() {
1021bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        float scale = mIsHoveringOver ? HOVER_SCALE : 1f;
1031bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        setScaleX(scale);
1041bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        setScaleY(scale);
1051bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
1061bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        float translation = (HOVER_SCALE - 1f) * getHeight();
1071bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        setTranslationY(translation * mTranslationDirection);
1081bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
1091bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
1101bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public boolean isHoveringOver() {
1111bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return mIsHoveringOver;
1121bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
1131bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham}
114