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