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