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.launcher2; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorListenerAdapter; 21 import android.animation.AnimatorSet; 22 import android.animation.ObjectAnimator; 23 import android.content.Context; 24 import android.graphics.Rect; 25 import android.graphics.drawable.Drawable; 26 import android.util.AttributeSet; 27 import android.view.View; 28 import android.view.animation.AccelerateInterpolator; 29 import android.view.animation.DecelerateInterpolator; 30 import android.widget.FrameLayout; 31 32 import com.android.launcher.R; 33 34 /* 35 * Ths bar will manage the transition between the QSB search bar and the delete drop 36 * targets so that each of the individual IconDropTargets don't have to. 37 */ 38 public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener { 39 40 private static final int sTransitionInDuration = 200; 41 private static final int sTransitionOutDuration = 175; 42 43 private AnimatorSet mDropTargetBarFadeInAnim; 44 private AnimatorSet mDropTargetBarFadeOutAnim; 45 private ObjectAnimator mQSBSearchBarFadeInAnim; 46 private ObjectAnimator mQSBSearchBarFadeOutAnim; 47 48 private boolean mIsSearchBarHidden; 49 private View mQSBSearchBar; 50 private View mDropTargetBar; 51 private ButtonDropTarget mInfoDropTarget; 52 private ButtonDropTarget mDeleteDropTarget; 53 private int mBarHeight; 54 private boolean mDeferOnDragEnd = false; 55 56 private Drawable mPreviousBackground; 57 58 public SearchDropTargetBar(Context context, AttributeSet attrs) { 59 this(context, attrs, 0); 60 } 61 62 public SearchDropTargetBar(Context context, AttributeSet attrs, int defStyle) { 63 super(context, attrs, defStyle); 64 } 65 66 public void setup(Launcher launcher, DragController dragController) { 67 dragController.addDragListener(this); 68 dragController.addDragListener(mInfoDropTarget); 69 dragController.addDragListener(mDeleteDropTarget); 70 dragController.addDropTarget(mInfoDropTarget); 71 dragController.addDropTarget(mDeleteDropTarget); 72 mInfoDropTarget.setLauncher(launcher); 73 mDeleteDropTarget.setLauncher(launcher); 74 } 75 76 @Override 77 protected void onFinishInflate() { 78 super.onFinishInflate(); 79 80 // Get the individual components 81 mQSBSearchBar = findViewById(R.id.qsb_search_bar); 82 mDropTargetBar = findViewById(R.id.drag_target_bar); 83 mInfoDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.info_target_text); 84 mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target_text); 85 mBarHeight = getResources().getDimensionPixelSize(R.dimen.qsb_bar_height); 86 87 mInfoDropTarget.setSearchDropTargetBar(this); 88 mDeleteDropTarget.setSearchDropTargetBar(this); 89 90 boolean enableDropDownDropTargets = 91 getResources().getBoolean(R.bool.config_useDropTargetDownTransition); 92 93 // Create the various fade animations 94 mDropTargetBar.setAlpha(0f); 95 ObjectAnimator fadeInAlphaAnim = ObjectAnimator.ofFloat(mDropTargetBar, "alpha", 1f); 96 fadeInAlphaAnim.setInterpolator(new DecelerateInterpolator()); 97 mDropTargetBarFadeInAnim = new AnimatorSet(); 98 AnimatorSet.Builder fadeInAnimators = mDropTargetBarFadeInAnim.play(fadeInAlphaAnim); 99 if (enableDropDownDropTargets) { 100 mDropTargetBar.setTranslationY(-mBarHeight); 101 fadeInAnimators.with(ObjectAnimator.ofFloat(mDropTargetBar, "translationY", 0f)); 102 } 103 mDropTargetBarFadeInAnim.setDuration(sTransitionInDuration); 104 mDropTargetBarFadeInAnim.addListener(new AnimatorListenerAdapter() { 105 @Override 106 public void onAnimationStart(Animator animation) { 107 mDropTargetBar.setVisibility(View.VISIBLE); 108 } 109 }); 110 ObjectAnimator fadeOutAlphaAnim = ObjectAnimator.ofFloat(mDropTargetBar, "alpha", 0f); 111 fadeOutAlphaAnim.setInterpolator(new AccelerateInterpolator()); 112 mDropTargetBarFadeOutAnim = new AnimatorSet(); 113 AnimatorSet.Builder fadeOutAnimators = mDropTargetBarFadeOutAnim.play(fadeOutAlphaAnim); 114 if (enableDropDownDropTargets) { 115 fadeOutAnimators.with(ObjectAnimator.ofFloat(mDropTargetBar, "translationY", 116 -mBarHeight)); 117 } 118 mDropTargetBarFadeOutAnim.setDuration(sTransitionOutDuration); 119 mDropTargetBarFadeOutAnim.addListener(new AnimatorListenerAdapter() { 120 @Override 121 public void onAnimationEnd(Animator animation) { 122 mDropTargetBar.setVisibility(View.INVISIBLE); 123 mDropTargetBar.setLayerType(View.LAYER_TYPE_NONE, null); 124 } 125 }); 126 mQSBSearchBarFadeInAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 1f); 127 mQSBSearchBarFadeInAnim.setDuration(sTransitionInDuration); 128 mQSBSearchBarFadeInAnim.addListener(new AnimatorListenerAdapter() { 129 @Override 130 public void onAnimationStart(Animator animation) { 131 mQSBSearchBar.setVisibility(View.VISIBLE); 132 } 133 }); 134 mQSBSearchBarFadeOutAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 0f); 135 mQSBSearchBarFadeOutAnim.setDuration(sTransitionOutDuration); 136 mQSBSearchBarFadeOutAnim.addListener(new AnimatorListenerAdapter() { 137 @Override 138 public void onAnimationEnd(Animator animation) { 139 mQSBSearchBar.setVisibility(View.INVISIBLE); 140 } 141 }); 142 } 143 144 private void cancelAnimations() { 145 mDropTargetBarFadeInAnim.cancel(); 146 mDropTargetBarFadeOutAnim.cancel(); 147 mQSBSearchBarFadeInAnim.cancel(); 148 mQSBSearchBarFadeOutAnim.cancel(); 149 } 150 151 /* 152 * Shows and hides the search bar. 153 */ 154 public void showSearchBar(boolean animated) { 155 cancelAnimations(); 156 if (animated) { 157 mQSBSearchBarFadeInAnim.start(); 158 } else { 159 mQSBSearchBar.setVisibility(View.VISIBLE); 160 mQSBSearchBar.setAlpha(1f); 161 } 162 mIsSearchBarHidden = false; 163 } 164 public void hideSearchBar(boolean animated) { 165 cancelAnimations(); 166 if (animated) { 167 mQSBSearchBarFadeOutAnim.start(); 168 } else { 169 mQSBSearchBar.setVisibility(View.INVISIBLE); 170 mQSBSearchBar.setAlpha(0f); 171 } 172 mIsSearchBarHidden = true; 173 } 174 175 /* 176 * Gets various transition durations. 177 */ 178 public int getTransitionInDuration() { 179 return sTransitionInDuration; 180 } 181 public int getTransitionOutDuration() { 182 return sTransitionOutDuration; 183 } 184 185 /* 186 * DragController.DragListener implementation 187 */ 188 @Override 189 public void onDragStart(DragSource source, Object info, int dragAction) { 190 // Animate out the QSB search bar, and animate in the drop target bar 191 mDropTargetBar.setLayerType(View.LAYER_TYPE_HARDWARE, null); 192 mDropTargetBar.buildLayer(); 193 mDropTargetBarFadeOutAnim.cancel(); 194 mDropTargetBarFadeInAnim.start(); 195 if (!mIsSearchBarHidden) { 196 mQSBSearchBarFadeInAnim.cancel(); 197 mQSBSearchBarFadeOutAnim.start(); 198 } 199 } 200 201 public void deferOnDragEnd() { 202 mDeferOnDragEnd = true; 203 } 204 205 @Override 206 public void onDragEnd() { 207 if (!mDeferOnDragEnd) { 208 // Restore the QSB search bar, and animate out the drop target bar 209 mDropTargetBarFadeInAnim.cancel(); 210 mDropTargetBarFadeOutAnim.start(); 211 if (!mIsSearchBarHidden) { 212 mQSBSearchBarFadeOutAnim.cancel(); 213 mQSBSearchBarFadeInAnim.start(); 214 } 215 } else { 216 mDeferOnDragEnd = false; 217 } 218 } 219 220 public void onSearchPackagesChanged(boolean searchVisible, boolean voiceVisible) { 221 if (mQSBSearchBar != null) { 222 Drawable bg = mQSBSearchBar.getBackground(); 223 if (bg != null && (!searchVisible && !voiceVisible)) { 224 // Save the background and disable it 225 mPreviousBackground = bg; 226 mQSBSearchBar.setBackgroundResource(0); 227 } else if (mPreviousBackground != null && (searchVisible || voiceVisible)) { 228 // Restore the background 229 mQSBSearchBar.setBackgroundDrawable(mPreviousBackground); 230 } 231 } 232 } 233 234 public Rect getSearchBarBounds() { 235 if (mQSBSearchBar != null) { 236 final float appScale = mQSBSearchBar.getContext().getResources() 237 .getCompatibilityInfo().applicationScale; 238 final int[] pos = new int[2]; 239 mQSBSearchBar.getLocationOnScreen(pos); 240 241 final Rect rect = new Rect(); 242 rect.left = (int) (pos[0] * appScale + 0.5f); 243 rect.top = (int) (pos[1] * appScale + 0.5f); 244 rect.right = (int) ((pos[0] + mQSBSearchBar.getWidth()) * appScale + 0.5f); 245 rect.bottom = (int) ((pos[1] + mQSBSearchBar.getHeight()) * appScale + 0.5f); 246 return rect; 247 } else { 248 return null; 249 } 250 } 251 } 252