blob: 2d96373a18bb15b5f678c99197f117b2e3a719ef [file] [log] [blame]
Daniel Sandler08d05e32012-08-08 16:39:54 -04001/*
2 * Copyright (C) 2012 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.phone;
18
Jorim Jaggid7daab72014-05-06 22:22:20 +020019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.ValueAnimator;
Daniel Sandler08d05e32012-08-08 16:39:54 -040022import android.content.Context;
23import android.util.AttributeSet;
Daniel Sandler040c2e42012-10-17 00:56:33 -040024import android.view.MotionEvent;
Jorim Jaggid7daab72014-05-06 22:22:20 +020025import android.view.VelocityTracker;
Daniel Sandler13522a22012-09-27 14:46:58 -040026import android.view.View;
Jorim Jaggi0d74eeb2014-05-09 22:05:24 +020027import android.view.ViewGroup;
Casey Burkhardt23b0a4e2013-04-29 12:18:32 -070028import android.view.accessibility.AccessibilityEvent;
Jorim Jaggid7daab72014-05-06 22:22:20 +020029import android.view.animation.AnimationUtils;
30import android.view.animation.Interpolator;
Jorim Jaggi0d74eeb2014-05-09 22:05:24 +020031import android.widget.LinearLayout;
Daniel Sandler13522a22012-09-27 14:46:58 -040032
Chet Haase4d179dc2012-08-22 07:14:42 -070033import com.android.systemui.R;
Jorim Jaggibe565df2014-04-28 17:51:23 +020034import com.android.systemui.statusbar.ExpandableView;
Daniel Sandler151f00d2012-10-02 22:33:08 -040035import com.android.systemui.statusbar.GestureRecorder;
Jorim Jaggiecbab362014-04-23 16:13:15 +020036import com.android.systemui.statusbar.StatusBarState;
Selim Cinekb6d85eb2014-03-28 20:21:01 +010037import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Daniel Sandler08d05e32012-08-08 16:39:54 -040038
Jorim Jaggibe565df2014-04-28 17:51:23 +020039public class NotificationPanelView extends PanelView implements
Jorim Jaggid7daab72014-05-06 22:22:20 +020040 ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
41 View.OnClickListener {
Chris Wren64161cc2012-12-17 16:49:30 -050042 public static final boolean DEBUG_GESTURES = true;
Jorim Jaggid7daab72014-05-06 22:22:20 +020043 private static final int EXPANSION_ANIMATION_LENGTH = 375;
Chet Haase4d179dc2012-08-22 07:14:42 -070044
Daniel Sandler040c2e42012-10-17 00:56:33 -040045 PhoneStatusBar mStatusBar;
Jorim Jaggid7daab72014-05-06 22:22:20 +020046 private StatusBarHeaderView mHeader;
47 private QuickSettingsContainerView mQsContainer;
John Spurlock73203eb2014-04-15 16:14:46 -040048 private View mKeyguardStatusView;
Jorim Jaggid7daab72014-05-06 22:22:20 +020049 private ObservableScrollView mScrollView;
50 private View mStackScrollerContainer;
John Spurlock73203eb2014-04-15 16:14:46 -040051
Selim Cinekb6d85eb2014-03-28 20:21:01 +010052 private NotificationStackScrollLayout mNotificationStackScroller;
Jorim Jaggi8c1a44b2014-04-29 19:04:02 +020053 private int mNotificationTopPadding;
Jorim Jaggi98fb09c2014-05-01 22:40:56 +020054 private boolean mAnimateNextTopPaddingChange;
Chet Haase4d179dc2012-08-22 07:14:42 -070055
Jorim Jaggid7daab72014-05-06 22:22:20 +020056 private Interpolator mExpansionInterpolator;
57
58 private int mTrackingPointer;
59 private VelocityTracker mVelocityTracker;
60 private boolean mTracking;
61 private boolean mQsExpanded;
62 private float mInitialHeightOnTouch;
63 private float mInitialTouchX;
64 private float mInitialTouchY;
65 private float mQsExpansionHeight;
66 private int mQsMinExpansionHeight;
67 private int mQsMaxExpansionHeight;
68 private int mMinStackHeight;
69 private float mNotificationTranslation;
70 private int mStackScrollerIntrinsicPadding;
71 private boolean mQsExpansionEnabled = true;
72 private ValueAnimator mQsExpansionAnimator;
73
Daniel Sandler08d05e32012-08-08 16:39:54 -040074 public NotificationPanelView(Context context, AttributeSet attrs) {
75 super(context, attrs);
Daniel Sandler13522a22012-09-27 14:46:58 -040076 }
Chet Haase4d179dc2012-08-22 07:14:42 -070077
Daniel Sandler040c2e42012-10-17 00:56:33 -040078 public void setStatusBar(PhoneStatusBar bar) {
Selim Cinekb6d85eb2014-03-28 20:21:01 +010079 if (mStatusBar != null) {
80 mStatusBar.setOnFlipRunnable(null);
81 }
Daniel Sandler040c2e42012-10-17 00:56:33 -040082 mStatusBar = bar;
Selim Cinekb6d85eb2014-03-28 20:21:01 +010083 if (bar != null) {
84 mStatusBar.setOnFlipRunnable(new Runnable() {
85 @Override
86 public void run() {
87 requestPanelHeightUpdate();
88 }
89 });
90 }
Daniel Sandler040c2e42012-10-17 00:56:33 -040091 }
92
Daniel Sandler13522a22012-09-27 14:46:58 -040093 @Override
94 protected void onFinishInflate() {
95 super.onFinishInflate();
Jorim Jaggid7daab72014-05-06 22:22:20 +020096 mHeader = (StatusBarHeaderView) findViewById(R.id.header);
97 mHeader.getBackgroundView().setOnClickListener(this);
Jorim Jaggi3d878be2014-05-10 03:22:32 +020098 mHeader.setOverlayParent(this);
John Spurlock73203eb2014-04-15 16:14:46 -040099 mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
Jorim Jaggid7daab72014-05-06 22:22:20 +0200100 mStackScrollerContainer = findViewById(R.id.notification_container_parent);
101 mQsContainer = (QuickSettingsContainerView) findViewById(R.id.quick_settings_container);
102 mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
103 mScrollView.setListener(this);
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100104 mNotificationStackScroller = (NotificationStackScrollLayout)
105 findViewById(R.id.notification_stack_scroller);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200106 mNotificationStackScroller.setOnHeightChangedListener(this);
Jorim Jaggi8c1a44b2014-04-29 19:04:02 +0200107 mNotificationTopPadding = getResources().getDimensionPixelSize(
108 R.dimen.notifications_top_padding);
Jorim Jaggid7daab72014-05-06 22:22:20 +0200109 mMinStackHeight = getResources().getDimensionPixelSize(R.dimen.collapsed_stack_height);
110 mExpansionInterpolator = AnimationUtils.loadInterpolator(
111 getContext(), android.R.interpolator.fast_out_slow_in);
Jorim Jaggi8c1a44b2014-04-29 19:04:02 +0200112 }
113
114 @Override
115 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
116 super.onLayout(changed, left, top, right, bottom);
117 int keyguardBottomMargin =
118 ((MarginLayoutParams) mKeyguardStatusView.getLayoutParams()).bottomMargin;
Jorim Jaggid7daab72014-05-06 22:22:20 +0200119 if (!mQsExpanded) {
120 mStackScrollerIntrinsicPadding = mStatusBar.getBarState() == StatusBarState.KEYGUARD
121 ? mKeyguardStatusView.getBottom() + keyguardBottomMargin
122 : mHeader.getBottom() + mNotificationTopPadding;
123 mNotificationStackScroller.setTopPadding(mStackScrollerIntrinsicPadding,
124 mAnimateNextTopPaddingChange);
125 mAnimateNextTopPaddingChange = false;
126 }
127
128 // Calculate quick setting heights.
129 mQsMinExpansionHeight = mHeader.getCollapsedHeight();
130 mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight();
131 if (mQsExpansionHeight == 0) {
132 mQsExpansionHeight = mQsMinExpansionHeight;
133 }
Jorim Jaggi98fb09c2014-05-01 22:40:56 +0200134 }
135
136 public void animateNextTopPaddingChange() {
137 mAnimateNextTopPaddingChange = true;
138 requestLayout();
Daniel Sandler08d05e32012-08-08 16:39:54 -0400139 }
140
Jorim Jaggid7daab72014-05-06 22:22:20 +0200141 /**
142 * @return Whether Quick Settings are currently expanded.
143 */
144 public boolean isQsExpanded() {
145 return mQsExpanded;
146 }
147
148 public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
149 mQsExpansionEnabled = qsExpansionEnabled;
Jorim Jaggid7daab72014-05-06 22:22:20 +0200150 }
151
152 public void closeQs() {
153 cancelAnimation();
154 setQsExpansion(mQsMinExpansionHeight);
155 }
156
157 public void openQs() {
158 cancelAnimation();
159 if (mQsExpansionEnabled) {
160 setQsExpansion(mQsMaxExpansionHeight);
161 }
162 }
163
Daniel Sandler08d05e32012-08-08 16:39:54 -0400164 @Override
165 public void fling(float vel, boolean always) {
Daniel Sandler151f00d2012-10-02 22:33:08 -0400166 GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
167 if (gr != null) {
168 gr.tag(
169 "fling " + ((vel > 0) ? "open" : "closed"),
170 "notifications,v=" + vel);
171 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400172 super.fling(vel, always);
173 }
Chet Haase4d179dc2012-08-22 07:14:42 -0700174
Casey Burkhardt23b0a4e2013-04-29 12:18:32 -0700175 @Override
176 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
177 if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
178 event.getText()
179 .add(getContext().getString(R.string.accessibility_desc_notification_shade));
180 return true;
181 }
182
183 return super.dispatchPopulateAccessibilityEvent(event);
184 }
185
Daniel Sandler040c2e42012-10-17 00:56:33 -0400186 @Override
John Spurlock73203eb2014-04-15 16:14:46 -0400187 public boolean onInterceptTouchEvent(MotionEvent event) {
Jorim Jaggid7daab72014-05-06 22:22:20 +0200188 int pointerIndex = event.findPointerIndex(mTrackingPointer);
189 if (pointerIndex < 0) {
190 pointerIndex = 0;
191 mTrackingPointer = event.getPointerId(pointerIndex);
John Spurlock73203eb2014-04-15 16:14:46 -0400192 }
Jorim Jaggid7daab72014-05-06 22:22:20 +0200193 final float x = event.getX(pointerIndex);
194 final float y = event.getY(pointerIndex);
195
196 switch (event.getActionMasked()) {
197 case MotionEvent.ACTION_DOWN:
198 mInitialTouchY = y;
199 mInitialTouchX = x;
200 initVelocityTracker();
201 trackMovement(event);
202 if (shouldIntercept(mInitialTouchX, mInitialTouchY, 0)) {
203 getParent().requestDisallowInterceptTouchEvent(true);
204 }
205 break;
206 case MotionEvent.ACTION_POINTER_UP:
207 final int upPointer = event.getPointerId(event.getActionIndex());
208 if (mTrackingPointer == upPointer) {
209 // gesture is ongoing, find a new pointer to track
210 final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
211 mTrackingPointer = event.getPointerId(newIndex);
212 mInitialTouchX = event.getX(newIndex);
213 mInitialTouchY = event.getY(newIndex);
214 }
215 break;
216
217 case MotionEvent.ACTION_MOVE:
218 final float h = y - mInitialTouchY;
219 trackMovement(event);
220 if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX)
221 && shouldIntercept(mInitialTouchX, mInitialTouchY, h)) {
222 onQsExpansionStarted();
223 mInitialHeightOnTouch = mQsExpansionHeight;
224 mInitialTouchY = y;
225 mInitialTouchX = x;
226 mTracking = true;
227 return true;
228 }
229 break;
230 }
231 return !mQsExpanded && super.onInterceptTouchEvent(event);
John Spurlock73203eb2014-04-15 16:14:46 -0400232 }
233
234 @Override
Daniel Sandler040c2e42012-10-17 00:56:33 -0400235 public boolean onTouchEvent(MotionEvent event) {
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100236 // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
237 // implementation.
Jorim Jaggid7daab72014-05-06 22:22:20 +0200238 if (mTracking) {
239 int pointerIndex = event.findPointerIndex(mTrackingPointer);
240 if (pointerIndex < 0) {
241 pointerIndex = 0;
242 mTrackingPointer = event.getPointerId(pointerIndex);
243 }
244 final float y = event.getY(pointerIndex);
245 final float x = event.getX(pointerIndex);
246
247 switch (event.getActionMasked()) {
248 case MotionEvent.ACTION_DOWN:
249 mTracking = true;
250 mInitialTouchY = y;
251 mInitialTouchX = x;
252 onQsExpansionStarted();
253 mInitialHeightOnTouch = mQsExpansionHeight;
254 initVelocityTracker();
255 trackMovement(event);
256 break;
257
258 case MotionEvent.ACTION_POINTER_UP:
259 final int upPointer = event.getPointerId(event.getActionIndex());
260 if (mTrackingPointer == upPointer) {
261 // gesture is ongoing, find a new pointer to track
262 final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
263 final float newY = event.getY(newIndex);
264 final float newX = event.getX(newIndex);
265 mTrackingPointer = event.getPointerId(newIndex);
266 mInitialHeightOnTouch = mQsExpansionHeight;
267 mInitialTouchY = newY;
268 mInitialTouchX = newX;
269 }
270 break;
271
272 case MotionEvent.ACTION_MOVE:
273 final float h = y - mInitialTouchY;
274 setQsExpansion(h + mInitialHeightOnTouch);
275 trackMovement(event);
276 break;
277
278 case MotionEvent.ACTION_UP:
279 case MotionEvent.ACTION_CANCEL:
280 mTracking = false;
281 mTrackingPointer = -1;
282 trackMovement(event);
283
284 float vel = getCurrentVelocity();
285
286 // TODO: Better logic whether we should expand or not.
287 flingSettings(vel, vel > 0);
288
289 if (mVelocityTracker != null) {
290 mVelocityTracker.recycle();
291 mVelocityTracker = null;
292 }
293 break;
John Spurlock73203eb2014-04-15 16:14:46 -0400294 }
295 return true;
296 }
Jorim Jaggid7daab72014-05-06 22:22:20 +0200297
298 // Consume touch events when QS are expanded.
299 return mQsExpanded || super.onTouchEvent(event);
300 }
301
302 private void onQsExpansionStarted() {
303 cancelAnimation();
304
305 // Reset scroll position and apply that position to the expanded height.
306 float height = mQsExpansionHeight - mScrollView.getScrollY();
307 mScrollView.scrollTo(0, 0);
308 setQsExpansion(height);
309 }
310
311 private void expandQs() {
312 mHeader.setExpanded(true);
313 mNotificationStackScroller.setEnabled(false);
314 mScrollView.setVisibility(View.VISIBLE);
315 mQsExpanded = true;
316 }
317
318 private void collapseQs() {
319 mHeader.setExpanded(false);
320 mNotificationStackScroller.setEnabled(true);
321 mScrollView.setVisibility(View.INVISIBLE);
322 mQsExpanded = false;
323 }
324
325 private void setQsExpansion(float height) {
326 height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
327 if (height > mQsMinExpansionHeight && !mQsExpanded) {
328 expandQs();
329 } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
330 collapseQs();
John Spurlock73203eb2014-04-15 16:14:46 -0400331 }
Jorim Jaggid7daab72014-05-06 22:22:20 +0200332 mQsExpansionHeight = height;
333 mHeader.setExpansion(height);
334 setQsTranslation(height);
335 setQsStackScrollerPadding(height);
336 }
337
338 private void setQsTranslation(float height) {
339 mQsContainer.setY(height - mQsContainer.getHeight());
340 }
341
342 private void setQsStackScrollerPadding(float height) {
343 float start = height - mScrollView.getScrollY() + mNotificationTopPadding;
344 float stackHeight = mNotificationStackScroller.getHeight() - start;
345 if (stackHeight <= mMinStackHeight) {
346 float overflow = mMinStackHeight - stackHeight;
347 stackHeight = mMinStackHeight;
348 start = mNotificationStackScroller.getHeight() - stackHeight;
349 mNotificationStackScroller.setTranslationY(overflow);
350 mNotificationTranslation = overflow + mScrollView.getScrollY();
351 } else {
352 mNotificationStackScroller.setTranslationY(0);
353 mNotificationTranslation = mScrollView.getScrollY();
354 }
355 mNotificationStackScroller.setTopPadding(clampQsStackScrollerPadding((int) start), false);
356 }
357
358 private int clampQsStackScrollerPadding(int desiredPadding) {
359 return Math.max(desiredPadding, mStackScrollerIntrinsicPadding);
360 }
361
362 private void trackMovement(MotionEvent event) {
363 if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
364 }
365
366 private void initVelocityTracker() {
367 if (mVelocityTracker != null) {
368 mVelocityTracker.recycle();
369 }
370 mVelocityTracker = VelocityTracker.obtain();
371 }
372
373 private float getCurrentVelocity() {
374 if (mVelocityTracker == null) {
375 return 0;
376 }
377 mVelocityTracker.computeCurrentVelocity(1000);
378 return mVelocityTracker.getYVelocity();
379 }
380
381 private void cancelAnimation() {
382 if (mQsExpansionAnimator != null) {
383 mQsExpansionAnimator.cancel();
384 }
385 }
386 private void flingSettings(float vel, boolean expand) {
387
388 // TODO: Actually use velocity.
389
390 float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight;
391 ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
392 animator.setDuration(EXPANSION_ANIMATION_LENGTH);
393 animator.setInterpolator(mExpansionInterpolator);
394 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
395 @Override
396 public void onAnimationUpdate(ValueAnimator animation) {
397 setQsExpansion((Float) animation.getAnimatedValue());
398 }
399 });
400 animator.addListener(new AnimatorListenerAdapter() {
401 @Override
402 public void onAnimationEnd(Animator animation) {
403 mQsExpansionAnimator = null;
404 }
405 });
406 animator.start();
407 mQsExpansionAnimator = animator;
408 }
409
410 /**
411 * @return Whether we should intercept a gesture to open Quick Settings.
412 */
413 private boolean shouldIntercept(float x, float y, float yDiff) {
414 if (!mQsExpansionEnabled) {
415 return false;
416 }
417 View headerView = mStatusBar.getBarState() == StatusBarState.KEYGUARD && !mQsExpanded
418 ? mKeyguardStatusView
419 : mHeader;
420 boolean onHeader = x >= headerView.getLeft() && x <= headerView.getRight()
421 && y >= headerView.getTop() && y <= headerView.getBottom();
422 if (mQsExpanded) {
423 return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0);
424 } else {
425 return onHeader;
426 }
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100427 }
428
429 @Override
Jorim Jaggi0d74eeb2014-05-09 22:05:24 +0200430 public void setVisibility(int visibility) {
431 int oldVisibility = getVisibility();
432 super.setVisibility(visibility);
433 if (visibility != oldVisibility) {
434 reparentStatusIcons(visibility == VISIBLE);
435 }
436 }
437
438 /**
439 * When the notification panel gets expanded, we need to move the status icons in the header
440 * card.
441 */
442 private void reparentStatusIcons(boolean toHeader) {
443 if (mStatusBar == null) {
444 return;
445 }
446 LinearLayout systemIcons = mStatusBar.getSystemIcons();
447 if (systemIcons.getParent() != null) {
448 ((ViewGroup) systemIcons.getParent()).removeView(systemIcons);
449 }
450 if (toHeader) {
451 mHeader.attachSystemIcons(systemIcons);
452 } else {
Jorim Jaggi13c1b1f2014-05-11 21:55:00 +0200453 mHeader.onSystemIconsDetached();
Jorim Jaggi0d74eeb2014-05-09 22:05:24 +0200454 mStatusBar.reattachSystemIcons();
455 }
456 }
457
458 @Override
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100459 protected boolean isScrolledToBottom() {
460 if (!isInSettings()) {
461 return mNotificationStackScroller.isScrolledToBottom();
Chris Wren64161cc2012-12-17 16:49:30 -0500462 }
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100463 return super.isScrolledToBottom();
464 }
465
466 @Override
467 protected int getMaxPanelHeight() {
468 if (!isInSettings()) {
469 int maxPanelHeight = super.getMaxPanelHeight();
Jorim Jaggid7daab72014-05-06 22:22:20 +0200470 int notificationMarginBottom = mStackScrollerContainer.getPaddingBottom();
471 int emptyBottomMargin = notificationMarginBottom
472 + mNotificationStackScroller.getEmptyBottomMargin();
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100473 return maxPanelHeight - emptyBottomMargin;
Daniel Sandler040c2e42012-10-17 00:56:33 -0400474 }
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100475 return super.getMaxPanelHeight();
476 }
477
478 private boolean isInSettings() {
Jorim Jaggid7daab72014-05-06 22:22:20 +0200479 return mQsExpanded;
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100480 }
481
482 @Override
483 protected void onHeightUpdated(float expandedHeight) {
Jorim Jaggi8c1a44b2014-04-29 19:04:02 +0200484 mNotificationStackScroller.setStackHeight(expandedHeight);
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100485 }
486
487 @Override
488 protected int getDesiredMeasureHeight() {
489 return mMaxPanelHeight;
Daniel Sandler040c2e42012-10-17 00:56:33 -0400490 }
Selim Cinek1685e632014-04-08 02:27:49 +0200491
492 @Override
493 protected void onExpandingStarted() {
494 super.onExpandingStarted();
495 mNotificationStackScroller.onExpansionStarted();
496 }
497
498 @Override
499 protected void onExpandingFinished() {
500 super.onExpandingFinished();
501 mNotificationStackScroller.onExpansionStopped();
502 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200503
504 @Override
505 public void onHeightChanged(ExpandableView view) {
506 requestPanelHeightUpdate();
507 }
Jorim Jaggid7daab72014-05-06 22:22:20 +0200508
509 @Override
510 public void onScrollChanged() {
511 if (mQsExpanded) {
512 mNotificationStackScroller.setTranslationY(
513 mNotificationTranslation - mScrollView.getScrollY());
514 }
515 }
516
517 @Override
518 public void onClick(View v) {
519 if (v == mHeader.getBackgroundView()) {
520 onQsExpansionStarted();
521 if (mQsExpanded) {
522 flingSettings(0 /* vel */, false /* expand */);
523 } else if (mQsExpansionEnabled) {
524 flingSettings(0 /* vel */, true /* expand */);
525 }
526 }
527 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400528}