blob: 992dceeef7fd5c101f99a27715a1f682121ce2d4 [file] [log] [blame]
Joe Onoratoddf680b2010-09-26 13:59:40 -07001/*
2 * Copyright (C) 2010 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.systemui.statusbar.tablet;
18
Joe Onorato7c270fa2010-12-08 17:31:42 -080019import android.animation.Animator;
Daniel Sandler14db0bc2011-01-20 12:11:23 -050020import android.animation.AnimatorListenerAdapter;
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -050021import android.animation.AnimatorSet;
Joe Onorato7c270fa2010-12-08 17:31:42 -080022import android.animation.ObjectAnimator;
Joe Onoratoddf680b2010-09-26 13:59:40 -070023import android.content.Context;
Joe Onorato7c270fa2010-12-08 17:31:42 -080024import android.graphics.Rect;
Joe Onoratoddf680b2010-09-26 13:59:40 -070025import android.util.AttributeSet;
Joe Onorato8a576712010-11-15 16:50:34 -080026import android.util.Slog;
Chris Wren9b2cd152012-06-11 10:39:36 -040027import android.view.Gravity;
Joe Onoratocf2b1992010-11-16 21:36:42 -080028import android.view.LayoutInflater;
Daniel Sandler8f491b52011-03-03 00:00:22 -050029import android.view.MotionEvent;
Joe Onorato8a576712010-11-15 16:50:34 -080030import android.view.View;
Joe Onorato7c270fa2010-12-08 17:31:42 -080031import android.view.ViewGroup;
Chet Haase41bff382011-08-29 16:00:23 -070032import android.view.ViewTreeObserver;
33import android.view.animation.AccelerateInterpolator;
34import android.view.animation.DecelerateInterpolator;
35import android.view.animation.Interpolator;
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -050036import android.widget.RelativeLayout;
Chris Wren9b2cd152012-06-11 10:39:36 -040037import android.widget.ScrollView;
Joe Onoratoddf680b2010-09-26 13:59:40 -070038
Chris Wren1e8f65d2012-06-06 18:08:56 -040039import com.android.systemui.ExpandHelper;
Joe Onoratofd52b182010-11-10 18:00:52 -080040import com.android.systemui.R;
Chris Wren1e8f65d2012-06-06 18:08:56 -040041import com.android.systemui.statusbar.policy.NotificationRowLayout;
Joe Onoratoddf680b2010-09-26 13:59:40 -070042
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -050043public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
Joe Onorato8a576712010-11-15 16:50:34 -080044 View.OnClickListener {
Chris Wren1e8f65d2012-06-06 18:08:56 -040045 private ExpandHelper mExpandHelper;
46 private NotificationRowLayout latestItems;
47
Daniel Sandleref6e9362010-12-17 14:50:03 -050048 static final String TAG = "Tablet/NotificationPanel";
49 static final boolean DEBUG = false;
Joe Onorato8a576712010-11-15 16:50:34 -080050
Daniel Sandler40c15452011-01-22 01:26:22 -050051 final static int PANEL_FADE_DURATION = 150;
52
Joe Onorato7c270fa2010-12-08 17:31:42 -080053 boolean mShowing;
Daniel Sandler06a0d4b2011-08-05 00:19:21 -040054 boolean mHasClearableNotifications = false;
Daniel Sandler40c15452011-01-22 01:26:22 -050055 int mNotificationCount = 0;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070056 NotificationPanelTitle mTitleArea;
Joe Onorato8a576712010-11-15 16:50:34 -080057 View mSettingsButton;
58 View mNotificationButton;
59 View mNotificationScroller;
Joe Onorato7c270fa2010-12-08 17:31:42 -080060 ViewGroup mContentFrame;
Joe Onorato6223fba2011-01-18 18:00:30 -080061 Rect mContentArea = new Rect();
Joe Onorato755cc742010-11-27 15:45:35 -080062 View mSettingsView;
Joe Onorato7c270fa2010-12-08 17:31:42 -080063 ViewGroup mContentParent;
Daniel Sandler1347c302011-08-01 16:47:53 -040064 TabletStatusBar mBar;
Daniel Sandler06a0d4b2011-08-05 00:19:21 -040065 View mClearButton;
Chet Haase41bff382011-08-29 16:00:23 -070066 static Interpolator sAccelerateInterpolator = new AccelerateInterpolator();
67 static Interpolator sDecelerateInterpolator = new DecelerateInterpolator();
Joe Onorato7c270fa2010-12-08 17:31:42 -080068
Daniel Sandler641a4992011-01-26 21:19:10 -050069 // amount to slide mContentParent down by when mContentFrame is missing
70 float mContentFrameMissingTranslation;
71
Joe Onorato7c270fa2010-12-08 17:31:42 -080072 Choreographer mChoreo = new Choreographer();
Joe Onorato8a576712010-11-15 16:50:34 -080073
Joe Onoratoddf680b2010-09-26 13:59:40 -070074 public NotificationPanel(Context context, AttributeSet attrs) {
75 this(context, attrs, 0);
76 }
77
78 public NotificationPanel(Context context, AttributeSet attrs, int defStyle) {
79 super(context, attrs, defStyle);
80 }
81
Daniel Sandler1347c302011-08-01 16:47:53 -040082 public void setBar(TabletStatusBar b) {
83 mBar = b;
84 }
85
Joe Onorato8a576712010-11-15 16:50:34 -080086 @Override
87 public void onFinishInflate() {
88 super.onFinishInflate();
89
Joe Onorato7c270fa2010-12-08 17:31:42 -080090 setWillNotDraw(false);
91
92 mContentParent = (ViewGroup)findViewById(R.id.content_parent);
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -050093 mContentParent.bringToFront();
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070094 mTitleArea = (NotificationPanelTitle) findViewById(R.id.title_area);
95 mTitleArea.setPanel(this);
Joe Onoratocf2b1992010-11-16 21:36:42 -080096
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070097 mSettingsButton = findViewById(R.id.settings_button);
98 mNotificationButton = findViewById(R.id.notification_button);
Joe Onorato8a576712010-11-15 16:50:34 -080099
Joe Onorato244e4152010-12-16 13:22:34 -0800100 mNotificationScroller = findViewById(R.id.notification_scroller);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800101 mContentFrame = (ViewGroup)findViewById(R.id.content_frame);
Daniel Sandler06a0d4b2011-08-05 00:19:21 -0400102 mContentFrameMissingTranslation = 0; // not needed with current assets
103
104 // the "X" that appears in place of the clock when the panel is showing notifications
105 mClearButton = findViewById(R.id.clear_all_button);
106 mClearButton.setOnClickListener(mClearButtonListener);
Daniel Sandler641a4992011-01-26 21:19:10 -0500107
108 mShowing = false;
109
110 setContentFrameVisible(mNotificationCount > 0, false);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800111 }
112
Chris Wren1e8f65d2012-06-06 18:08:56 -0400113 @Override
114 protected void onAttachedToWindow () {
115 super.onAttachedToWindow();
116 latestItems = (NotificationRowLayout) findViewById(R.id.content);
117 int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
118 int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
119 mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight);
120 mExpandHelper.setEventSource(this);
Chris Wren9b2cd152012-06-11 10:39:36 -0400121 mExpandHelper.setGravity(Gravity.BOTTOM);
Chris Wren1e8f65d2012-06-06 18:08:56 -0400122 }
123
Daniel Sandler06a0d4b2011-08-05 00:19:21 -0400124 private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
125 public void onClick(View v) {
126 mBar.clearAll();
127 }
128 };
129
130 public View getClearButton() {
131 return mClearButton;
132 }
133
Joe Onorato7c270fa2010-12-08 17:31:42 -0800134 public void show(boolean show, boolean animate) {
Daniel Sandler40c15452011-01-22 01:26:22 -0500135 if (show && !mShowing) {
Daniel Sandler641a4992011-01-26 21:19:10 -0500136 setContentFrameVisible(mSettingsView != null || mNotificationCount > 0, false);
Daniel Sandler40c15452011-01-22 01:26:22 -0500137 }
138
Joe Onorato7c270fa2010-12-08 17:31:42 -0800139 if (animate) {
140 if (mShowing != show) {
141 mShowing = show;
142 if (show) {
143 setVisibility(View.VISIBLE);
Chet Haase41bff382011-08-29 16:00:23 -0700144 // Don't start the animation until we've created the layer, which is done
145 // right before we are drawn
146 mContentParent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
147 getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
148 } else {
149 mChoreo.startAnimation(show);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800150 }
Joe Onorato7c270fa2010-12-08 17:31:42 -0800151 }
152 } else {
153 mShowing = show;
154 setVisibility(show ? View.VISIBLE : View.GONE);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800155 }
156 }
157
158 /**
Chet Haase41bff382011-08-29 16:00:23 -0700159 * This is used only when we've created a hardware layer and are waiting until it's
160 * been created in order to start the appearing animation.
161 */
162 private ViewTreeObserver.OnPreDrawListener mPreDrawListener =
163 new ViewTreeObserver.OnPreDrawListener() {
164 @Override
165 public boolean onPreDraw() {
166 getViewTreeObserver().removeOnPreDrawListener(this);
167 mChoreo.startAnimation(true);
Chet Haase3c4ce722011-09-02 15:37:25 -0700168 return false;
Chet Haase41bff382011-08-29 16:00:23 -0700169 }
170 };
171
172 /**
Joe Onorato7c270fa2010-12-08 17:31:42 -0800173 * Whether the panel is showing, or, if it's animating, whether it will be
174 * when the animation is done.
175 */
176 public boolean isShowing() {
177 return mShowing;
Joe Onorato8a576712010-11-15 16:50:34 -0800178 }
179
180 @Override
181 public void onVisibilityChanged(View v, int vis) {
182 super.onVisibilityChanged(v, vis);
183 // when we hide, put back the notifications
Daniel Sandler641a4992011-01-26 21:19:10 -0500184 if (vis != View.VISIBLE) {
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500185 if (mSettingsView != null) removeSettingsView();
186 mNotificationScroller.setVisibility(View.VISIBLE);
187 mNotificationScroller.setAlpha(1f);
Joe Onorato43861912010-11-27 16:08:58 -0800188 mNotificationScroller.scrollTo(0, 0);
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500189 updatePanelModeButtons();
Joe Onorato8a576712010-11-15 16:50:34 -0800190 }
191 }
192
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700193 @Override
194 public boolean dispatchHoverEvent(MotionEvent event) {
195 // Ignore hover events outside of this panel bounds since such events
196 // generate spurious accessibility events with the panel content when
197 // tapping outside of it, thus confusing the user.
198 final int x = (int) event.getX();
199 final int y = (int) event.getY();
200 if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
201 return super.dispatchHoverEvent(event);
202 }
203 return true;
204 }
205
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500206 /*
Joe Onorato4cddc982010-11-21 11:48:15 -0800207 @Override
208 protected void onLayout(boolean changed, int l, int t, int r, int b) {
209 super.onLayout(changed, l, t, r, b);
Daniel Sandler2f447aa2011-01-14 16:39:19 -0500210
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500211 if (DEBUG) Slog.d(TAG, String.format("PANEL: onLayout: (%d, %d, %d, %d)", l, t, r, b));
Joe Onorato7c270fa2010-12-08 17:31:42 -0800212 }
213
214 @Override
215 public void onSizeChanged(int w, int h, int oldw, int oldh) {
216 super.onSizeChanged(w, h, oldw, oldh);
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500217
218 if (DEBUG) {
219 Slog.d(TAG, String.format("PANEL: onSizeChanged: (%d -> %d, %d -> %d)",
220 oldw, w, oldh, h));
221 }
Joe Onorato4cddc982010-11-21 11:48:15 -0800222 }
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500223 */
Joe Onorato4cddc982010-11-21 11:48:15 -0800224
Joe Onorato8a576712010-11-15 16:50:34 -0800225 public void onClick(View v) {
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700226 if (v == mTitleArea) {
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500227 swapPanels();
Joe Onorato8a576712010-11-15 16:50:34 -0800228 }
229 }
230
Daniel Sandler40c15452011-01-22 01:26:22 -0500231 public void setNotificationCount(int n) {
Daniel Sandler0ffc2302011-03-02 14:33:09 -0500232// Slog.d(TAG, "notificationCount=" + n);
Daniel Sandler40c15452011-01-22 01:26:22 -0500233 if (!mShowing) {
234 // just do it, already
235 setContentFrameVisible(n > 0, false);
236 } else if (mSettingsView == null) {
237 // we're looking at the notifications; time to maybe make some changes
Daniel Sandler2c831802011-01-30 21:26:24 -0500238 if ((mNotificationCount > 0) != (n > 0)) {
Daniel Sandler641a4992011-01-26 21:19:10 -0500239 setContentFrameVisible(n > 0, true);
Daniel Sandler40c15452011-01-22 01:26:22 -0500240 }
241 }
242 mNotificationCount = n;
243 }
244
245 public void setContentFrameVisible(final boolean showing, boolean animate) {
246 if (!animate) {
247 mContentFrame.setVisibility(showing ? View.VISIBLE : View.GONE);
Daniel Sandler641a4992011-01-26 21:19:10 -0500248 mContentFrame.setAlpha(1f);
249 // the translation will be patched up when the window is slid into place
Daniel Sandler40c15452011-01-22 01:26:22 -0500250 return;
251 }
252
Daniel Sandler641a4992011-01-26 21:19:10 -0500253 if (showing) {
254 mContentFrame.setVisibility(View.VISIBLE);
255 }
Daniel Sandler40c15452011-01-22 01:26:22 -0500256 AnimatorSet set = new AnimatorSet();
Daniel Sandler40c15452011-01-22 01:26:22 -0500257 set.play(ObjectAnimator.ofFloat(
258 mContentFrame, "alpha",
259 showing ? 0f : 1f,
260 showing ? 1f : 0f))
261 .with(ObjectAnimator.ofFloat(
262 mContentParent, "translationY",
Daniel Sandler641a4992011-01-26 21:19:10 -0500263 showing ? mContentFrameMissingTranslation : 0f,
264 showing ? 0f : mContentFrameMissingTranslation))
265 ;
266
Daniel Sandler40c15452011-01-22 01:26:22 -0500267 set.setDuration(200);
Daniel Sandler1347c302011-08-01 16:47:53 -0400268 set.addListener(new AnimatorListenerAdapter() {
269 @Override
270 public void onAnimationEnd(Animator _a) {
271 if (!showing) {
Daniel Sandler641a4992011-01-26 21:19:10 -0500272 mContentFrame.setVisibility(View.GONE);
273 mContentFrame.setAlpha(1f);
274 }
Daniel Sandler1347c302011-08-01 16:47:53 -0400275 updateClearButton();
276 }
277 });
Daniel Sandler40c15452011-01-22 01:26:22 -0500278 set.start();
279 }
Joe Onorato8a576712010-11-15 16:50:34 -0800280
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500281 public void swapPanels() {
282 final View toShow, toHide;
283 if (mSettingsView == null) {
284 addSettingsView();
285 toShow = mSettingsView;
286 toHide = mNotificationScroller;
287 } else {
288 toShow = mNotificationScroller;
289 toHide = mSettingsView;
290 }
291 Animator a = ObjectAnimator.ofFloat(toHide, "alpha", 1f, 0f)
292 .setDuration(PANEL_FADE_DURATION);
293 a.addListener(new AnimatorListenerAdapter() {
294 @Override
295 public void onAnimationEnd(Animator _a) {
296 toHide.setVisibility(View.GONE);
Daniel Sandler40c15452011-01-22 01:26:22 -0500297 if (toShow != null) {
298 if (mNotificationCount == 0) {
299 // show the frame for settings, hide for notifications
300 setContentFrameVisible(toShow == mSettingsView, true);
301 }
302
303 toShow.setVisibility(View.VISIBLE);
304 if (toShow == mSettingsView || mNotificationCount > 0) {
305 ObjectAnimator.ofFloat(toShow, "alpha", 0f, 1f)
306 .setDuration(PANEL_FADE_DURATION)
307 .start();
308 }
309
310 if (toHide == mSettingsView) {
311 removeSettingsView();
312 }
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500313 }
Daniel Sandler1347c302011-08-01 16:47:53 -0400314 updateClearButton();
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500315 updatePanelModeButtons();
316 }
317 });
318 a.start();
319 }
320
Daniel Sandler1347c302011-08-01 16:47:53 -0400321 public void updateClearButton() {
322 if (mBar != null) {
323 final boolean showX
324 = (isShowing()
Daniel Sandler06a0d4b2011-08-05 00:19:21 -0400325 && mHasClearableNotifications
326 && mNotificationScroller.getVisibility() == View.VISIBLE);
327 getClearButton().setVisibility(showX ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler1347c302011-08-01 16:47:53 -0400328 }
329 }
330
Daniel Sandler06a0d4b2011-08-05 00:19:21 -0400331 public void setClearable(boolean clearable) {
332 mHasClearableNotifications = clearable;
333 }
334
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500335 public void updatePanelModeButtons() {
336 final boolean settingsVisible = (mSettingsView != null);
Daniel Sandler5962fd52012-01-11 14:57:04 -0500337 mSettingsButton.setVisibility(!settingsVisible ? View.VISIBLE : View.GONE);
338 mNotificationButton.setVisibility(settingsVisible ? View.VISIBLE : View.GONE);
Joe Onorato8a576712010-11-15 16:50:34 -0800339 }
340
Joe Onoratoddf680b2010-09-26 13:59:40 -0700341 public boolean isInContentArea(int x, int y) {
Chris Wren1e8f65d2012-06-06 18:08:56 -0400342 mContentArea.left = mContentFrame.getLeft() + mContentFrame.getPaddingLeft();
343 mContentArea.top = mContentFrame.getTop() + mContentFrame.getPaddingTop()
Daniel Sandler641a4992011-01-26 21:19:10 -0500344 + (int)mContentParent.getTranslationY(); // account for any adjustment
Chris Wren1e8f65d2012-06-06 18:08:56 -0400345 mContentArea.right = mContentFrame.getRight() - mContentFrame.getPaddingRight();
346 mContentArea.bottom = mContentFrame.getBottom() - mContentFrame.getPaddingBottom();
Daniel Sandler641a4992011-01-26 21:19:10 -0500347
Joe Onorato6223fba2011-01-18 18:00:30 -0800348 offsetDescendantRectToMyCoords(mContentParent, mContentArea);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800349 return mContentArea.contains(x, y);
Joe Onoratoddf680b2010-09-26 13:59:40 -0700350 }
Joe Onorato8a576712010-11-15 16:50:34 -0800351
Joe Onorato755cc742010-11-27 15:45:35 -0800352 void removeSettingsView() {
353 if (mSettingsView != null) {
354 mContentFrame.removeView(mSettingsView);
355 mSettingsView = null;
Joe Onorato8a576712010-11-15 16:50:34 -0800356 }
357 }
358
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500359 // NB: it will be invisible until you show it
Joe Onorato755cc742010-11-27 15:45:35 -0800360 void addSettingsView() {
Joe Onoratocf2b1992010-11-16 21:36:42 -0800361 LayoutInflater infl = LayoutInflater.from(getContext());
Daniel Sandler4a066c52012-04-20 14:49:13 -0400362 mSettingsView = infl.inflate(R.layout.system_bar_settings_view, mContentFrame, false);
Daniel Sandler14db0bc2011-01-20 12:11:23 -0500363 mSettingsView.setVisibility(View.GONE);
Daniel Sandler2f447aa2011-01-14 16:39:19 -0500364 mContentFrame.addView(mSettingsView);
Joe Onorato8a576712010-11-15 16:50:34 -0800365 }
Joe Onorato7c270fa2010-12-08 17:31:42 -0800366
367 private class Choreographer implements Animator.AnimatorListener {
Joe Onorato244e4152010-12-16 13:22:34 -0800368 boolean mVisible;
Joe Onorato7c270fa2010-12-08 17:31:42 -0800369 int mPanelHeight;
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500370 AnimatorSet mContentAnim;
Joe Onorato7c270fa2010-12-08 17:31:42 -0800371
372 // should group this into a multi-property animation
Chet Haase41bff382011-08-29 16:00:23 -0700373 final static int OPEN_DURATION = 250;
374 final static int CLOSE_DURATION = 250;
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500375
376 // the panel will start to appear this many px from the end
Daniel Sandler1347c302011-08-01 16:47:53 -0400377 final int HYPERSPACE_OFFRAMP = 200;
Joe Onorato7c270fa2010-12-08 17:31:42 -0800378
379 Choreographer() {
380 }
381
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500382 void createAnimation(boolean appearing) {
Daniel Sandleradd26202011-01-20 02:53:43 -0500383 // mVisible: previous state; appearing: new state
384
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500385 float start, end;
Joe Onorato7c270fa2010-12-08 17:31:42 -0800386
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500387 // 0: on-screen
388 // height: off-screen
389 float y = mContentParent.getTranslationY();
390 if (appearing) {
391 // we want to go from near-the-top to the top, unless we're half-open in the right
392 // general vicinity
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500393 end = 0;
Daniel Sandler641a4992011-01-26 21:19:10 -0500394 if (mNotificationCount == 0) {
395 end += mContentFrameMissingTranslation;
396 }
Daniel Sandler8c989182011-01-30 01:24:09 -0500397 start = HYPERSPACE_OFFRAMP+end;
Joe Onorato7c270fa2010-12-08 17:31:42 -0800398 } else {
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500399 start = y;
400 end = y + HYPERSPACE_OFFRAMP;
Joe Onorato7c270fa2010-12-08 17:31:42 -0800401 }
Daniel Sandler641a4992011-01-26 21:19:10 -0500402
Daniel Sandleradd26202011-01-20 02:53:43 -0500403 Animator posAnim = ObjectAnimator.ofFloat(mContentParent, "translationY",
404 start, end);
Chet Haase41bff382011-08-29 16:00:23 -0700405 posAnim.setInterpolator(appearing ? sDecelerateInterpolator : sAccelerateInterpolator);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800406
Daniel Sandlerf844dc42011-01-24 23:44:47 -0500407 if (mContentAnim != null && mContentAnim.isRunning()) {
408 mContentAnim.cancel();
409 }
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500410
Daniel Sandler8c989182011-01-30 01:24:09 -0500411 Animator fadeAnim = ObjectAnimator.ofFloat(mContentParent, "alpha",
Chet Haase41bff382011-08-29 16:00:23 -0700412 appearing ? 1.0f : 0.0f);
413 fadeAnim.setInterpolator(appearing ? sAccelerateInterpolator : sDecelerateInterpolator);
Daniel Sandler8c989182011-01-30 01:24:09 -0500414
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500415 mContentAnim = new AnimatorSet();
416 mContentAnim
Daniel Sandler8c989182011-01-30 01:24:09 -0500417 .play(fadeAnim)
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500418 .with(posAnim)
419 ;
Daniel Sandleradd26202011-01-20 02:53:43 -0500420 mContentAnim.setDuration((DEBUG?10:1)*(appearing ? OPEN_DURATION : CLOSE_DURATION));
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500421 mContentAnim.addListener(this);
422 }
423
424 void startAnimation(boolean appearing) {
425 if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
426
427 createAnimation(appearing);
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500428 mContentAnim.start();
429
430 mVisible = appearing;
Daniel Sandler1347c302011-08-01 16:47:53 -0400431
432 // we want to start disappearing promptly
433 if (!mVisible) updateClearButton();
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500434 }
435
Joe Onorato7c270fa2010-12-08 17:31:42 -0800436 public void onAnimationCancel(Animator animation) {
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500437 if (DEBUG) Slog.d(TAG, "onAnimationCancel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800438 }
439
440 public void onAnimationEnd(Animator animation) {
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500441 if (DEBUG) Slog.d(TAG, "onAnimationEnd");
442 if (! mVisible) {
Joe Onorato7c270fa2010-12-08 17:31:42 -0800443 setVisibility(View.GONE);
444 }
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500445 mContentParent.setLayerType(View.LAYER_TYPE_NONE, null);
446 mContentAnim = null;
Daniel Sandler1347c302011-08-01 16:47:53 -0400447
448 // we want to show the X lazily
449 if (mVisible) updateClearButton();
Joe Onorato7c270fa2010-12-08 17:31:42 -0800450 }
451
452 public void onAnimationRepeat(Animator animation) {
453 }
454
455 public void onAnimationStart(Animator animation) {
456 }
457 }
Chris Wren1e8f65d2012-06-06 18:08:56 -0400458
459 @Override
460 public boolean onInterceptTouchEvent(MotionEvent ev) {
461 MotionEvent cancellation = MotionEvent.obtain(ev);
462 cancellation.setAction(MotionEvent.ACTION_CANCEL);
463
464 boolean intercept = mExpandHelper.onInterceptTouchEvent(ev) ||
465 super.onInterceptTouchEvent(ev);
466 if (intercept) {
467 latestItems.onInterceptTouchEvent(cancellation);
468 }
469 return intercept;
470 }
471
472 @Override
473 public boolean onTouchEvent(MotionEvent ev) {
474 boolean handled = mExpandHelper.onTouchEvent(ev) ||
475 super.onTouchEvent(ev);
476 return handled;
477 }
Joe Onoratoddf680b2010-09-26 13:59:40 -0700478}
479