Home | History | Annotate | Download | only in launcher3
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.launcher3;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorListenerAdapter;
     21 import android.animation.ObjectAnimator;
     22 import android.content.Context;
     23 import android.graphics.Rect;
     24 import android.graphics.drawable.Drawable;
     25 import android.util.AttributeSet;
     26 import android.view.View;
     27 import android.view.animation.AccelerateInterpolator;
     28 import android.widget.FrameLayout;
     29 
     30 /*
     31  * Ths bar will manage the transition between the QSB search bar and the delete drop
     32  * targets so that each of the individual IconDropTargets don't have to.
     33  */
     34 public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener {
     35 
     36     private static final int sTransitionInDuration = 200;
     37     private static final int sTransitionOutDuration = 175;
     38 
     39     private ObjectAnimator mDropTargetBarAnim;
     40     private ObjectAnimator mQSBSearchBarAnim;
     41     private static final AccelerateInterpolator sAccelerateInterpolator =
     42             new AccelerateInterpolator();
     43 
     44     private boolean mIsSearchBarHidden;
     45     private View mQSBSearchBar;
     46     private View mDropTargetBar;
     47     private ButtonDropTarget mInfoDropTarget;
     48     private ButtonDropTarget mDeleteDropTarget;
     49     private int mBarHeight;
     50     private boolean mDeferOnDragEnd = false;
     51 
     52     private Drawable mPreviousBackground;
     53     private boolean mEnableDropDownDropTargets;
     54 
     55     public SearchDropTargetBar(Context context, AttributeSet attrs) {
     56         this(context, attrs, 0);
     57     }
     58 
     59     public SearchDropTargetBar(Context context, AttributeSet attrs, int defStyle) {
     60         super(context, attrs, defStyle);
     61     }
     62 
     63     public void setup(Launcher launcher, DragController dragController) {
     64         dragController.addDragListener(this);
     65         dragController.addDragListener(mInfoDropTarget);
     66         dragController.addDragListener(mDeleteDropTarget);
     67         dragController.addDropTarget(mInfoDropTarget);
     68         dragController.addDropTarget(mDeleteDropTarget);
     69         dragController.setFlingToDeleteDropTarget(mDeleteDropTarget);
     70         mInfoDropTarget.setLauncher(launcher);
     71         mDeleteDropTarget.setLauncher(launcher);
     72         mQSBSearchBar = launcher.getQsbBar();
     73         if (mEnableDropDownDropTargets) {
     74             mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
     75                     -mBarHeight);
     76         } else {
     77             mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
     78         }
     79         setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
     80     }
     81 
     82     private void prepareStartAnimation(View v) {
     83         // Enable the hw layers before the animation starts (will be disabled in the onAnimationEnd
     84         // callback below)
     85         v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
     86     }
     87 
     88     private void setupAnimation(ObjectAnimator anim, final View v) {
     89         anim.setInterpolator(sAccelerateInterpolator);
     90         anim.setDuration(sTransitionInDuration);
     91         anim.addListener(new AnimatorListenerAdapter() {
     92             @Override
     93             public void onAnimationEnd(Animator animation) {
     94                 v.setLayerType(View.LAYER_TYPE_NONE, null);
     95             }
     96         });
     97     }
     98 
     99     @Override
    100     protected void onFinishInflate() {
    101         super.onFinishInflate();
    102 
    103         // Get the individual components
    104         mDropTargetBar = findViewById(R.id.drag_target_bar);
    105         mInfoDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.info_target_text);
    106         mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target_text);
    107 
    108         mInfoDropTarget.setSearchDropTargetBar(this);
    109         mDeleteDropTarget.setSearchDropTargetBar(this);
    110 
    111         mEnableDropDownDropTargets =
    112             getResources().getBoolean(R.bool.config_useDropTargetDownTransition);
    113 
    114         // Create the various fade animations
    115         if (mEnableDropDownDropTargets) {
    116             LauncherAppState app = LauncherAppState.getInstance();
    117             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
    118             mBarHeight = grid.searchBarSpaceHeightPx;
    119             mDropTargetBar.setTranslationY(-mBarHeight);
    120             mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "translationY",
    121                     -mBarHeight, 0f);
    122 
    123         } else {
    124             mDropTargetBar.setAlpha(0f);
    125             mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
    126         }
    127         setupAnimation(mDropTargetBarAnim, mDropTargetBar);
    128     }
    129 
    130     public void finishAnimations() {
    131         prepareStartAnimation(mDropTargetBar);
    132         mDropTargetBarAnim.reverse();
    133         prepareStartAnimation(mQSBSearchBar);
    134         mQSBSearchBarAnim.reverse();
    135     }
    136 
    137     /*
    138      * Shows and hides the search bar.
    139      */
    140     public void showSearchBar(boolean animated) {
    141         boolean needToCancelOngoingAnimation = mQSBSearchBarAnim.isRunning() && !animated;
    142         if (!mIsSearchBarHidden && !needToCancelOngoingAnimation) return;
    143         if (animated) {
    144             prepareStartAnimation(mQSBSearchBar);
    145             mQSBSearchBarAnim.reverse();
    146         } else {
    147             mQSBSearchBarAnim.cancel();
    148             if (mEnableDropDownDropTargets) {
    149                 mQSBSearchBar.setTranslationY(0);
    150             } else {
    151                 mQSBSearchBar.setAlpha(1f);
    152             }
    153         }
    154         mIsSearchBarHidden = false;
    155     }
    156     public void hideSearchBar(boolean animated) {
    157         boolean needToCancelOngoingAnimation = mQSBSearchBarAnim.isRunning() && !animated;
    158         if (mIsSearchBarHidden && !needToCancelOngoingAnimation) return;
    159         if (animated) {
    160             prepareStartAnimation(mQSBSearchBar);
    161             mQSBSearchBarAnim.start();
    162         } else {
    163             mQSBSearchBarAnim.cancel();
    164             if (mEnableDropDownDropTargets) {
    165                 mQSBSearchBar.setTranslationY(-mBarHeight);
    166             } else {
    167                 mQSBSearchBar.setAlpha(0f);
    168             }
    169         }
    170         mIsSearchBarHidden = true;
    171     }
    172 
    173     /*
    174      * Gets various transition durations.
    175      */
    176     public int getTransitionInDuration() {
    177         return sTransitionInDuration;
    178     }
    179     public int getTransitionOutDuration() {
    180         return sTransitionOutDuration;
    181     }
    182 
    183     /*
    184      * DragController.DragListener implementation
    185      */
    186     @Override
    187     public void onDragStart(DragSource source, Object info, int dragAction) {
    188         // Animate out the QSB search bar, and animate in the drop target bar
    189         prepareStartAnimation(mDropTargetBar);
    190         mDropTargetBarAnim.start();
    191         if (!mIsSearchBarHidden) {
    192             prepareStartAnimation(mQSBSearchBar);
    193             mQSBSearchBarAnim.start();
    194         }
    195     }
    196 
    197     public void deferOnDragEnd() {
    198         mDeferOnDragEnd = true;
    199     }
    200 
    201     @Override
    202     public void onDragEnd() {
    203         if (!mDeferOnDragEnd) {
    204             // Restore the QSB search bar, and animate out the drop target bar
    205             prepareStartAnimation(mDropTargetBar);
    206             mDropTargetBarAnim.reverse();
    207             if (!mIsSearchBarHidden) {
    208                 prepareStartAnimation(mQSBSearchBar);
    209                 mQSBSearchBarAnim.reverse();
    210             }
    211         } else {
    212             mDeferOnDragEnd = false;
    213         }
    214     }
    215 
    216     public void onSearchPackagesChanged(boolean searchVisible, boolean voiceVisible) {
    217         if (mQSBSearchBar != null) {
    218             Drawable bg = mQSBSearchBar.getBackground();
    219             if (bg != null && (!searchVisible && !voiceVisible)) {
    220                 // Save the background and disable it
    221                 mPreviousBackground = bg;
    222                 mQSBSearchBar.setBackgroundResource(0);
    223             } else if (mPreviousBackground != null && (searchVisible || voiceVisible)) {
    224                 // Restore the background
    225                 mQSBSearchBar.setBackground(mPreviousBackground);
    226             }
    227         }
    228     }
    229 
    230     public Rect getSearchBarBounds() {
    231         if (mQSBSearchBar != null) {
    232             final int[] pos = new int[2];
    233             mQSBSearchBar.getLocationOnScreen(pos);
    234 
    235             final Rect rect = new Rect();
    236             rect.left = pos[0];
    237             rect.top = pos[1];
    238             rect.right = pos[0] + mQSBSearchBar.getWidth();
    239             rect.bottom = pos[1] + mQSBSearchBar.getHeight();
    240             return rect;
    241         } else {
    242             return null;
    243         }
    244     }
    245 }
    246