blob: 7c1116170ec3d1c28dbcc0d454991ecf1b00c352 [file] [log] [blame]
Jorim Jaggibe565df2014-04-28 17:51:23 +02001/*
2 * Copyright (C) 2014 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
Adrian Roosb88b1a12015-12-09 18:51:05 -080019import android.app.Notification;
20import android.app.RemoteInput;
Jorim Jaggibe565df2014-04-28 17:51:23 +020021import android.content.Context;
22import android.graphics.Rect;
Selim Cinek860b6da2015-12-16 19:02:19 -080023import android.os.Build;
Selim Cinek83bc7832015-10-22 13:26:54 -070024import android.service.notification.StatusBarNotification;
Jorim Jaggibe565df2014-04-28 17:51:23 +020025import android.util.AttributeSet;
Selim Cinekeaa29ca2015-11-23 13:51:13 -080026import android.view.NotificationHeaderView;
Jorim Jaggibe565df2014-04-28 17:51:23 +020027import android.view.View;
Selim Cinek8d490d42015-04-10 00:05:50 -070028import android.view.ViewGroup;
Selim Cinekbb3d1cf2014-10-31 00:12:56 +010029import android.view.ViewTreeObserver;
Selim Cinekc9c00ae2014-05-20 03:33:40 +020030import android.widget.FrameLayout;
Selim Cinek8d490d42015-04-10 00:05:50 -070031
Jorim Jaggibe565df2014-04-28 17:51:23 +020032import com.android.systemui.R;
Selim Cinek83bc7832015-10-22 13:26:54 -070033import com.android.systemui.statusbar.notification.HybridNotificationView;
34import com.android.systemui.statusbar.notification.HybridNotificationViewManager;
Selim Cinek0ffbda62016-01-01 20:29:12 +010035import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
36import com.android.systemui.statusbar.notification.NotificationViewWrapper;
Selim Cinek83bc7832015-10-22 13:26:54 -070037import com.android.systemui.statusbar.phone.NotificationGroupManager;
Adrian Roosb88b1a12015-12-09 18:51:05 -080038import com.android.systemui.statusbar.policy.RemoteInputView;
Jorim Jaggibe565df2014-04-28 17:51:23 +020039
40/**
Selim Cinek684a4422015-04-15 16:18:39 -070041 * A frame layout containing the actual payload of the notification, including the contracted,
42 * expanded and heads up layout. This class is responsible for clipping the content and and
43 * switching between the expanded, contracted and the heads up view depending on its clipped size.
Jorim Jaggibe565df2014-04-28 17:51:23 +020044 */
Selim Cinekc9c00ae2014-05-20 03:33:40 +020045public class NotificationContentView extends FrameLayout {
Jorim Jaggibe565df2014-04-28 17:51:23 +020046
Selim Cinek684a4422015-04-15 16:18:39 -070047 private static final int VISIBLE_TYPE_CONTRACTED = 0;
48 private static final int VISIBLE_TYPE_EXPANDED = 1;
49 private static final int VISIBLE_TYPE_HEADSUP = 2;
Selim Cinek83bc7832015-10-22 13:26:54 -070050 private static final int VISIBLE_TYPE_SINGLELINE = 3;
Selim Cinek8f2f6a62016-02-23 19:56:31 -080051 private static final int UNDEFINED = -1;
Jorim Jaggi11298832014-05-24 16:18:38 +020052
Jorim Jaggibe565df2014-04-28 17:51:23 +020053 private final Rect mClipBounds = new Rect();
Selim Cinek860b6da2015-12-16 19:02:19 -080054 private final int mMinContractedHeight;
Selim Cinek6ecc8102016-01-26 18:26:19 -080055 private final int mNotificationContentMarginEnd;
Selim Cinek30e387d2016-01-11 18:01:47 -080056 private final OnLayoutChangeListener mLayoutUpdater = new OnLayoutChangeListener() {
57 @Override
58 public void onLayoutChange(View v, int left, int top, int right, int bottom,
59 int oldLeft,
60 int oldTop, int oldRight, int oldBottom) {
61 selectLayout(false /* animate */, false /* force */);
62 }
63 };
Selim Cinek860b6da2015-12-16 19:02:19 -080064
Jorim Jaggibe565df2014-04-28 17:51:23 +020065
66 private View mContractedChild;
67 private View mExpandedChild;
Selim Cinek8d490d42015-04-10 00:05:50 -070068 private View mHeadsUpChild;
Selim Cinek83bc7832015-10-22 13:26:54 -070069 private HybridNotificationView mSingleLineView;
Jorim Jaggibe565df2014-04-28 17:51:23 +020070
Jorim Jaggi4e857f42014-11-17 19:14:04 +010071 private NotificationViewWrapper mContractedWrapper;
Jorim Jaggibe4116a2015-05-20 20:04:08 -070072 private NotificationViewWrapper mExpandedWrapper;
73 private NotificationViewWrapper mHeadsUpWrapper;
Selim Cinek83bc7832015-10-22 13:26:54 -070074 private HybridNotificationViewManager mHybridViewManager;
Selim Cinekc9c00ae2014-05-20 03:33:40 +020075 private int mClipTopAmount;
Selim Cinekb5605e52015-02-20 18:21:41 +010076 private int mContentHeight;
Jorim Jaggibe4116a2015-05-20 20:04:08 -070077 private int mUnrestrictedContentHeight;
Selim Cinek684a4422015-04-15 16:18:39 -070078 private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
John Spurlocke15452b2014-08-21 09:44:39 -040079 private boolean mDark;
Selim Cinekbb3d1cf2014-10-31 00:12:56 +010080 private boolean mAnimate;
Selim Cinek684a4422015-04-15 16:18:39 -070081 private boolean mIsHeadsUp;
Jorim Jaggi59ec3042015-06-05 15:18:43 -070082 private boolean mShowingLegacyBackground;
Selim Cinek83bc7832015-10-22 13:26:54 -070083 private boolean mIsChildInGroup;
Selim Cinek816c8e42015-11-19 12:00:45 -080084 private int mSmallHeight;
Selim Cinek77019c72015-12-09 10:18:02 -080085 private int mHeadsUpHeight;
Selim Cinekd84a5932015-12-15 11:45:36 -080086 private int mNotificationMaxHeight;
Selim Cinek83bc7832015-10-22 13:26:54 -070087 private StatusBarNotification mStatusBarNotification;
Selim Cinek65b2e7c2015-10-26 14:11:31 -070088 private NotificationGroupManager mGroupManager;
Adrian Roosb88b1a12015-12-09 18:51:05 -080089 private RemoteInputController mRemoteInputController;
Jorim Jaggi59ec3042015-06-05 15:18:43 -070090
Jorim Jaggibe4116a2015-05-20 20:04:08 -070091 private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
Selim Cinekbb3d1cf2014-10-31 00:12:56 +010092 = new ViewTreeObserver.OnPreDrawListener() {
93 @Override
94 public boolean onPreDraw() {
95 mAnimate = true;
96 getViewTreeObserver().removeOnPreDrawListener(this);
97 return true;
98 }
99 };
Jorim Jaggi11298832014-05-24 16:18:38 +0200100
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800101 private OnClickListener mExpandClickListener;
Selim Cinek860b6da2015-12-16 19:02:19 -0800102 private boolean mBeforeN;
Selim Cinek98be3f32015-12-17 16:39:06 -0800103 private boolean mExpandable;
Selim Cinek4ffd6362015-12-29 15:12:23 +0100104 private boolean mClipToActualHeight = true;
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800105 private ExpandableNotificationRow mContainingNotification;
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800106 private int mTransformationStartVisibleType;
107 private boolean mUserExpanding;
Selim Cinek98be3f32015-12-17 16:39:06 -0800108
Jorim Jaggibe565df2014-04-28 17:51:23 +0200109 public NotificationContentView(Context context, AttributeSet attrs) {
110 super(context, attrs);
Selim Cinek83bc7832015-10-22 13:26:54 -0700111 mHybridViewManager = new HybridNotificationViewManager(getContext(), this);
Selim Cinek860b6da2015-12-16 19:02:19 -0800112 mMinContractedHeight = getResources().getDimensionPixelSize(
113 R.dimen.min_notification_layout_height);
Selim Cinek6ecc8102016-01-26 18:26:19 -0800114 mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
115 com.android.internal.R.dimen.notification_content_margin_end);
Selim Cinek1a521f32014-11-03 17:39:29 +0100116 reset(true);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200117 }
118
Selim Cinekd84a5932015-12-15 11:45:36 -0800119 public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight) {
Selim Cinek816c8e42015-11-19 12:00:45 -0800120 mSmallHeight = smallHeight;
Selim Cinek77019c72015-12-09 10:18:02 -0800121 mHeadsUpHeight = headsUpMaxHeight;
Selim Cinekd84a5932015-12-15 11:45:36 -0800122 mNotificationMaxHeight = maxHeight;
Selim Cinek816c8e42015-11-19 12:00:45 -0800123 }
124
Jorim Jaggibe565df2014-04-28 17:51:23 +0200125 @Override
Selim Cinek8d490d42015-04-10 00:05:50 -0700126 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
127 int heightMode = MeasureSpec.getMode(heightMeasureSpec);
128 boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
129 boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
130 int maxSize = Integer.MAX_VALUE;
131 if (hasFixedHeight || isHeightLimited) {
132 maxSize = MeasureSpec.getSize(heightMeasureSpec);
133 }
134 int maxChildHeight = 0;
Selim Cinek6ecc8102016-01-26 18:26:19 -0800135 if (mExpandedChild != null) {
136 int size = Math.min(maxSize, mNotificationMaxHeight);
137 ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams();
138 if (layoutParams.height >= 0) {
139 // An actual height is set
140 size = Math.min(maxSize, layoutParams.height);
141 }
142 int spec = size == Integer.MAX_VALUE
143 ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
144 : MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
145 mExpandedChild.measure(widthMeasureSpec, spec);
146 maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
147 }
Selim Cinek8d490d42015-04-10 00:05:50 -0700148 if (mContractedChild != null) {
Selim Cinek860b6da2015-12-16 19:02:19 -0800149 int heightSpec;
Selim Cinekf619ffc2016-02-17 14:53:05 -0800150 int size = Math.min(maxSize, mSmallHeight);
Selim Cinek860b6da2015-12-16 19:02:19 -0800151 if (shouldContractedBeFixedSize()) {
Selim Cinek860b6da2015-12-16 19:02:19 -0800152 heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
153 } else {
Selim Cinekf619ffc2016-02-17 14:53:05 -0800154 heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
Selim Cinek860b6da2015-12-16 19:02:19 -0800155 }
156 mContractedChild.measure(widthMeasureSpec, heightSpec);
157 int measuredHeight = mContractedChild.getMeasuredHeight();
158 if (measuredHeight < mMinContractedHeight) {
159 heightSpec = MeasureSpec.makeMeasureSpec(mMinContractedHeight, MeasureSpec.EXACTLY);
160 mContractedChild.measure(widthMeasureSpec, heightSpec);
161 }
162 maxChildHeight = Math.max(maxChildHeight, measuredHeight);
Selim Cinek6ecc8102016-01-26 18:26:19 -0800163 if (updateContractedHeaderWidth()) {
164 mContractedChild.measure(widthMeasureSpec, heightSpec);
Selim Cinek8d490d42015-04-10 00:05:50 -0700165 }
Selim Cinek8d490d42015-04-10 00:05:50 -0700166 }
167 if (mHeadsUpChild != null) {
168 int size = Math.min(maxSize, mHeadsUpHeight);
169 ViewGroup.LayoutParams layoutParams = mHeadsUpChild.getLayoutParams();
170 if (layoutParams.height >= 0) {
171 // An actual height is set
Selim Cinek77019c72015-12-09 10:18:02 -0800172 size = Math.min(size, layoutParams.height);
Selim Cinek8d490d42015-04-10 00:05:50 -0700173 }
174 mHeadsUpChild.measure(widthMeasureSpec,
175 MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST));
176 maxChildHeight = Math.max(maxChildHeight, mHeadsUpChild.getMeasuredHeight());
177 }
Selim Cinek83bc7832015-10-22 13:26:54 -0700178 if (mSingleLineView != null) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700179 mSingleLineView.measure(widthMeasureSpec,
Selim Cinek7b836392015-12-04 20:02:59 -0800180 MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.AT_MOST));
Selim Cinek83bc7832015-10-22 13:26:54 -0700181 maxChildHeight = Math.max(maxChildHeight, mSingleLineView.getMeasuredHeight());
182 }
Selim Cinek8d490d42015-04-10 00:05:50 -0700183 int ownHeight = Math.min(maxChildHeight, maxSize);
184 int width = MeasureSpec.getSize(widthMeasureSpec);
185 setMeasuredDimension(width, ownHeight);
186 }
187
Selim Cinek6ecc8102016-01-26 18:26:19 -0800188 private boolean updateContractedHeaderWidth() {
189 // We need to update the expanded and the collapsed header to have exactly the same with to
190 // have the expand buttons laid out at the same location.
191 NotificationHeaderView contractedHeader = mContractedWrapper.getNotificationHeader();
192 if (contractedHeader != null) {
193 if (mExpandedChild != null
194 && mExpandedWrapper.getNotificationHeader() != null) {
195 NotificationHeaderView expandedHeader = mExpandedWrapper.getNotificationHeader();
196 int expandedSize = expandedHeader.getMeasuredWidth()
197 - expandedHeader.getPaddingEnd();
198 int collapsedSize = contractedHeader.getMeasuredWidth()
199 - expandedHeader.getPaddingEnd();
200 if (expandedSize != collapsedSize) {
201 int paddingEnd = contractedHeader.getMeasuredWidth() - expandedSize;
202 contractedHeader.setPadding(
Selim Cinekcb445682016-01-29 16:13:12 -0800203 contractedHeader.isLayoutRtl()
204 ? paddingEnd
205 : contractedHeader.getPaddingLeft(),
Selim Cinek6ecc8102016-01-26 18:26:19 -0800206 contractedHeader.getPaddingTop(),
Selim Cinekcb445682016-01-29 16:13:12 -0800207 contractedHeader.isLayoutRtl()
208 ? contractedHeader.getPaddingLeft()
209 : paddingEnd,
Selim Cinek6ecc8102016-01-26 18:26:19 -0800210 contractedHeader.getPaddingBottom());
211 contractedHeader.setShowWorkBadgeAtEnd(true);
212 return true;
213 }
214 } else {
215 int paddingEnd = mNotificationContentMarginEnd;
216 if (contractedHeader.getPaddingEnd() != paddingEnd) {
217 contractedHeader.setPadding(
Selim Cinekcb445682016-01-29 16:13:12 -0800218 contractedHeader.isLayoutRtl()
219 ? paddingEnd
220 : contractedHeader.getPaddingLeft(),
Selim Cinek6ecc8102016-01-26 18:26:19 -0800221 contractedHeader.getPaddingTop(),
Selim Cinekcb445682016-01-29 16:13:12 -0800222 contractedHeader.isLayoutRtl()
223 ? contractedHeader.getPaddingLeft()
224 : paddingEnd,
Selim Cinek6ecc8102016-01-26 18:26:19 -0800225 contractedHeader.getPaddingBottom());
226 contractedHeader.setShowWorkBadgeAtEnd(false);
227 return true;
228 }
229 }
230 }
231 return false;
232 }
233
Selim Cinek860b6da2015-12-16 19:02:19 -0800234 private boolean shouldContractedBeFixedSize() {
235 return mBeforeN && mContractedWrapper instanceof NotificationCustomViewWrapper;
236 }
237
Selim Cinek8d490d42015-04-10 00:05:50 -0700238 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +0200239 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
240 super.onLayout(changed, left, top, right, bottom);
241 updateClipping();
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700242 invalidateOutline();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200243 }
244
Selim Cinekbb3d1cf2014-10-31 00:12:56 +0100245 @Override
Selim Cinek7b8157e2014-11-20 16:00:32 +0100246 protected void onAttachedToWindow() {
247 super.onAttachedToWindow();
Selim Cinekbb3d1cf2014-10-31 00:12:56 +0100248 updateVisibility();
249 }
250
Selim Cinek1a521f32014-11-03 17:39:29 +0100251 public void reset(boolean resetActualHeight) {
Jorim Jaggi0d9f35d2014-08-20 17:06:55 +0200252 if (mContractedChild != null) {
253 mContractedChild.animate().cancel();
Selim Cinekde33a4a2016-02-11 16:43:41 -0800254 removeView(mContractedChild);
Jorim Jaggi0d9f35d2014-08-20 17:06:55 +0200255 }
256 if (mExpandedChild != null) {
257 mExpandedChild.animate().cancel();
Selim Cinekde33a4a2016-02-11 16:43:41 -0800258 removeView(mExpandedChild);
Jorim Jaggi0d9f35d2014-08-20 17:06:55 +0200259 }
Selim Cinek8d490d42015-04-10 00:05:50 -0700260 if (mHeadsUpChild != null) {
261 mHeadsUpChild.animate().cancel();
Selim Cinekde33a4a2016-02-11 16:43:41 -0800262 removeView(mHeadsUpChild);
Selim Cinek8d490d42015-04-10 00:05:50 -0700263 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200264 mContractedChild = null;
265 mExpandedChild = null;
Selim Cinek1f3f5442015-04-10 17:54:46 -0700266 mHeadsUpChild = null;
Selim Cinek684a4422015-04-15 16:18:39 -0700267 mVisibleType = VISIBLE_TYPE_CONTRACTED;
Selim Cinek1a521f32014-11-03 17:39:29 +0100268 if (resetActualHeight) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100269 mContentHeight = mSmallHeight;
Selim Cinek1a521f32014-11-03 17:39:29 +0100270 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200271 }
272
Selim Cinekcab4a602014-09-03 14:47:57 +0200273 public View getContractedChild() {
274 return mContractedChild;
275 }
276
277 public View getExpandedChild() {
278 return mExpandedChild;
279 }
280
Selim Cinek8d490d42015-04-10 00:05:50 -0700281 public View getHeadsUpChild() {
282 return mHeadsUpChild;
283 }
284
Jorim Jaggibe565df2014-04-28 17:51:23 +0200285 public void setContractedChild(View child) {
286 if (mContractedChild != null) {
Jorim Jaggi0d9f35d2014-08-20 17:06:55 +0200287 mContractedChild.animate().cancel();
Selim Cinek30e387d2016-01-11 18:01:47 -0800288 mContractedChild.removeOnLayoutChangeListener(mLayoutUpdater);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200289 removeView(mContractedChild);
290 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200291 addView(child);
292 mContractedChild = child;
Selim Cinek30e387d2016-01-11 18:01:47 -0800293 mContractedChild.addOnLayoutChangeListener(mLayoutUpdater);
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100294 mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child);
Jorim Jaggi11298832014-05-24 16:18:38 +0200295 selectLayout(false /* animate */, true /* force */);
Jorim Jaggi10ad7612014-12-08 18:41:11 +0100296 mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200297 }
298
299 public void setExpandedChild(View child) {
300 if (mExpandedChild != null) {
Jorim Jaggi0d9f35d2014-08-20 17:06:55 +0200301 mExpandedChild.animate().cancel();
Selim Cinek30e387d2016-01-11 18:01:47 -0800302 mExpandedChild.removeOnLayoutChangeListener(mLayoutUpdater);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200303 removeView(mExpandedChild);
304 }
305 addView(child);
306 mExpandedChild = child;
Selim Cinek30e387d2016-01-11 18:01:47 -0800307 mExpandedChild.addOnLayoutChangeListener(mLayoutUpdater);
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700308 mExpandedWrapper = NotificationViewWrapper.wrap(getContext(), child);
Jorim Jaggi11298832014-05-24 16:18:38 +0200309 selectLayout(false /* animate */, true /* force */);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200310 }
311
Selim Cinek8d490d42015-04-10 00:05:50 -0700312 public void setHeadsUpChild(View child) {
313 if (mHeadsUpChild != null) {
314 mHeadsUpChild.animate().cancel();
Selim Cinek30e387d2016-01-11 18:01:47 -0800315 mHeadsUpChild.removeOnLayoutChangeListener(mLayoutUpdater);
Selim Cinek8d490d42015-04-10 00:05:50 -0700316 removeView(mHeadsUpChild);
317 }
318 addView(child);
319 mHeadsUpChild = child;
Selim Cinek30e387d2016-01-11 18:01:47 -0800320 mHeadsUpChild.addOnLayoutChangeListener(mLayoutUpdater);
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700321 mHeadsUpWrapper = NotificationViewWrapper.wrap(getContext(), child);
Selim Cinek8d490d42015-04-10 00:05:50 -0700322 selectLayout(false /* animate */, true /* force */);
323 }
324
Selim Cinekbb3d1cf2014-10-31 00:12:56 +0100325 @Override
326 protected void onVisibilityChanged(View changedView, int visibility) {
327 super.onVisibilityChanged(changedView, visibility);
328 updateVisibility();
329 }
330
331 private void updateVisibility() {
332 setVisible(isShown());
333 }
334
335 private void setVisible(final boolean isVisible) {
336 if (isVisible) {
337
338 // We only animate if we are drawn at least once, otherwise the view might animate when
339 // it's shown the first time
340 getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener);
341 } else {
342 getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
343 mAnimate = false;
344 }
345 }
346
Selim Cinekb5605e52015-02-20 18:21:41 +0100347 public void setContentHeight(int contentHeight) {
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700348 mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());;
349 mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
Selim Cinekbb3d1cf2014-10-31 00:12:56 +0100350 selectLayout(mAnimate /* animate */, false /* force */);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200351 updateClipping();
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700352 invalidateOutline();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200353 }
354
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800355 private void updateContentTransformation() {
356 int visibleType = calculateVisibleType();
357 if (visibleType != mVisibleType) {
358 // A new transformation starts
359 mTransformationStartVisibleType = mVisibleType;
360 final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
361 final TransformableView hiddenView = getTransformableViewForVisibleType(
362 mTransformationStartVisibleType);
363 shownView.transformFrom(hiddenView, 0.0f);
364 getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
365 hiddenView.transformTo(shownView, 0.0f);
366 mVisibleType = visibleType;
367 }
368 if (mTransformationStartVisibleType != UNDEFINED
369 && mVisibleType != mTransformationStartVisibleType) {
370 final TransformableView shownView = getTransformableViewForVisibleType(mVisibleType);
371 final TransformableView hiddenView = getTransformableViewForVisibleType(
372 mTransformationStartVisibleType);
373 float transformationAmount = calculateTransformationAmount();
374 shownView.transformFrom(hiddenView, transformationAmount);
375 hiddenView.transformTo(shownView, transformationAmount);
376 } else {
377 updateViewVisibilities(visibleType);
378 }
379 }
380
381 private float calculateTransformationAmount() {
382 int startHeight = getViewForVisibleType(mTransformationStartVisibleType).getHeight();
383 int endHeight = getViewForVisibleType(mVisibleType).getHeight();
384 int progress = Math.abs(mContentHeight - startHeight);
385 int totalDistance = Math.abs(endHeight - startHeight);
386 float amount = (float) progress / (float) totalDistance;
387 return Math.min(1.0f, amount);
388 }
389
Selim Cinekb5605e52015-02-20 18:21:41 +0100390 public int getContentHeight() {
391 return mContentHeight;
392 }
393
Jorim Jaggibe565df2014-04-28 17:51:23 +0200394 public int getMaxHeight() {
Selim Cinek77019c72015-12-09 10:18:02 -0800395 if (mExpandedChild != null) {
Selim Cinek8d490d42015-04-10 00:05:50 -0700396 return mExpandedChild.getHeight();
Selim Cinek77019c72015-12-09 10:18:02 -0800397 } else if (mIsHeadsUp && mHeadsUpChild != null) {
398 return mHeadsUpChild.getHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -0700399 }
Selim Cinek860b6da2015-12-16 19:02:19 -0800400 return mContractedChild.getHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200401 }
402
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200403 public int getMinHeight() {
Selim Cinek42357e02016-02-24 18:48:01 -0800404 return getMinHeight(false /* likeGroupExpanded */);
405 }
406
407 public int getMinHeight(boolean likeGroupExpanded) {
408 if (likeGroupExpanded || !mIsChildInGroup || isGroupExpanded()) {
Selim Cinek860b6da2015-12-16 19:02:19 -0800409 return mContractedChild.getHeight();
Selim Cinek42357e02016-02-24 18:48:01 -0800410 } else {
411 return mSingleLineView.getHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -0700412 }
413 }
414
415 private boolean isGroupExpanded() {
416 return mGroupManager.isGroupExpanded(mStatusBarNotification);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200417 }
418
Jorim Jaggibe565df2014-04-28 17:51:23 +0200419 public void setClipTopAmount(int clipTopAmount) {
Selim Cinekc9c00ae2014-05-20 03:33:40 +0200420 mClipTopAmount = clipTopAmount;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200421 updateClipping();
422 }
423
Jorim Jaggibe565df2014-04-28 17:51:23 +0200424 private void updateClipping() {
Selim Cinek4ffd6362015-12-29 15:12:23 +0100425 if (mClipToActualHeight) {
426 mClipBounds.set(0, mClipTopAmount, getWidth(), mContentHeight);
427 setClipBounds(mClipBounds);
428 } else {
429 setClipBounds(null);
430 }
431 }
432
433 public void setClipToActualHeight(boolean clipToActualHeight) {
434 mClipToActualHeight = clipToActualHeight;
435 updateClipping();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200436 }
437
Jorim Jaggi11298832014-05-24 16:18:38 +0200438 private void selectLayout(boolean animate, boolean force) {
439 if (mContractedChild == null) {
440 return;
441 }
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800442 if (mUserExpanding) {
443 updateContentTransformation();
444 return;
445 }
Selim Cinek684a4422015-04-15 16:18:39 -0700446 int visibleType = calculateVisibleType();
447 if (visibleType != mVisibleType || force) {
Jorim Jaggi021eee52015-06-11 17:07:18 -0700448 if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
Selim Cinek684a4422015-04-15 16:18:39 -0700449 || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
Selim Cinek83bc7832015-10-22 13:26:54 -0700450 || (visibleType == VISIBLE_TYPE_SINGLELINE && mSingleLineView != null)
Jorim Jaggi021eee52015-06-11 17:07:18 -0700451 || visibleType == VISIBLE_TYPE_CONTRACTED)) {
Selim Cinek4ffd6362015-12-29 15:12:23 +0100452 animateToVisibleType(visibleType);
Selim Cinek8d490d42015-04-10 00:05:50 -0700453 } else {
Selim Cinek684a4422015-04-15 16:18:39 -0700454 updateViewVisibilities(visibleType);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200455 }
Selim Cinek684a4422015-04-15 16:18:39 -0700456 mVisibleType = visibleType;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200457 }
Jorim Jaggi11298832014-05-24 16:18:38 +0200458 }
459
Selim Cinek684a4422015-04-15 16:18:39 -0700460 private void updateViewVisibilities(int visibleType) {
461 boolean contractedVisible = visibleType == VISIBLE_TYPE_CONTRACTED;
Selim Cinek4ffd6362015-12-29 15:12:23 +0100462 mContractedWrapper.setVisible(contractedVisible);
Selim Cinek8d490d42015-04-10 00:05:50 -0700463 if (mExpandedChild != null) {
Selim Cinek684a4422015-04-15 16:18:39 -0700464 boolean expandedVisible = visibleType == VISIBLE_TYPE_EXPANDED;
Selim Cinek4ffd6362015-12-29 15:12:23 +0100465 mExpandedWrapper.setVisible(expandedVisible);
Selim Cinek8d490d42015-04-10 00:05:50 -0700466 }
467 if (mHeadsUpChild != null) {
Selim Cinek684a4422015-04-15 16:18:39 -0700468 boolean headsUpVisible = visibleType == VISIBLE_TYPE_HEADSUP;
Selim Cinek4ffd6362015-12-29 15:12:23 +0100469 mHeadsUpWrapper.setVisible(headsUpVisible);
Selim Cinek8d490d42015-04-10 00:05:50 -0700470 }
Selim Cinek83bc7832015-10-22 13:26:54 -0700471 if (mSingleLineView != null) {
472 boolean singleLineVisible = visibleType == VISIBLE_TYPE_SINGLELINE;
Selim Cinek4ffd6362015-12-29 15:12:23 +0100473 mSingleLineView.setVisible(singleLineVisible);
Selim Cinek83bc7832015-10-22 13:26:54 -0700474 }
Selim Cinek8d490d42015-04-10 00:05:50 -0700475 }
476
Selim Cinek4ffd6362015-12-29 15:12:23 +0100477 private void animateToVisibleType(int visibleType) {
478 final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
479 final TransformableView hiddenView = getTransformableViewForVisibleType(mVisibleType);
480 shownView.transformFrom(hiddenView);
481 getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
482 hiddenView.transformTo(shownView, new Runnable() {
483 @Override
484 public void run() {
485 hiddenView.setVisible(false);
486 }
487 });
Jorim Jaggi11298832014-05-24 16:18:38 +0200488 }
489
Selim Cinek684a4422015-04-15 16:18:39 -0700490 /**
491 * @param visibleType one of the static enum types in this view
Selim Cinek4ffd6362015-12-29 15:12:23 +0100492 * @return the corresponding transformable view according to the given visible type
493 */
494 private TransformableView getTransformableViewForVisibleType(int visibleType) {
495 switch (visibleType) {
496 case VISIBLE_TYPE_EXPANDED:
497 return mExpandedWrapper;
498 case VISIBLE_TYPE_HEADSUP:
499 return mHeadsUpWrapper;
500 case VISIBLE_TYPE_SINGLELINE:
501 return mSingleLineView;
502 default:
503 return mContractedWrapper;
504 }
505 }
506
507 /**
508 * @param visibleType one of the static enum types in this view
Selim Cinek684a4422015-04-15 16:18:39 -0700509 * @return the corresponding view according to the given visible type
510 */
511 private View getViewForVisibleType(int visibleType) {
512 switch (visibleType) {
513 case VISIBLE_TYPE_EXPANDED:
Selim Cinek8d490d42015-04-10 00:05:50 -0700514 return mExpandedChild;
Selim Cinek684a4422015-04-15 16:18:39 -0700515 case VISIBLE_TYPE_HEADSUP:
Selim Cinek8d490d42015-04-10 00:05:50 -0700516 return mHeadsUpChild;
Selim Cinek83bc7832015-10-22 13:26:54 -0700517 case VISIBLE_TYPE_SINGLELINE:
518 return mSingleLineView;
Selim Cinek684a4422015-04-15 16:18:39 -0700519 default:
520 return mContractedChild;
Selim Cinek8d490d42015-04-10 00:05:50 -0700521 }
Selim Cinek8d490d42015-04-10 00:05:50 -0700522 }
523
Selim Cinek34eda5e2016-02-18 17:10:43 -0800524 private NotificationViewWrapper getCurrentVisibleWrapper() {
525 switch (mVisibleType) {
526 case VISIBLE_TYPE_EXPANDED:
527 return mExpandedWrapper;
528 case VISIBLE_TYPE_HEADSUP:
529 return mHeadsUpWrapper;
530 case VISIBLE_TYPE_CONTRACTED:
531 return mContractedWrapper;
532 default:
533 return null;
534 }
535 }
536
Selim Cinek684a4422015-04-15 16:18:39 -0700537 /**
538 * @return one of the static enum types in this view, calculated form the current state
539 */
540 private int calculateVisibleType() {
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800541 if (mUserExpanding) {
Selim Cinek42357e02016-02-24 18:48:01 -0800542 int height = !mIsChildInGroup || isGroupExpanded()
543 || mContainingNotification.isExpanded()
544 ? mContainingNotification.getMaxContentHeight()
545 : mContainingNotification.getShowingLayout().getMinHeight();
546 int expandedVisualType = getVisualTypeForHeight(height);
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800547 int collapsedVisualType = getVisualTypeForHeight(
548 mContainingNotification.getMinExpandHeight());
549 return mTransformationStartVisibleType == collapsedVisualType
550 ? expandedVisualType
551 : collapsedVisualType;
552 }
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800553 int viewHeight = Math.min(mContentHeight, mContainingNotification.getIntrinsicHeight());
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800554 return getVisualTypeForHeight(viewHeight);
555 }
556
557 private int getVisualTypeForHeight(float viewHeight) {
558 boolean noExpandedChild = mExpandedChild == null;
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800559 if (!noExpandedChild && viewHeight == mExpandedChild.getHeight()) {
Adrian Roos777ef562015-12-01 17:37:14 -0800560 return VISIBLE_TYPE_EXPANDED;
561 }
Selim Cinek42357e02016-02-24 18:48:01 -0800562 if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded()) {
Selim Cinekd84a5932015-12-15 11:45:36 -0800563 return VISIBLE_TYPE_SINGLELINE;
564 }
Adrian Roos777ef562015-12-01 17:37:14 -0800565
Selim Cinek1f3f5442015-04-10 17:54:46 -0700566 if (mIsHeadsUp && mHeadsUpChild != null) {
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800567 if (viewHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
Selim Cinek684a4422015-04-15 16:18:39 -0700568 return VISIBLE_TYPE_HEADSUP;
Selim Cinek8d490d42015-04-10 00:05:50 -0700569 } else {
Selim Cinek684a4422015-04-15 16:18:39 -0700570 return VISIBLE_TYPE_EXPANDED;
Selim Cinek8d490d42015-04-10 00:05:50 -0700571 }
572 } else {
Selim Cineka4091502016-02-11 17:21:16 -0800573 if (noExpandedChild || (viewHeight <= mContractedChild.getHeight()
574 && (!mIsChildInGroup || !mContainingNotification.isExpanded()))) {
Selim Cinek684a4422015-04-15 16:18:39 -0700575 return VISIBLE_TYPE_CONTRACTED;
Selim Cinek8d490d42015-04-10 00:05:50 -0700576 } else {
Selim Cinek684a4422015-04-15 16:18:39 -0700577 return VISIBLE_TYPE_EXPANDED;
Selim Cinek8d490d42015-04-10 00:05:50 -0700578 }
579 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200580 }
581
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200582 public boolean isContentExpandable() {
583 return mExpandedChild != null;
584 }
John Spurlocke15452b2014-08-21 09:44:39 -0400585
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100586 public void setDark(boolean dark, boolean fade, long delay) {
Selim Cinekb88b9842016-02-26 09:25:33 -0800587 if (mContractedChild == null) {
Selim Cinek0934bd92016-02-19 12:22:33 -0800588 return;
589 }
John Spurlocke15452b2014-08-21 09:44:39 -0400590 mDark = dark;
Selim Cinek30e387d2016-01-11 18:01:47 -0800591 dark = dark && !mShowingLegacyBackground;
Selim Cinek19ba7052016-01-27 20:04:27 -0800592 if (mVisibleType == VISIBLE_TYPE_CONTRACTED || !dark) {
Selim Cinek30e387d2016-01-11 18:01:47 -0800593 mContractedWrapper.setDark(dark, fade, delay);
594 }
Selim Cinek19ba7052016-01-27 20:04:27 -0800595 if (mVisibleType == VISIBLE_TYPE_EXPANDED || (mExpandedChild != null && !dark)) {
Selim Cinek30e387d2016-01-11 18:01:47 -0800596 mExpandedWrapper.setDark(dark, fade, delay);
597 }
Selim Cinek19ba7052016-01-27 20:04:27 -0800598 if (mVisibleType == VISIBLE_TYPE_HEADSUP || (mHeadsUpChild != null && !dark)) {
Selim Cinek30e387d2016-01-11 18:01:47 -0800599 mHeadsUpWrapper.setDark(dark, fade, delay);
600 }
Selim Cinek19ba7052016-01-27 20:04:27 -0800601 if (mSingleLineView != null && (mVisibleType == VISIBLE_TYPE_SINGLELINE || !dark)) {
Selim Cinek9c7712d2015-12-08 19:19:48 -0800602 mSingleLineView.setDark(dark, fade, delay);
603 }
John Spurlocke15452b2014-08-21 09:44:39 -0400604 }
605
Selim Cinek8d490d42015-04-10 00:05:50 -0700606 public void setHeadsUp(boolean headsUp) {
607 mIsHeadsUp = headsUp;
608 selectLayout(false /* animate */, true /* force */);
Selim Cinek98be3f32015-12-17 16:39:06 -0800609 updateExpandButtons(mExpandable);
Selim Cinek8d490d42015-04-10 00:05:50 -0700610 }
611
Jorim Jaggiaa92ffb2014-09-10 23:29:28 +0200612 @Override
613 public boolean hasOverlappingRendering() {
614
615 // This is not really true, but good enough when fading from the contracted to the expanded
616 // layout, and saves us some layers.
617 return false;
618 }
Jorim Jaggi59ec3042015-06-05 15:18:43 -0700619
620 public void setShowingLegacyBackground(boolean showing) {
621 mShowingLegacyBackground = showing;
622 }
Selim Cinek8d6440d2015-10-22 13:00:05 -0700623
Selim Cinek83bc7832015-10-22 13:26:54 -0700624 public void setIsChildInGroup(boolean isChildInGroup) {
625 mIsChildInGroup = isChildInGroup;
626 updateSingleLineView();
627 }
628
Adrian Roosb88b1a12015-12-09 18:51:05 -0800629 public void onNotificationUpdated(NotificationData.Entry entry) {
630 mStatusBarNotification = entry.notification;
Selim Cinek860b6da2015-12-16 19:02:19 -0800631 mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
Selim Cinek83bc7832015-10-22 13:26:54 -0700632 updateSingleLineView();
Adrian Roosb88b1a12015-12-09 18:51:05 -0800633 applyRemoteInput(entry);
Selim Cinek8fc93c92015-11-23 17:48:07 -0800634 selectLayout(false /* animate */, true /* force */);
635 if (mContractedChild != null) {
Selim Cinek4ffd6362015-12-29 15:12:23 +0100636 mContractedWrapper.notifyContentUpdated(entry.notification);
Selim Cinek8fc93c92015-11-23 17:48:07 -0800637 }
638 if (mExpandedChild != null) {
Selim Cinek4ffd6362015-12-29 15:12:23 +0100639 mExpandedWrapper.notifyContentUpdated(entry.notification);
Selim Cinek8fc93c92015-11-23 17:48:07 -0800640 }
641 if (mHeadsUpChild != null) {
Selim Cinek4ffd6362015-12-29 15:12:23 +0100642 mHeadsUpWrapper.notifyContentUpdated(entry.notification);
Selim Cinek8fc93c92015-11-23 17:48:07 -0800643 }
Selim Cinekb88b9842016-02-26 09:25:33 -0800644 setDark(mDark, false /* animate */, 0 /* delay */);
Selim Cinek83bc7832015-10-22 13:26:54 -0700645 }
646
647 private void updateSingleLineView() {
648 if (mIsChildInGroup) {
649 mSingleLineView = mHybridViewManager.bindFromNotification(
650 mSingleLineView, mStatusBarNotification.getNotification());
Selim Cinekde33a4a2016-02-11 16:43:41 -0800651 } else if (mSingleLineView != null) {
652 removeView(mSingleLineView);
653 mSingleLineView = null;
Selim Cinek83bc7832015-10-22 13:26:54 -0700654 }
655 }
656
Adrian Roosb88b1a12015-12-09 18:51:05 -0800657 private void applyRemoteInput(final NotificationData.Entry entry) {
658 if (mRemoteInputController == null) {
659 return;
660 }
661
662 boolean hasRemoteInput = false;
663
664 Notification.Action[] actions = entry.notification.getNotification().actions;
665 if (actions != null) {
666 for (Notification.Action a : actions) {
667 if (a.getRemoteInputs() != null) {
668 for (RemoteInput ri : a.getRemoteInputs()) {
669 if (ri.getAllowFreeFormInput()) {
670 hasRemoteInput = true;
671 break;
672 }
673 }
674 }
675 }
676 }
677
678 View bigContentView = mExpandedChild;
679 if (bigContentView != null) {
680 applyRemoteInput(bigContentView, entry, hasRemoteInput);
681 }
682 View headsUpContentView = mHeadsUpChild;
683 if (headsUpContentView != null) {
684 applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
685 }
686 }
687
688 private void applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
689 View actionContainerCandidate = view.findViewById(
690 com.android.internal.R.id.actions_container);
691 if (actionContainerCandidate instanceof FrameLayout) {
692 RemoteInputView existing = (RemoteInputView)
693 view.findViewWithTag(RemoteInputView.VIEW_TAG);
694
695 if (existing != null) {
696 existing.onNotificationUpdate();
697 }
698
699 if (existing == null && hasRemoteInput) {
700 ViewGroup actionContainer = (FrameLayout) actionContainerCandidate;
701 RemoteInputView riv = RemoteInputView.inflate(
702 mContext, actionContainer, entry, mRemoteInputController);
703
704 riv.setVisibility(View.INVISIBLE);
705 actionContainer.addView(riv, new LayoutParams(
706 ViewGroup.LayoutParams.MATCH_PARENT,
707 ViewGroup.LayoutParams.MATCH_PARENT)
708 );
709 int color = entry.notification.getNotification().color;
710 if (color == Notification.COLOR_DEFAULT) {
711 color = mContext.getColor(R.color.default_remote_input_background);
712 }
713 riv.setBackgroundColor(color);
714 }
715 }
716 }
717
Selim Cinek83bc7832015-10-22 13:26:54 -0700718 public void setGroupManager(NotificationGroupManager groupManager) {
719 mGroupManager = groupManager;
720 }
Selim Cinek65b2e7c2015-10-26 14:11:31 -0700721
Adrian Roosb88b1a12015-12-09 18:51:05 -0800722 public void setRemoteInputController(RemoteInputController r) {
723 mRemoteInputController = r;
724 }
725
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800726 public void setExpandClickListener(OnClickListener expandClickListener) {
727 mExpandClickListener = expandClickListener;
728 }
729
730 public void updateExpandButtons(boolean expandable) {
Selim Cinek98be3f32015-12-17 16:39:06 -0800731 mExpandable = expandable;
732 // if the expanded child has the same height as the collapsed one we hide it.
733 if (mExpandedChild != null && mExpandedChild.getHeight() != 0 &&
734 ((mIsHeadsUp && mExpandedChild.getHeight() == mHeadsUpChild.getHeight()) ||
735 (!mIsHeadsUp && mExpandedChild.getHeight() == mContractedChild.getHeight()))) {
736 expandable = false;
737 }
Selim Cinek65b2e7c2015-10-26 14:11:31 -0700738 if (mExpandedChild != null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800739 mExpandedWrapper.updateExpandability(expandable, mExpandClickListener);
Selim Cinek65b2e7c2015-10-26 14:11:31 -0700740 }
741 if (mContractedChild != null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800742 mContractedWrapper.updateExpandability(expandable, mExpandClickListener);
Selim Cinek65b2e7c2015-10-26 14:11:31 -0700743 }
744 if (mHeadsUpChild != null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800745 mHeadsUpWrapper.updateExpandability(expandable, mExpandClickListener);
Selim Cinek65b2e7c2015-10-26 14:11:31 -0700746 }
747 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800748
749 public NotificationHeaderView getNotificationHeader() {
750 NotificationHeaderView header = null;
751 if (mContractedChild != null) {
752 header = mContractedWrapper.getNotificationHeader();
753 }
754 if (header == null && mExpandedChild != null) {
755 header = mExpandedWrapper.getNotificationHeader();
756 }
757 if (header == null && mHeadsUpChild != null) {
758 header = mHeadsUpWrapper.getNotificationHeader();
759 }
760 return header;
761 }
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800762
Selim Cinek34eda5e2016-02-18 17:10:43 -0800763 public NotificationHeaderView getVisibleNotificationHeader() {
764 NotificationViewWrapper wrapper = getCurrentVisibleWrapper();
765 return wrapper == null ? null : wrapper.getNotificationHeader();
766 }
767
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800768 public void setContainingNotification(ExpandableNotificationRow containingNotification) {
769 mContainingNotification = containingNotification;
770 }
771
772 public void requestSelectLayout(boolean needsAnimation) {
773 selectLayout(needsAnimation, false);
774 }
Selim Cinekde33a4a2016-02-11 16:43:41 -0800775
776 public void reInflateViews() {
777 if (mIsChildInGroup && mSingleLineView != null) {
778 removeView(mSingleLineView);
779 mSingleLineView = null;
780 updateSingleLineView();
781 }
782 }
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800783
784 public void setUserExpanding(boolean userExpanding) {
785 mUserExpanding = userExpanding;
786 if (userExpanding) {
787 mTransformationStartVisibleType = mVisibleType;
788 } else {
789 mTransformationStartVisibleType = UNDEFINED;
790 mVisibleType = calculateVisibleType();
791 updateViewVisibilities(mVisibleType);
792 }
793 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200794}