blob: dec2fc75501b70aa5ef8d2d00ad29c44709d66f0 [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
19import android.content.Context;
Jorim Jaggibe4116a2015-05-20 20:04:08 -070020import android.graphics.Outline;
Jorim Jaggi11298832014-05-24 16:18:38 +020021import android.graphics.Paint;
22import android.graphics.PorterDuff;
23import android.graphics.PorterDuffXfermode;
Jorim Jaggibe565df2014-04-28 17:51:23 +020024import android.graphics.Rect;
25import android.util.AttributeSet;
Jorim Jaggibe565df2014-04-28 17:51:23 +020026import android.view.View;
Selim Cinek8d490d42015-04-10 00:05:50 -070027import android.view.ViewGroup;
Jorim Jaggibe4116a2015-05-20 20:04:08 -070028import android.view.ViewOutlineProvider;
Selim Cinekbb3d1cf2014-10-31 00:12:56 +010029import android.view.ViewTreeObserver;
Jorim Jaggi11298832014-05-24 16:18:38 +020030import android.view.animation.Interpolator;
31import android.view.animation.LinearInterpolator;
Selim Cinekc9c00ae2014-05-20 03:33:40 +020032import android.widget.FrameLayout;
Selim Cinek8d490d42015-04-10 00:05:50 -070033
Jorim Jaggibe565df2014-04-28 17:51:23 +020034import com.android.systemui.R;
35
36/**
Selim Cinek684a4422015-04-15 16:18:39 -070037 * A frame layout containing the actual payload of the notification, including the contracted,
38 * expanded and heads up layout. This class is responsible for clipping the content and and
39 * switching between the expanded, contracted and the heads up view depending on its clipped size.
Jorim Jaggibe565df2014-04-28 17:51:23 +020040 */
Selim Cinekc9c00ae2014-05-20 03:33:40 +020041public class NotificationContentView extends FrameLayout {
Jorim Jaggibe565df2014-04-28 17:51:23 +020042
Jorim Jaggi11298832014-05-24 16:18:38 +020043 private static final long ANIMATION_DURATION_LENGTH = 170;
Selim Cinek684a4422015-04-15 16:18:39 -070044 private static final int VISIBLE_TYPE_CONTRACTED = 0;
45 private static final int VISIBLE_TYPE_EXPANDED = 1;
46 private static final int VISIBLE_TYPE_HEADSUP = 2;
Jorim Jaggi11298832014-05-24 16:18:38 +020047
Jorim Jaggibe565df2014-04-28 17:51:23 +020048 private final Rect mClipBounds = new Rect();
Selim Cinek684a4422015-04-15 16:18:39 -070049 private final int mSmallHeight;
50 private final int mHeadsUpHeight;
Jorim Jaggibe4116a2015-05-20 20:04:08 -070051 private final int mRoundRectRadius;
Selim Cinek684a4422015-04-15 16:18:39 -070052 private final Interpolator mLinearInterpolator = new LinearInterpolator();
Jorim Jaggibe4116a2015-05-20 20:04:08 -070053 private final boolean mRoundRectClippingEnabled;
Jorim Jaggibe565df2014-04-28 17:51:23 +020054
55 private View mContractedChild;
56 private View mExpandedChild;
Selim Cinek8d490d42015-04-10 00:05:50 -070057 private View mHeadsUpChild;
Jorim Jaggibe565df2014-04-28 17:51:23 +020058
Jorim Jaggi4e857f42014-11-17 19:14:04 +010059 private NotificationViewWrapper mContractedWrapper;
Jorim Jaggibe4116a2015-05-20 20:04:08 -070060 private NotificationViewWrapper mExpandedWrapper;
61 private NotificationViewWrapper mHeadsUpWrapper;
Selim Cinekc9c00ae2014-05-20 03:33:40 +020062 private int mClipTopAmount;
Selim Cinekb5605e52015-02-20 18:21:41 +010063 private int mContentHeight;
Jorim Jaggibe4116a2015-05-20 20:04:08 -070064 private int mUnrestrictedContentHeight;
Selim Cinek684a4422015-04-15 16:18:39 -070065 private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
John Spurlocke15452b2014-08-21 09:44:39 -040066 private boolean mDark;
Christoph Studera7fe6312014-06-27 19:32:44 +020067 private final Paint mFadePaint = new Paint();
Selim Cinekbb3d1cf2014-10-31 00:12:56 +010068 private boolean mAnimate;
Selim Cinek684a4422015-04-15 16:18:39 -070069 private boolean mIsHeadsUp;
Jorim Jaggibe4116a2015-05-20 20:04:08 -070070 private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
Selim Cinekbb3d1cf2014-10-31 00:12:56 +010071 = new ViewTreeObserver.OnPreDrawListener() {
72 @Override
73 public boolean onPreDraw() {
74 mAnimate = true;
75 getViewTreeObserver().removeOnPreDrawListener(this);
76 return true;
77 }
78 };
Jorim Jaggi11298832014-05-24 16:18:38 +020079
Jorim Jaggibe4116a2015-05-20 20:04:08 -070080 private final ViewOutlineProvider mOutlineProvider = new ViewOutlineProvider() {
81 @Override
82 public void getOutline(View view, Outline outline) {
83 outline.setRoundRect(0, 0, view.getWidth(), mUnrestrictedContentHeight,
84 mRoundRectRadius);
85 }
86 };
87
Jorim Jaggibe565df2014-04-28 17:51:23 +020088 public NotificationContentView(Context context, AttributeSet attrs) {
89 super(context, attrs);
Jorim Jaggi11298832014-05-24 16:18:38 +020090 mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
Selim Cinek1f3f5442015-04-10 17:54:46 -070091 mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
92 mHeadsUpHeight = getResources().getDimensionPixelSize(R.dimen.notification_mid_height);
Jorim Jaggibe4116a2015-05-20 20:04:08 -070093 mRoundRectRadius = getResources().getDimensionPixelSize(
94 R.dimen.notification_material_rounded_rect_radius);
95 mRoundRectClippingEnabled = getResources().getBoolean(
96 R.bool.config_notifications_round_rect_clipping);
Selim Cinek1a521f32014-11-03 17:39:29 +010097 reset(true);
Jorim Jaggibe4116a2015-05-20 20:04:08 -070098 setOutlineProvider(mOutlineProvider);
Jorim Jaggibe565df2014-04-28 17:51:23 +020099 }
100
101 @Override
Selim Cinek8d490d42015-04-10 00:05:50 -0700102 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
103 int heightMode = MeasureSpec.getMode(heightMeasureSpec);
104 boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
105 boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
106 int maxSize = Integer.MAX_VALUE;
107 if (hasFixedHeight || isHeightLimited) {
108 maxSize = MeasureSpec.getSize(heightMeasureSpec);
109 }
110 int maxChildHeight = 0;
111 if (mContractedChild != null) {
112 int size = Math.min(maxSize, mSmallHeight);
113 mContractedChild.measure(widthMeasureSpec,
Selim Cinek06a24ebd2015-04-22 14:22:05 -0700114 MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY));
Selim Cinek8d490d42015-04-10 00:05:50 -0700115 maxChildHeight = Math.max(maxChildHeight, mContractedChild.getMeasuredHeight());
116 }
117 if (mExpandedChild != null) {
118 int size = maxSize;
119 ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams();
120 if (layoutParams.height >= 0) {
121 // An actual height is set
122 size = Math.min(maxSize, layoutParams.height);
123 }
Selim Cinek684a4422015-04-15 16:18:39 -0700124 int spec = size == Integer.MAX_VALUE
125 ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
126 : MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
Selim Cinek8d490d42015-04-10 00:05:50 -0700127 mExpandedChild.measure(widthMeasureSpec, spec);
128 maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
129 }
130 if (mHeadsUpChild != null) {
131 int size = Math.min(maxSize, mHeadsUpHeight);
132 ViewGroup.LayoutParams layoutParams = mHeadsUpChild.getLayoutParams();
133 if (layoutParams.height >= 0) {
134 // An actual height is set
135 size = Math.min(maxSize, layoutParams.height);
136 }
137 mHeadsUpChild.measure(widthMeasureSpec,
138 MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST));
139 maxChildHeight = Math.max(maxChildHeight, mHeadsUpChild.getMeasuredHeight());
140 }
141 int ownHeight = Math.min(maxChildHeight, maxSize);
142 int width = MeasureSpec.getSize(widthMeasureSpec);
143 setMeasuredDimension(width, ownHeight);
144 }
145
146 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +0200147 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
148 super.onLayout(changed, left, top, right, bottom);
149 updateClipping();
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700150 invalidateOutline();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200151 }
152
Selim Cinekbb3d1cf2014-10-31 00:12:56 +0100153 @Override
Selim Cinek7b8157e2014-11-20 16:00:32 +0100154 protected void onAttachedToWindow() {
155 super.onAttachedToWindow();
Selim Cinekbb3d1cf2014-10-31 00:12:56 +0100156 updateVisibility();
157 }
158
Selim Cinek1a521f32014-11-03 17:39:29 +0100159 public void reset(boolean resetActualHeight) {
Jorim Jaggi0d9f35d2014-08-20 17:06:55 +0200160 if (mContractedChild != null) {
161 mContractedChild.animate().cancel();
162 }
163 if (mExpandedChild != null) {
164 mExpandedChild.animate().cancel();
165 }
Selim Cinek8d490d42015-04-10 00:05:50 -0700166 if (mHeadsUpChild != null) {
167 mHeadsUpChild.animate().cancel();
168 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200169 removeAllViews();
170 mContractedChild = null;
171 mExpandedChild = null;
Selim Cinek1f3f5442015-04-10 17:54:46 -0700172 mHeadsUpChild = null;
Selim Cinek684a4422015-04-15 16:18:39 -0700173 mVisibleType = VISIBLE_TYPE_CONTRACTED;
Selim Cinek1a521f32014-11-03 17:39:29 +0100174 if (resetActualHeight) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100175 mContentHeight = mSmallHeight;
Selim Cinek1a521f32014-11-03 17:39:29 +0100176 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200177 }
178
Selim Cinekcab4a602014-09-03 14:47:57 +0200179 public View getContractedChild() {
180 return mContractedChild;
181 }
182
183 public View getExpandedChild() {
184 return mExpandedChild;
185 }
186
Selim Cinek8d490d42015-04-10 00:05:50 -0700187 public View getHeadsUpChild() {
188 return mHeadsUpChild;
189 }
190
Jorim Jaggibe565df2014-04-28 17:51:23 +0200191 public void setContractedChild(View child) {
192 if (mContractedChild != null) {
Jorim Jaggi0d9f35d2014-08-20 17:06:55 +0200193 mContractedChild.animate().cancel();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200194 removeView(mContractedChild);
195 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200196 addView(child);
197 mContractedChild = child;
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100198 mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child);
Jorim Jaggi11298832014-05-24 16:18:38 +0200199 selectLayout(false /* animate */, true /* force */);
Jorim Jaggi10ad7612014-12-08 18:41:11 +0100200 mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */);
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700201 updateRoundRectClipping();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200202 }
203
204 public void setExpandedChild(View child) {
205 if (mExpandedChild != null) {
Jorim Jaggi0d9f35d2014-08-20 17:06:55 +0200206 mExpandedChild.animate().cancel();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200207 removeView(mExpandedChild);
208 }
209 addView(child);
210 mExpandedChild = child;
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700211 mExpandedWrapper = NotificationViewWrapper.wrap(getContext(), child);
Jorim Jaggi11298832014-05-24 16:18:38 +0200212 selectLayout(false /* animate */, true /* force */);
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700213 updateRoundRectClipping();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200214 }
215
Selim Cinek8d490d42015-04-10 00:05:50 -0700216 public void setHeadsUpChild(View child) {
217 if (mHeadsUpChild != null) {
218 mHeadsUpChild.animate().cancel();
219 removeView(mHeadsUpChild);
220 }
221 addView(child);
222 mHeadsUpChild = child;
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700223 mHeadsUpWrapper = NotificationViewWrapper.wrap(getContext(), child);
Selim Cinek8d490d42015-04-10 00:05:50 -0700224 selectLayout(false /* animate */, true /* force */);
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700225 updateRoundRectClipping();
Selim Cinek8d490d42015-04-10 00:05:50 -0700226 }
227
Selim Cinekbb3d1cf2014-10-31 00:12:56 +0100228 @Override
229 protected void onVisibilityChanged(View changedView, int visibility) {
230 super.onVisibilityChanged(changedView, visibility);
231 updateVisibility();
232 }
233
234 private void updateVisibility() {
235 setVisible(isShown());
236 }
237
238 private void setVisible(final boolean isVisible) {
239 if (isVisible) {
240
241 // We only animate if we are drawn at least once, otherwise the view might animate when
242 // it's shown the first time
243 getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener);
244 } else {
245 getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
246 mAnimate = false;
247 }
248 }
249
Selim Cinekb5605e52015-02-20 18:21:41 +0100250 public void setContentHeight(int contentHeight) {
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700251 mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());;
252 mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
Selim Cinekbb3d1cf2014-10-31 00:12:56 +0100253 selectLayout(mAnimate /* animate */, false /* force */);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200254 updateClipping();
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700255 invalidateOutline();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200256 }
257
Selim Cinekb5605e52015-02-20 18:21:41 +0100258 public int getContentHeight() {
259 return mContentHeight;
260 }
261
Jorim Jaggibe565df2014-04-28 17:51:23 +0200262 public int getMaxHeight() {
Selim Cinek8d490d42015-04-10 00:05:50 -0700263 if (mIsHeadsUp && mHeadsUpChild != null) {
264 return mHeadsUpChild.getHeight();
265 } else if (mExpandedChild != null) {
266 return mExpandedChild.getHeight();
267 }
268 return mSmallHeight;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200269 }
270
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200271 public int getMinHeight() {
272 return mSmallHeight;
273 }
274
Jorim Jaggibe565df2014-04-28 17:51:23 +0200275 public void setClipTopAmount(int clipTopAmount) {
Selim Cinekc9c00ae2014-05-20 03:33:40 +0200276 mClipTopAmount = clipTopAmount;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200277 updateClipping();
278 }
279
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700280 private void updateRoundRectClipping() {
281 boolean enabled = needsRoundRectClipping();
282 setClipToOutline(enabled);
283 }
284
285 private boolean needsRoundRectClipping() {
286 if (!mRoundRectClippingEnabled) {
287 return false;
288 }
289 boolean needsForContracted = mContractedChild != null
290 && mContractedChild.getVisibility() == View.VISIBLE
291 && mContractedWrapper.needsRoundRectClipping();
292 boolean needsForExpanded = mExpandedChild != null
293 && mExpandedChild.getVisibility() == View.VISIBLE
294 && mExpandedWrapper.needsRoundRectClipping();
295 boolean needsForHeadsUp = mExpandedChild != null
296 && mExpandedChild.getVisibility() == View.VISIBLE
297 && mExpandedWrapper.needsRoundRectClipping();
298 return needsForContracted || needsForExpanded || needsForHeadsUp;
299 }
300
Jorim Jaggibe565df2014-04-28 17:51:23 +0200301 private void updateClipping() {
Selim Cinekb5605e52015-02-20 18:21:41 +0100302 mClipBounds.set(0, mClipTopAmount, getWidth(), mContentHeight);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200303 setClipBounds(mClipBounds);
304 }
305
Jorim Jaggi11298832014-05-24 16:18:38 +0200306 private void selectLayout(boolean animate, boolean force) {
307 if (mContractedChild == null) {
308 return;
309 }
Selim Cinek684a4422015-04-15 16:18:39 -0700310 int visibleType = calculateVisibleType();
311 if (visibleType != mVisibleType || force) {
312 if (animate && (visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
313 || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
314 || visibleType == VISIBLE_TYPE_CONTRACTED) {
315 runSwitchAnimation(visibleType);
Selim Cinek8d490d42015-04-10 00:05:50 -0700316 } else {
Selim Cinek684a4422015-04-15 16:18:39 -0700317 updateViewVisibilities(visibleType);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200318 }
Selim Cinek684a4422015-04-15 16:18:39 -0700319 mVisibleType = visibleType;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200320 }
Jorim Jaggi11298832014-05-24 16:18:38 +0200321 }
322
Selim Cinek684a4422015-04-15 16:18:39 -0700323 private void updateViewVisibilities(int visibleType) {
324 boolean contractedVisible = visibleType == VISIBLE_TYPE_CONTRACTED;
Selim Cinek8d490d42015-04-10 00:05:50 -0700325 mContractedChild.setVisibility(contractedVisible ? View.VISIBLE : View.INVISIBLE);
326 mContractedChild.setAlpha(contractedVisible ? 1f : 0f);
327 mContractedChild.setLayerType(LAYER_TYPE_NONE, null);
328 if (mExpandedChild != null) {
Selim Cinek684a4422015-04-15 16:18:39 -0700329 boolean expandedVisible = visibleType == VISIBLE_TYPE_EXPANDED;
Selim Cinek8d490d42015-04-10 00:05:50 -0700330 mExpandedChild.setVisibility(expandedVisible ? View.VISIBLE : View.INVISIBLE);
331 mExpandedChild.setAlpha(expandedVisible ? 1f : 0f);
332 mExpandedChild.setLayerType(LAYER_TYPE_NONE, null);
333 }
334 if (mHeadsUpChild != null) {
Selim Cinek684a4422015-04-15 16:18:39 -0700335 boolean headsUpVisible = visibleType == VISIBLE_TYPE_HEADSUP;
Selim Cinek8d490d42015-04-10 00:05:50 -0700336 mHeadsUpChild.setVisibility(headsUpVisible ? View.VISIBLE : View.INVISIBLE);
337 mHeadsUpChild.setAlpha(headsUpVisible ? 1f : 0f);
338 mHeadsUpChild.setLayerType(LAYER_TYPE_NONE, null);
339 }
340 setLayerType(LAYER_TYPE_NONE, null);
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700341 updateRoundRectClipping();
Selim Cinek8d490d42015-04-10 00:05:50 -0700342 }
343
Selim Cinek684a4422015-04-15 16:18:39 -0700344 private void runSwitchAnimation(int visibleType) {
345 View shownView = getViewForVisibleType(visibleType);
346 View hiddenView = getViewForVisibleType(mVisibleType);
Selim Cinek8d490d42015-04-10 00:05:50 -0700347 shownView.setVisibility(View.VISIBLE);
348 hiddenView.setVisibility(View.VISIBLE);
349 shownView.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
350 hiddenView.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
Jorim Jaggi11298832014-05-24 16:18:38 +0200351 setLayerType(LAYER_TYPE_HARDWARE, null);
Selim Cinek8d490d42015-04-10 00:05:50 -0700352 hiddenView.animate()
353 .alpha(0f)
Jorim Jaggi11298832014-05-24 16:18:38 +0200354 .setDuration(ANIMATION_DURATION_LENGTH)
Selim Cinek8d490d42015-04-10 00:05:50 -0700355 .setInterpolator(mLinearInterpolator)
356 .withEndAction(null); // In case we have multiple changes in one frame.
357 shownView.animate()
358 .alpha(1f)
Jorim Jaggi11298832014-05-24 16:18:38 +0200359 .setDuration(ANIMATION_DURATION_LENGTH)
360 .setInterpolator(mLinearInterpolator)
361 .withEndAction(new Runnable() {
362 @Override
363 public void run() {
Selim Cinek684a4422015-04-15 16:18:39 -0700364 updateViewVisibilities(mVisibleType);
Jorim Jaggi11298832014-05-24 16:18:38 +0200365 }
366 });
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700367 updateRoundRectClipping();
Jorim Jaggi11298832014-05-24 16:18:38 +0200368 }
369
Selim Cinek684a4422015-04-15 16:18:39 -0700370 /**
371 * @param visibleType one of the static enum types in this view
372 * @return the corresponding view according to the given visible type
373 */
374 private View getViewForVisibleType(int visibleType) {
375 switch (visibleType) {
376 case VISIBLE_TYPE_EXPANDED:
Selim Cinek8d490d42015-04-10 00:05:50 -0700377 return mExpandedChild;
Selim Cinek684a4422015-04-15 16:18:39 -0700378 case VISIBLE_TYPE_HEADSUP:
Selim Cinek8d490d42015-04-10 00:05:50 -0700379 return mHeadsUpChild;
Selim Cinek684a4422015-04-15 16:18:39 -0700380 default:
381 return mContractedChild;
Selim Cinek8d490d42015-04-10 00:05:50 -0700382 }
Selim Cinek8d490d42015-04-10 00:05:50 -0700383 }
384
Selim Cinek684a4422015-04-15 16:18:39 -0700385 /**
386 * @return one of the static enum types in this view, calculated form the current state
387 */
388 private int calculateVisibleType() {
Selim Cinek8d490d42015-04-10 00:05:50 -0700389 boolean noExpandedChild = mExpandedChild == null;
Selim Cinek1f3f5442015-04-10 17:54:46 -0700390 if (mIsHeadsUp && mHeadsUpChild != null) {
391 if (mContentHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
Selim Cinek684a4422015-04-15 16:18:39 -0700392 return VISIBLE_TYPE_HEADSUP;
Selim Cinek8d490d42015-04-10 00:05:50 -0700393 } else {
Selim Cinek684a4422015-04-15 16:18:39 -0700394 return VISIBLE_TYPE_EXPANDED;
Selim Cinek8d490d42015-04-10 00:05:50 -0700395 }
396 } else {
397 if (mContentHeight <= mSmallHeight || noExpandedChild) {
Selim Cinek684a4422015-04-15 16:18:39 -0700398 return VISIBLE_TYPE_CONTRACTED;
Selim Cinek8d490d42015-04-10 00:05:50 -0700399 } else {
Selim Cinek684a4422015-04-15 16:18:39 -0700400 return VISIBLE_TYPE_EXPANDED;
Selim Cinek8d490d42015-04-10 00:05:50 -0700401 }
402 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200403 }
404
405 public void notifyContentUpdated() {
Jorim Jaggi11298832014-05-24 16:18:38 +0200406 selectLayout(false /* animate */, true /* force */);
Jorim Jaggi394a5d62014-11-26 23:07:13 +0100407 if (mContractedChild != null) {
Jorim Jaggidacc9242014-12-08 19:21:26 +0100408 mContractedWrapper.notifyContentUpdated();
Jorim Jaggi394a5d62014-11-26 23:07:13 +0100409 mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */);
410 }
Jorim Jaggibe4116a2015-05-20 20:04:08 -0700411 if (mExpandedChild != null) {
412 mExpandedWrapper.notifyContentUpdated();
413 }
414 updateRoundRectClipping();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200415 }
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200416
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200417 public boolean isContentExpandable() {
418 return mExpandedChild != null;
419 }
John Spurlocke15452b2014-08-21 09:44:39 -0400420
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100421 public void setDark(boolean dark, boolean fade, long delay) {
John Spurlockc3dfd322014-08-27 14:55:54 -0400422 if (mDark == dark || mContractedChild == null) return;
John Spurlocke15452b2014-08-21 09:44:39 -0400423 mDark = dark;
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100424 mContractedWrapper.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400425 }
426
Selim Cinek8d490d42015-04-10 00:05:50 -0700427 public void setHeadsUp(boolean headsUp) {
428 mIsHeadsUp = headsUp;
429 selectLayout(false /* animate */, true /* force */);
430 }
431
Jorim Jaggiaa92ffb2014-09-10 23:29:28 +0200432 @Override
433 public boolean hasOverlappingRendering() {
434
435 // This is not really true, but good enough when fading from the contracted to the expanded
436 // layout, and saves us some layers.
437 return false;
438 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200439}