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 17package com.android.launcher2; 18 19import android.animation.Animator; 20import android.animation.AnimatorListenerAdapter; 21import android.animation.ObjectAnimator; 22import android.content.Context; 23import android.graphics.Rect; 24import android.graphics.drawable.Drawable; 25import android.util.AttributeSet; 26import android.view.View; 27import android.view.animation.AccelerateInterpolator; 28import android.widget.FrameLayout; 29 30import 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 */ 36public 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 57 public SearchDropTargetBar(Context context, AttributeSet attrs) { 58 this(context, attrs, 0); 59 } 60 61 public SearchDropTargetBar(Context context, AttributeSet attrs, int defStyle) { 62 super(context, attrs, defStyle); 63 } 64 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 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 } 81 82 private void setupAnimation(ObjectAnimator anim, final View v) { 83 anim.setInterpolator(sAccelerateInterpolator); 84 anim.setDuration(sTransitionInDuration); 85 anim.addListener(new AnimatorListenerAdapter() { 86 @Override 87 public void onAnimationEnd(Animator animation) { 88 v.setLayerType(View.LAYER_TYPE_NONE, null); 89 } 90 }); 91 } 92 93 @Override 94 protected void onFinishInflate() { 95 super.onFinishInflate(); 96 97 // Get the individual components 98 mQSBSearchBar = findViewById(R.id.qsb_search_bar); 99 mDropTargetBar = findViewById(R.id.drag_target_bar); 100 mInfoDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.info_target_text); 101 mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target_text); 102 mBarHeight = getResources().getDimensionPixelSize(R.dimen.qsb_bar_height); 103 104 mInfoDropTarget.setSearchDropTargetBar(this); 105 mDeleteDropTarget.setSearchDropTargetBar(this); 106 107 mEnableDropDownDropTargets = 108 getResources().getBoolean(R.bool.config_useDropTargetDownTransition); 109 110 // Create the various fade animations 111 if (mEnableDropDownDropTargets) { 112 mDropTargetBar.setTranslationY(-mBarHeight); 113 mDropTargetBarAnim = ObjectAnimator.ofFloat(mDropTargetBar, "translationY", -mBarHeight, 0f); 114 mQSBSearchBarAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "translationY", 0f, -mBarHeight); 115 } else { 116 mDropTargetBar.setAlpha(0f); 117 mDropTargetBarAnim = ObjectAnimator.ofFloat(mDropTargetBar, "alpha", 0f, 1f); 118 mQSBSearchBarAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 1f, 0f); 119 } 120 setupAnimation(mDropTargetBarAnim, mDropTargetBar); 121 setupAnimation(mQSBSearchBarAnim, mQSBSearchBar); 122 } 123 124 public void finishAnimations() { 125 prepareStartAnimation(mDropTargetBar); 126 mDropTargetBarAnim.reverse(); 127 prepareStartAnimation(mQSBSearchBar); 128 mQSBSearchBarAnim.reverse(); 129 } 130 131 /* 132 * Shows and hides the search bar. 133 */ 134 public void showSearchBar(boolean animated) { 135 if (!mIsSearchBarHidden) return; 136 if (animated) { 137 prepareStartAnimation(mQSBSearchBar); 138 mQSBSearchBarAnim.reverse(); 139 } else { 140 mQSBSearchBarAnim.cancel(); 141 if (mEnableDropDownDropTargets) { 142 mQSBSearchBar.setTranslationY(0); 143 } else { 144 mQSBSearchBar.setAlpha(1f); 145 } 146 } 147 mIsSearchBarHidden = false; 148 } 149 public void hideSearchBar(boolean animated) { 150 if (mIsSearchBarHidden) return; 151 if (animated) { 152 prepareStartAnimation(mQSBSearchBar); 153 mQSBSearchBarAnim.start(); 154 } else { 155 mQSBSearchBarAnim.cancel(); 156 if (mEnableDropDownDropTargets) { 157 mQSBSearchBar.setTranslationY(-mBarHeight); 158 } else { 159 mQSBSearchBar.setAlpha(0f); 160 } 161 } 162 mIsSearchBarHidden = true; 163 } 164 165 /* 166 * Gets various transition durations. 167 */ 168 public int getTransitionInDuration() { 169 return sTransitionInDuration; 170 } 171 public int getTransitionOutDuration() { 172 return sTransitionOutDuration; 173 } 174 175 /* 176 * DragController.DragListener implementation 177 */ 178 @Override 179 public void onDragStart(DragSource source, Object info, int dragAction) { 180 // Animate out the QSB search bar, and animate in the drop target bar 181 prepareStartAnimation(mDropTargetBar); 182 mDropTargetBarAnim.start(); 183 if (!mIsSearchBarHidden) { 184 prepareStartAnimation(mQSBSearchBar); 185 mQSBSearchBarAnim.start(); 186 } 187 } 188 189 public void deferOnDragEnd() { 190 mDeferOnDragEnd = true; 191 } 192 193 @Override 194 public void onDragEnd() { 195 if (!mDeferOnDragEnd) { 196 // Restore the QSB search bar, and animate out the drop target bar 197 prepareStartAnimation(mDropTargetBar); 198 mDropTargetBarAnim.reverse(); 199 if (!mIsSearchBarHidden) { 200 prepareStartAnimation(mQSBSearchBar); 201 mQSBSearchBarAnim.reverse(); 202 } 203 } else { 204 mDeferOnDragEnd = false; 205 } 206 } 207 208 public void onSearchPackagesChanged(boolean searchVisible, boolean voiceVisible) { 209 if (mQSBSearchBar != null) { 210 Drawable bg = mQSBSearchBar.getBackground(); 211 if (bg != null && (!searchVisible && !voiceVisible)) { 212 // Save the background and disable it 213 mPreviousBackground = bg; 214 mQSBSearchBar.setBackgroundResource(0); 215 } else if (mPreviousBackground != null && (searchVisible || voiceVisible)) { 216 // Restore the background 217 mQSBSearchBar.setBackground(mPreviousBackground); 218 } 219 } 220 } 221 222 public Rect getSearchBarBounds() { 223 if (mQSBSearchBar != null) { 224 final int[] pos = new int[2]; 225 mQSBSearchBar.getLocationOnScreen(pos); 226 227 final Rect rect = new Rect(); 228 rect.left = pos[0]; 229 rect.top = pos[1]; 230 rect.right = pos[0] + mQSBSearchBar.getWidth(); 231 rect.bottom = pos[1] + mQSBSearchBar.getHeight(); 232 return rect; 233 } else { 234 return null; 235 } 236 } 237} 238