blob: fdf4dbf51fe43906eccd513bfa7e78ca0ce4096a [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;
Chris Wren51c75102013-07-16 20:49:17 -040022import android.view.ViewGroup;
23import android.widget.FrameLayout;
24
Selim Cinek1685e632014-04-08 02:27:49 +020025import com.android.internal.widget.SizeAdaptiveLayout;
Dan Sandlera5e0f412014-01-23 15:11:54 -050026import com.android.systemui.R;
27
Jorim Jaggic5dc0d02014-04-15 15:42:55 +020028public class ExpandableNotificationRow extends FrameLayout
29 implements LatestItemView.OnActivatedListener {
Selim Cinek1685e632014-04-08 02:27:49 +020030 private int mRowMinHeight;
31 private int mRowMaxHeight;
Chris Wren51c75102013-07-16 20:49:17 -040032
Selim Cinek1685e632014-04-08 02:27:49 +020033 /** Does this row contain layouts that can adapt to row expansion */
Chris Wren51c75102013-07-16 20:49:17 -040034 private boolean mExpandable;
Selim Cinek1685e632014-04-08 02:27:49 +020035 /** Has the user actively changed the expansion state of this row */
36 private boolean mHasUserChangedExpansion;
37 /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
Chris Wren51c75102013-07-16 20:49:17 -040038 private boolean mUserExpanded;
Selim Cinek1685e632014-04-08 02:27:49 +020039 /** Is the user touching this row */
Chris Wren51c75102013-07-16 20:49:17 -040040 private boolean mUserLocked;
Selim Cinek1685e632014-04-08 02:27:49 +020041 /** Are we showing the "public" version */
Dan Sandlera5e0f412014-01-23 15:11:54 -050042 private boolean mShowingPublic;
Chris Wren51c75102013-07-16 20:49:17 -040043
Jorim Jaggi251957d2014-04-09 04:24:09 +020044 private LatestItemView mLatestItemView;
45
Selim Cinek1685e632014-04-08 02:27:49 +020046 /**
47 * Is this notification expanded by the system. The expansion state can be overridden by the
48 * user expansion.
49 */
50 private boolean mIsSystemExpanded;
51 private SizeAdaptiveLayout mPublicLayout;
52 private SizeAdaptiveLayout mPrivateLayout;
53 private int mMaxExpandHeight;
54 private boolean mMaxHeightNeedsUpdate;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +020055 private NotificationActivator mActivator;
56 private LatestItemView.OnActivatedListener mOnActivatedListener;
Selim Cinek1685e632014-04-08 02:27:49 +020057
Chris Wren51c75102013-07-16 20:49:17 -040058 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
59 super(context, attrs);
60 }
61
Jorim Jaggi251957d2014-04-09 04:24:09 +020062 @Override
63 protected void onFinishInflate() {
64 super.onFinishInflate();
Selim Cinek1685e632014-04-08 02:27:49 +020065 mPublicLayout = (SizeAdaptiveLayout) findViewById(R.id.expandedPublic);
66 mPrivateLayout = (SizeAdaptiveLayout) findViewById(R.id.expanded);
Jorim Jaggi251957d2014-04-09 04:24:09 +020067 mLatestItemView = (LatestItemView) findViewById(R.id.container);
Jorim Jaggi251957d2014-04-09 04:24:09 +020068
Jorim Jaggic5dc0d02014-04-15 15:42:55 +020069 mActivator = new NotificationActivator(this);
70 mLatestItemView.setOnActivatedListener(this);
71 }
Chris Wren51c75102013-07-16 20:49:17 -040072
Selim Cinek1685e632014-04-08 02:27:49 +020073 public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
74 mRowMinHeight = rowMinHeight;
75 mRowMaxHeight = rowMaxHeight;
76 mMaxHeightNeedsUpdate = true;
Chris Wren51c75102013-07-16 20:49:17 -040077 }
78
79 public boolean isExpandable() {
80 return mExpandable;
81 }
82
83 public void setExpandable(boolean expandable) {
84 mExpandable = expandable;
85 }
86
Selim Cinek1685e632014-04-08 02:27:49 +020087 /**
88 * @return whether the user has changed the expansion state
89 */
90 public boolean hasUserChangedExpansion() {
91 return mHasUserChangedExpansion;
92 }
93
Chris Wren51c75102013-07-16 20:49:17 -040094 public boolean isUserExpanded() {
95 return mUserExpanded;
96 }
97
Selim Cinek1685e632014-04-08 02:27:49 +020098 /**
99 * Set this notification to be expanded by the user
100 *
101 * @param userExpanded whether the user wants this notification to be expanded
102 */
Chris Wren51c75102013-07-16 20:49:17 -0400103 public void setUserExpanded(boolean userExpanded) {
Selim Cinek1685e632014-04-08 02:27:49 +0200104 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400105 mUserExpanded = userExpanded;
106 }
107
108 public boolean isUserLocked() {
109 return mUserLocked;
110 }
111
112 public void setUserLocked(boolean userLocked) {
113 mUserLocked = userLocked;
114 }
115
Selim Cinek1685e632014-04-08 02:27:49 +0200116 /**
117 * @return has the system set this notification to be expanded
118 */
119 public boolean isSystemExpanded() {
120 return mIsSystemExpanded;
121 }
122
123 /**
124 * Set this notification to be expanded by the system.
125 *
126 * @param expand whether the system wants this notification to be expanded.
127 */
128 public void setSystemExpanded(boolean expand) {
129 mIsSystemExpanded = expand;
130 applyExpansionToLayout(expand);
131 }
132
133 /**
134 * Apply an expansion state to the layout.
135 *
136 * @param expand should the layout be in the expanded state
137 */
138 public void applyExpansionToLayout(boolean expand) {
Chris Wren51c75102013-07-16 20:49:17 -0400139 ViewGroup.LayoutParams lp = getLayoutParams();
140 if (expand && mExpandable) {
141 lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
142 } else {
Selim Cinek1685e632014-04-08 02:27:49 +0200143 lp.height = mRowMinHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400144 }
145 setLayoutParams(lp);
146 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500147
Selim Cinek1685e632014-04-08 02:27:49 +0200148 /**
149 * If {@link #isExpanded()} then this is the greatest possible height this view can
150 * get and otherwise it is {@link #mRowMinHeight}.
151 *
152 * @return the maximum allowed expansion height of this view.
153 */
154 public int getMaximumAllowedExpandHeight() {
155 boolean inExpansionState = isExpanded();
156 if (!inExpansionState) {
157 // not expanded, so we return the collapsed size
158 return mRowMinHeight;
159 }
160
161 return mShowingPublic ? mRowMinHeight : getMaxExpandHeight();
162 }
163
Selim Cinek1685e632014-04-08 02:27:49 +0200164 private void updateMaxExpandHeight() {
165 ViewGroup.LayoutParams lp = getLayoutParams();
166 int oldHeight = lp.height;
167 lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
168 setLayoutParams(lp);
169 measure(View.MeasureSpec.makeMeasureSpec(getMeasuredWidth(), View.MeasureSpec.EXACTLY),
170 View.MeasureSpec.makeMeasureSpec(mRowMaxHeight, View.MeasureSpec.AT_MOST));
171 lp.height = oldHeight;
172 setLayoutParams(lp);
173 mMaxExpandHeight = getMeasuredHeight();
174 }
175
176 /**
177 * Check whether the view state is currently expanded. This is given by the system in {@link
178 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
179 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
180 * view can differ from this state, if layout params are modified from outside.
181 *
182 * @return whether the view state is currently expanded.
183 */
184 private boolean isExpanded() {
185 return !hasUserChangedExpansion() && isSystemExpanded() || isUserExpanded();
186 }
187
188 @Override
189 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
190 super.onLayout(changed, left, top, right, bottom);
191 mMaxHeightNeedsUpdate = true;
192 }
193
Dan Sandlera5e0f412014-01-23 15:11:54 -0500194 public void setShowingPublic(boolean show) {
195 mShowingPublic = show;
Dan Sandlera5e0f412014-01-23 15:11:54 -0500196
197 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +0200198 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -0500199
200 // TODO: animation?
Selim Cinek1685e632014-04-08 02:27:49 +0200201 mPublicLayout.setVisibility(show ? View.VISIBLE : View.GONE);
202 mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE);
Dan Sandlera5e0f412014-01-23 15:11:54 -0500203 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200204
205 /**
206 * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
207 */
208 public void setDimmed(boolean dimmed) {
209 mLatestItemView.setDimmed(dimmed);
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200210 mActivator.setDimmed(dimmed);
Jorim Jaggi251957d2014-04-09 04:24:09 +0200211 }
212
Selim Cinek1685e632014-04-08 02:27:49 +0200213 public int getMaxExpandHeight() {
214 if (mMaxHeightNeedsUpdate) {
215 updateMaxExpandHeight();
216 mMaxHeightNeedsUpdate = false;
217 }
218 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400219 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +0200220
Jorim Jaggi251957d2014-04-09 04:24:09 +0200221 /**
222 * Sets the notification as locked. In the locked state, the first tap will produce a quantum
223 * ripple to make the notification brighter and only the second tap will cause a click.
224 */
225 public void setLocked(boolean locked) {
226 mLatestItemView.setLocked(locked);
227 }
Jorim Jaggi46739852014-04-15 09:58:24 +0200228
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200229 public void setOnActivatedListener(LatestItemView.OnActivatedListener listener) {
230 mOnActivatedListener = listener;
231 }
232
233 public NotificationActivator getActivator() {
234 return mActivator;
235 }
236
237 @Override
238 public void onActivated(View view) {
239 if (mOnActivatedListener != null) {
240 mOnActivatedListener.onActivated(this);
241 }
242 }
243
244 @Override
245 public void onReset(View view) {
246 if (mOnActivatedListener != null) {
247 mOnActivatedListener.onReset(this);
248 }
249 }
250
Jorim Jaggi46739852014-04-15 09:58:24 +0200251 /**
252 * Sets the resource id for the background of this notification.
253 *
254 * @param bgResId The background resource to use in normal state.
255 * @param dimmedBgResId The background resource to use in dimmed state.
256 */
257 public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
258 mLatestItemView.setBackgroundResourceIds(bgResId, dimmedBgResId);
259 }
Chris Wren51c75102013-07-16 20:49:17 -0400260}