blob: 2d2f2f121e4e014be37aaf3a97989affa8b9b83b [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
19import android.content.Context;
20import android.util.AttributeSet;
Daniel Sandler040c2e42012-10-17 00:56:33 -040021import android.view.MotionEvent;
Daniel Sandler13522a22012-09-27 14:46:58 -040022import android.view.View;
Casey Burkhardt23b0a4e2013-04-29 12:18:32 -070023import android.view.accessibility.AccessibilityEvent;
Daniel Sandler13522a22012-09-27 14:46:58 -040024
Chet Haase4d179dc2012-08-22 07:14:42 -070025import com.android.systemui.R;
Daniel Sandler151f00d2012-10-02 22:33:08 -040026import com.android.systemui.statusbar.GestureRecorder;
Selim Cinekb6d85eb2014-03-28 20:21:01 +010027import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Daniel Sandler08d05e32012-08-08 16:39:54 -040028
29public class NotificationPanelView extends PanelView {
Chris Wren64161cc2012-12-17 16:49:30 -050030 public static final boolean DEBUG_GESTURES = true;
Chet Haase4d179dc2012-08-22 07:14:42 -070031
Daniel Sandler040c2e42012-10-17 00:56:33 -040032 PhoneStatusBar mStatusBar;
Selim Cinekb6d85eb2014-03-28 20:21:01 +010033 private NotificationStackScrollLayout mNotificationStackScroller;
34 private int[] mTempLocation = new int[2];
35 private int[] mTempChildLocation = new int[2];
36 private View mNotificationParent;
37
Chet Haase4d179dc2012-08-22 07:14:42 -070038
Daniel Sandler08d05e32012-08-08 16:39:54 -040039 public NotificationPanelView(Context context, AttributeSet attrs) {
40 super(context, attrs);
Daniel Sandler13522a22012-09-27 14:46:58 -040041 }
Chet Haase4d179dc2012-08-22 07:14:42 -070042
Daniel Sandler040c2e42012-10-17 00:56:33 -040043 public void setStatusBar(PhoneStatusBar bar) {
Selim Cinekb6d85eb2014-03-28 20:21:01 +010044 if (mStatusBar != null) {
45 mStatusBar.setOnFlipRunnable(null);
46 }
Daniel Sandler040c2e42012-10-17 00:56:33 -040047 mStatusBar = bar;
Selim Cinekb6d85eb2014-03-28 20:21:01 +010048 if (bar != null) {
49 mStatusBar.setOnFlipRunnable(new Runnable() {
50 @Override
51 public void run() {
52 requestPanelHeightUpdate();
53 }
54 });
55 }
Daniel Sandler040c2e42012-10-17 00:56:33 -040056 }
57
Daniel Sandler13522a22012-09-27 14:46:58 -040058 @Override
59 protected void onFinishInflate() {
60 super.onFinishInflate();
61
Selim Cinekb6d85eb2014-03-28 20:21:01 +010062 mNotificationStackScroller = (NotificationStackScrollLayout)
63 findViewById(R.id.notification_stack_scroller);
64 mNotificationParent = findViewById(R.id.notification_container_parent);
Daniel Sandler08d05e32012-08-08 16:39:54 -040065 }
66
Daniel Sandler08d05e32012-08-08 16:39:54 -040067 @Override
68 public void fling(float vel, boolean always) {
Daniel Sandler151f00d2012-10-02 22:33:08 -040069 GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
70 if (gr != null) {
71 gr.tag(
72 "fling " + ((vel > 0) ? "open" : "closed"),
73 "notifications,v=" + vel);
74 }
Daniel Sandler08d05e32012-08-08 16:39:54 -040075 super.fling(vel, always);
76 }
Chet Haase4d179dc2012-08-22 07:14:42 -070077
Casey Burkhardt23b0a4e2013-04-29 12:18:32 -070078 @Override
79 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
80 if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
81 event.getText()
82 .add(getContext().getString(R.string.accessibility_desc_notification_shade));
83 return true;
84 }
85
86 return super.dispatchPopulateAccessibilityEvent(event);
87 }
88
Selim Cinekb6d85eb2014-03-28 20:21:01 +010089 /**
90 * Gets the relative position of a view on the screen in regard to this view.
91 *
92 * @param requestedView the view we want to find the relative position for
93 * @return
94 */
95 private int getRelativeTop(View requestedView) {
96 getLocationOnScreen(mTempLocation);
97 requestedView.getLocationOnScreen(mTempChildLocation);
98 return mTempChildLocation[1] - mTempLocation[1];
Chet Haase4d179dc2012-08-22 07:14:42 -070099 }
Daniel Sandler040c2e42012-10-17 00:56:33 -0400100
101 @Override
102 public boolean onTouchEvent(MotionEvent event) {
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100103 // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
104 // implementation.
105 return super.onTouchEvent(event);
106 }
107
108 @Override
109 protected boolean isScrolledToBottom() {
110 if (!isInSettings()) {
111 return mNotificationStackScroller.isScrolledToBottom();
Chris Wren64161cc2012-12-17 16:49:30 -0500112 }
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100113 return super.isScrolledToBottom();
114 }
115
116 @Override
117 protected int getMaxPanelHeight() {
118 if (!isInSettings()) {
119 int maxPanelHeight = super.getMaxPanelHeight();
120 int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
121 return maxPanelHeight - emptyBottomMargin;
Daniel Sandler040c2e42012-10-17 00:56:33 -0400122 }
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100123 return super.getMaxPanelHeight();
124 }
125
126 private boolean isInSettings() {
127 return mStatusBar != null && mStatusBar.isFlippedToSettings();
128 }
129
130 @Override
131 protected void onHeightUpdated(float expandedHeight) {
132 updateNotificationStackHeight(expandedHeight);
133 }
134
135 /**
136 * Update the height of the {@link #mNotificationStackScroller} to the new expanded height.
137 * This is much more efficient than doing it over the layout pass.
138 *
139 * @param expandedHeight the new expanded height
140 */
141 private void updateNotificationStackHeight(float expandedHeight) {
142 float childOffset = getRelativeTop(mNotificationStackScroller)
143 - mNotificationParent.getTranslationY();
144 int newStackHeight = (int) (expandedHeight - childOffset);
145 int itemHeight = mNotificationStackScroller.getItemHeight();
146 int bottomStackPeekSize = mNotificationStackScroller.getBottomStackPeekSize();
147 int minStackHeight = itemHeight + bottomStackPeekSize;
148 if (newStackHeight >= minStackHeight) {
149 mNotificationParent.setTranslationY(0);
150 mNotificationStackScroller.setCurrentStackHeight(newStackHeight);
151 } else {
152
153 // We did not reach the position yet where we actually start growing,
154 // so we translate the stack upwards.
155 int translationY = (newStackHeight - minStackHeight);
156 // A slight parallax effect is introduced in order for the stack to catch up with
157 // the top card.
158 float partiallyThere = (float) newStackHeight / minStackHeight;
159 partiallyThere = Math.max(0, partiallyThere);
160 translationY += (1 - partiallyThere) * bottomStackPeekSize;
161 mNotificationParent.setTranslationY(translationY);
162 mNotificationStackScroller.setCurrentStackHeight(
163 (int) (expandedHeight - (childOffset + translationY)));
164 }
165 }
166
167 @Override
168 protected int getDesiredMeasureHeight() {
169 return mMaxPanelHeight;
Daniel Sandler040c2e42012-10-17 00:56:33 -0400170 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400171}