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