blob: 280bade5a31b436b7cffe32c5e328607e4a20f41 [file] [log] [blame]
Chris Wren51c75102013-07-16 20:49:17 -04001/*
2 * Copyright (C) 2013 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;
18
19import android.content.Context;
20import android.util.AttributeSet;
Dan Sandlera5e0f412014-01-23 15:11:54 -050021import android.view.View;
Jorim Jaggife40f7d2014-04-28 15:20:04 +020022import android.view.accessibility.AccessibilityEvent;
Chris Wren51c75102013-07-16 20:49:17 -040023
Dan Sandlera5e0f412014-01-23 15:11:54 -050024import com.android.systemui.R;
25
Jorim Jaggi4222d9a2014-04-23 16:13:15 +020026public class ExpandableNotificationRow extends ActivatableNotificationView {
Selim Cinek1685e632014-04-08 02:27:49 +020027 private int mRowMinHeight;
28 private int mRowMaxHeight;
Chris Wren51c75102013-07-16 20:49:17 -040029
Selim Cinek1685e632014-04-08 02:27:49 +020030 /** Does this row contain layouts that can adapt to row expansion */
Chris Wren51c75102013-07-16 20:49:17 -040031 private boolean mExpandable;
Selim Cinek1685e632014-04-08 02:27:49 +020032 /** Has the user actively changed the expansion state of this row */
33 private boolean mHasUserChangedExpansion;
34 /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
Chris Wren51c75102013-07-16 20:49:17 -040035 private boolean mUserExpanded;
Selim Cinek1685e632014-04-08 02:27:49 +020036 /** Is the user touching this row */
Chris Wren51c75102013-07-16 20:49:17 -040037 private boolean mUserLocked;
Selim Cinek1685e632014-04-08 02:27:49 +020038 /** Are we showing the "public" version */
Dan Sandlera5e0f412014-01-23 15:11:54 -050039 private boolean mShowingPublic;
Chris Wren51c75102013-07-16 20:49:17 -040040
Selim Cinek1685e632014-04-08 02:27:49 +020041 /**
42 * Is this notification expanded by the system. The expansion state can be overridden by the
43 * user expansion.
44 */
45 private boolean mIsSystemExpanded;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020046
47 /**
48 * Whether the notification expansion is disabled. This is the case on Keyguard.
49 */
50 private boolean mExpansionDisabled;
51
Jorim Jaggibe565df2014-04-28 17:51:23 +020052 private NotificationContentView mPublicLayout;
53 private NotificationContentView mPrivateLayout;
Selim Cinek1685e632014-04-08 02:27:49 +020054 private int mMaxExpandHeight;
Selim Cinek863834b2014-05-20 04:20:25 +020055 private View mVetoButton;
Selim Cinek1685e632014-04-08 02:27:49 +020056
Chris Wren51c75102013-07-16 20:49:17 -040057 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
58 super(context, attrs);
59 }
60
Christoph Studera7fe6312014-06-27 19:32:44 +020061 /**
62 * Resets this view so it can be re-used for an updated notification.
63 */
64 public void reset() {
65 mRowMinHeight = 0;
66 mRowMaxHeight = 0;
67 mExpandable = false;
68 mHasUserChangedExpansion = false;
69 mUserLocked = false;
70 mShowingPublic = false;
71 mIsSystemExpanded = false;
72 mExpansionDisabled = false;
73 mPublicLayout.reset();
74 mPrivateLayout.reset();
75 mMaxExpandHeight = 0;
76 }
77
Jorim Jaggi251957d2014-04-09 04:24:09 +020078 @Override
79 protected void onFinishInflate() {
80 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +020081 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
82 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinek863834b2014-05-20 04:20:25 +020083 mVetoButton = findViewById(R.id.veto);
Jorim Jaggife40f7d2014-04-28 15:20:04 +020084 }
85
86 @Override
87 public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
88 if (super.onRequestSendAccessibilityEvent(child, event)) {
89 // Add a record for the entire layout since its content is somehow small.
90 // The event comes from a leaf view that is interacted with.
91 AccessibilityEvent record = AccessibilityEvent.obtain();
92 onInitializeAccessibilityEvent(record);
93 dispatchPopulateAccessibilityEvent(record);
94 event.appendRecord(record);
95 return true;
96 }
97 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +020098 }
Chris Wren51c75102013-07-16 20:49:17 -040099
Selim Cinek1685e632014-04-08 02:27:49 +0200100 public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
101 mRowMinHeight = rowMinHeight;
102 mRowMaxHeight = rowMaxHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400103 }
104
105 public boolean isExpandable() {
106 return mExpandable;
107 }
108
109 public void setExpandable(boolean expandable) {
110 mExpandable = expandable;
111 }
112
Selim Cinek1685e632014-04-08 02:27:49 +0200113 /**
114 * @return whether the user has changed the expansion state
115 */
116 public boolean hasUserChangedExpansion() {
117 return mHasUserChangedExpansion;
118 }
119
Chris Wren51c75102013-07-16 20:49:17 -0400120 public boolean isUserExpanded() {
121 return mUserExpanded;
122 }
123
Selim Cinek1685e632014-04-08 02:27:49 +0200124 /**
125 * Set this notification to be expanded by the user
126 *
127 * @param userExpanded whether the user wants this notification to be expanded
128 */
Chris Wren51c75102013-07-16 20:49:17 -0400129 public void setUserExpanded(boolean userExpanded) {
Christoph Studera7fe6312014-06-27 19:32:44 +0200130 if (userExpanded && !mExpandable) return;
Selim Cinek1685e632014-04-08 02:27:49 +0200131 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400132 mUserExpanded = userExpanded;
133 }
134
135 public boolean isUserLocked() {
136 return mUserLocked;
137 }
138
139 public void setUserLocked(boolean userLocked) {
140 mUserLocked = userLocked;
141 }
142
Selim Cinek1685e632014-04-08 02:27:49 +0200143 /**
144 * @return has the system set this notification to be expanded
145 */
146 public boolean isSystemExpanded() {
147 return mIsSystemExpanded;
148 }
149
150 /**
151 * Set this notification to be expanded by the system.
152 *
153 * @param expand whether the system wants this notification to be expanded.
154 */
155 public void setSystemExpanded(boolean expand) {
156 mIsSystemExpanded = expand;
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200157 notifyHeightChanged();
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200158 }
159
160 /**
161 * @param expansionDisabled whether to prevent notification expansion
162 */
163 public void setExpansionDisabled(boolean expansionDisabled) {
164 mExpansionDisabled = expansionDisabled;
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200165 notifyHeightChanged();
Selim Cinek1685e632014-04-08 02:27:49 +0200166 }
167
168 /**
169 * Apply an expansion state to the layout.
Selim Cinek1685e632014-04-08 02:27:49 +0200170 */
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200171 public void applyExpansionToLayout() {
172 boolean expand = isExpanded();
Chris Wren51c75102013-07-16 20:49:17 -0400173 if (expand && mExpandable) {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200174 setActualHeight(mMaxExpandHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400175 } else {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200176 setActualHeight(mRowMinHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400177 }
Chris Wren51c75102013-07-16 20:49:17 -0400178 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500179
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200180 @Override
181 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200182 if (isUserLocked()) {
183 return getActualHeight();
184 }
Selim Cinek1685e632014-04-08 02:27:49 +0200185 boolean inExpansionState = isExpanded();
186 if (!inExpansionState) {
187 // not expanded, so we return the collapsed size
188 return mRowMinHeight;
189 }
190
191 return mShowingPublic ? mRowMinHeight : getMaxExpandHeight();
192 }
193
Selim Cinek1685e632014-04-08 02:27:49 +0200194 /**
195 * Check whether the view state is currently expanded. This is given by the system in {@link
196 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
197 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
198 * view can differ from this state, if layout params are modified from outside.
199 *
200 * @return whether the view state is currently expanded.
201 */
202 private boolean isExpanded() {
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200203 return !mExpansionDisabled
204 && (!hasUserChangedExpansion() && isSystemExpanded() || isUserExpanded());
Selim Cinek1685e632014-04-08 02:27:49 +0200205 }
206
207 @Override
208 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
209 super.onLayout(changed, left, top, right, bottom);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200210 boolean updateExpandHeight = mMaxExpandHeight == 0;
211 mMaxExpandHeight = mPrivateLayout.getMaxHeight();
212 if (updateExpandHeight) {
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200213 applyExpansionToLayout();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200214 }
Selim Cinek1685e632014-04-08 02:27:49 +0200215 }
216
Dan Sandlera5e0f412014-01-23 15:11:54 -0500217 public void setShowingPublic(boolean show) {
218 mShowingPublic = show;
Dan Sandlera5e0f412014-01-23 15:11:54 -0500219
220 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +0200221 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -0500222
223 // TODO: animation?
Selim Cinek1685e632014-04-08 02:27:49 +0200224 mPublicLayout.setVisibility(show ? View.VISIBLE : View.GONE);
225 mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE);
Dan Sandlera5e0f412014-01-23 15:11:54 -0500226 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200227
Selim Cinek1685e632014-04-08 02:27:49 +0200228 public int getMaxExpandHeight() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200229 return mShowingPublic ? mRowMinHeight : mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400230 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +0200231
Jorim Jaggibe565df2014-04-28 17:51:23 +0200232 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200233 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200234 NotificationContentView showingLayout = getShowingLayout();
235 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200236 }
237
238 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200239 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekc9c00ae2014-05-20 03:33:40 +0200240 mPrivateLayout.setActualHeight(height);
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200241 mPublicLayout.setActualHeight(height);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200242 invalidate();
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200243 super.setActualHeight(height, notifyListeners);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200244 }
245
246 @Override
247 public int getMaxHeight() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200248 NotificationContentView showingLayout = getShowingLayout();
249 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200250 }
251
252 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200253 public int getMinHeight() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200254 NotificationContentView showingLayout = getShowingLayout();
255 return showingLayout.getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200256 }
257
258 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +0200259 public void setClipTopAmount(int clipTopAmount) {
260 super.setClipTopAmount(clipTopAmount);
261 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200262 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200263 }
264
265 public void notifyContentUpdated() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200266 mPublicLayout.notifyContentUpdated();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200267 mPrivateLayout.notifyContentUpdated();
Selim Cinek343e6e22014-04-11 21:23:30 +0200268 }
Selim Cinek7d447722014-06-10 15:51:59 +0200269
270 public boolean isShowingLayoutLayouted() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200271 NotificationContentView showingLayout = getShowingLayout();
Selim Cinek7d447722014-06-10 15:51:59 +0200272 return showingLayout.getWidth() != 0;
273 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200274
275 private NotificationContentView getShowingLayout() {
276 return mShowingPublic ? mPublicLayout : mPrivateLayout;
277 }
Chris Wren51c75102013-07-16 20:49:17 -0400278}