blob: 315c5092922c8446e8018f1543670f870c10942b [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
Jorim Jaggife40f7d2014-04-28 15:20:04 +02002 * Copyright (C) 2014 The Android Open Source Project
Kenny Root15a4d2f2010-03-11 18:20:12 -08003 *
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
Jorim Jaggife40f7d2014-04-28 15:20:04 +020014 * limitations under the License
Kenny Root15a4d2f2010-03-11 18:20:12 -080015 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016
Joe Onorato79de0c52010-05-26 17:03:26 -040017package com.android.systemui.statusbar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Jorim Jaggi4222d9a2014-04-23 16:13:15 +020019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.ObjectAnimator;
Selim Cinekd35c2792016-01-21 13:20:57 -080022import android.animation.TimeAnimator;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020023import android.animation.ValueAnimator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.Context;
Selim Cinek8efa6dd2014-05-19 16:27:37 +020025import android.graphics.Canvas;
Selim Cinek8efa6dd2014-05-19 16:27:37 +020026import android.graphics.RectF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.util.AttributeSet;
Jorim Jaggi251957d2014-04-09 04:24:09 +020028import android.view.MotionEvent;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070029import android.view.View;
ztenghui62f30e02014-06-05 09:55:04 -070030import android.view.ViewAnimationUtils;
Jorim Jaggi251957d2014-04-09 04:24:09 +020031import android.view.ViewConfiguration;
Jorim Jaggi4222d9a2014-04-23 16:13:15 +020032import android.view.animation.Interpolator;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020033import android.view.animation.PathInterpolator;
ztenghui62f30e02014-06-05 09:55:04 -070034
Winsonc0d70582016-01-29 10:24:39 -080035import com.android.systemui.Interpolators;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020036import com.android.systemui.R;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070037import com.android.systemui.classifier.FalsingManager;
Selim Cinekd35c2792016-01-21 13:20:57 -080038import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Jorim Jaggi46739852014-04-15 09:58:24 +020039
Jorim Jaggife40f7d2014-04-28 15:20:04 +020040/**
41 * Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
42 * to implement dimming/activating on Keyguard for the double-tap gesture
43 */
Jorim Jaggibe565df2014-04-28 17:51:23 +020044public abstract class ActivatableNotificationView extends ExpandableOutlineView {
Jorim Jaggi251957d2014-04-09 04:24:09 +020045
Jorim Jaggia8b48e12014-05-19 20:26:46 +020046 private static final long DOUBLETAP_TIMEOUT_MS = 1200;
Jorim Jaggid552d9d2014-05-07 19:41:13 +020047 private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020048 private static final int ACTIVATE_ANIMATION_LENGTH = 220;
Jorim Jaggi4e857f42014-11-17 19:14:04 +010049 private static final int DARK_ANIMATION_LENGTH = 170;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020050
Selim Cinek8efa6dd2014-05-19 16:27:37 +020051 /**
52 * The amount of width, which is kept in the end when performing a disappear animation (also
53 * the amount from which the horizontal appearing begins)
54 */
55 private static final float HORIZONTAL_COLLAPSED_REST_PARTIAL = 0.05f;
56
57 /**
58 * At which point from [0,1] does the horizontal collapse animation end (or start when
59 * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
60 */
61 private static final float HORIZONTAL_ANIMATION_END = 0.2f;
62
63 /**
64 * At which point from [0,1] does the alpha animation end (or start when
65 * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
66 */
67 private static final float ALPHA_ANIMATION_END = 0.0f;
68
69 /**
70 * At which point from [0,1] does the horizontal collapse animation start (or start when
71 * expanding)? 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
72 */
73 private static final float HORIZONTAL_ANIMATION_START = 1.0f;
74
75 /**
76 * At which point from [0,1] does the vertical collapse animation start (or end when
77 * expanding) 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
78 */
79 private static final float VERTICAL_ANIMATION_START = 1.0f;
80
Jorim Jaggi4e857f42014-11-17 19:14:04 +010081 /**
82 * Scale for the background to animate from when exiting dark mode.
83 */
84 private static final float DARK_EXIT_SCALE_START = 0.93f;
85
Jorim Jaggia8b48e12014-05-19 20:26:46 +020086 private static final Interpolator ACTIVATE_INVERSE_INTERPOLATOR
87 = new PathInterpolator(0.6f, 0, 0.5f, 1);
88 private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
89 = new PathInterpolator(0, 0, 0.5f, 1);
Selim Cinekb2da91b2014-09-02 17:35:20 +020090 private final int mTintedRippleColor;
91 private final int mLowPriorityRippleColor;
Selim Cinekb5605e52015-02-20 18:21:41 +010092 protected final int mNormalRippleColor;
Jorim Jaggi251957d2014-04-09 04:24:09 +020093
94 private boolean mDimmed;
John Spurlockbf370992014-06-17 13:58:31 -040095 private boolean mDark;
Jorim Jaggi251957d2014-04-09 04:24:09 +020096
Dan Sandlerfe266a32014-05-15 22:28:06 -040097 private int mBgTint = 0;
Dan Sandlerfe266a32014-05-15 22:28:06 -040098
Jorim Jaggi251957d2014-04-09 04:24:09 +020099 /**
100 * Flag to indicate that the notification has been touched once and the second touch will
101 * click it.
102 */
103 private boolean mActivated;
104
105 private float mDownX;
106 private float mDownY;
107 private final float mTouchSlop;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200108
109 private OnActivatedListener mOnActivatedListener;
Jorim Jaggi251957d2014-04-09 04:24:09 +0200110
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200111 private final Interpolator mSlowOutFastInInterpolator;
112 private final Interpolator mSlowOutLinearInInterpolator;
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200113 private Interpolator mCurrentAppearInterpolator;
114 private Interpolator mCurrentAlphaInterpolator;
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200115
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200116 private NotificationBackgroundView mBackgroundNormal;
117 private NotificationBackgroundView mBackgroundDimmed;
118 private ObjectAnimator mBackgroundAnimator;
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200119 private RectF mAppearAnimationRect = new RectF();
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200120 private float mAnimationTranslationY;
121 private boolean mDrawingAppearAnimation;
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200122 private ValueAnimator mAppearAnimator;
123 private float mAppearAnimationFraction = -1.0f;
124 private float mAppearAnimationTranslation;
Selim Cinek697178b2014-07-02 19:40:30 +0200125 private boolean mShowingLegacyBackground;
126 private final int mLegacyColor;
127 private final int mNormalColor;
Selim Cinek3d2b94bf2014-07-02 22:12:47 +0200128 private final int mLowPriorityColor;
129 private boolean mIsBelowSpeedBump;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700130 private FalsingManager mFalsingManager;
Selim Cinek570981d2015-12-01 11:37:01 -0800131 private boolean mTrackTouch;
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200132
Selim Cinekd35c2792016-01-21 13:20:57 -0800133 private float mNormalBackgroundVisibilityAmount;
134 private ValueAnimator mFadeInFromDarkAnimator;
135 private ValueAnimator.AnimatorUpdateListener mBackgroundVisibilityUpdater
136 = new ValueAnimator.AnimatorUpdateListener() {
137 @Override
138 public void onAnimationUpdate(ValueAnimator animation) {
139 setNormalBackgroundVisibilityAmount(mBackgroundNormal.getAlpha());
140 }
141 };
142 private AnimatorListenerAdapter mFadeInEndListener = new AnimatorListenerAdapter() {
143 @Override
144 public void onAnimationEnd(Animator animation) {
145 super.onAnimationEnd(animation);
146 mFadeInFromDarkAnimator = null;
147 updateOutlineAlpha();
148 }
149 };
150 private ValueAnimator.AnimatorUpdateListener mUpdateOutlineListener
151 = new ValueAnimator.AnimatorUpdateListener() {
152 @Override
153 public void onAnimationUpdate(ValueAnimator animation) {
154 updateOutlineAlpha();
155 }
156 };
Selim Cinek277a8aa2016-01-22 12:12:37 -0800157 private float mShadowAlpha = 1.0f;
Selim Cinekd35c2792016-01-21 13:20:57 -0800158
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200159 public ActivatableNotificationView(Context context, AttributeSet attrs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 super(context, attrs);
Jorim Jaggi251957d2014-04-09 04:24:09 +0200161 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200162 mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200163 mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200164 setClipChildren(false);
165 setClipToPadding(false);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700166 mLegacyColor = context.getColor(R.color.notification_legacy_background_color);
167 mNormalColor = context.getColor(R.color.notification_material_background_color);
168 mLowPriorityColor = context.getColor(
Selim Cinek3d2b94bf2014-07-02 22:12:47 +0200169 R.color.notification_material_background_low_priority_color);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700170 mTintedRippleColor = context.getColor(
Selim Cinekb2da91b2014-09-02 17:35:20 +0200171 R.color.notification_ripple_tinted_color);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700172 mLowPriorityRippleColor = context.getColor(
Selim Cinekb2da91b2014-09-02 17:35:20 +0200173 R.color.notification_ripple_color_low_priority);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700174 mNormalRippleColor = context.getColor(
Selim Cinekb2da91b2014-09-02 17:35:20 +0200175 R.color.notification_ripple_untinted_color);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700176 mFalsingManager = FalsingManager.getInstance(context);
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200177 }
178
179 @Override
180 protected void onFinishInflate() {
181 super.onFinishInflate();
182 mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
183 mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
Selim Cinek697178b2014-07-02 19:40:30 +0200184 mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
185 mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
Adrian Roosbcbb75a2014-05-27 16:38:11 +0200186 updateBackground();
Selim Cinek697178b2014-07-02 19:40:30 +0200187 updateBackgroundTint();
Selim Cinekd35c2792016-01-21 13:20:57 -0800188 updateOutlineAlpha();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 }
190
Jorim Jaggi251957d2014-04-09 04:24:09 +0200191 private final Runnable mTapTimeoutRunnable = new Runnable() {
192 @Override
193 public void run() {
Selim Cineka32ab602014-06-11 15:06:01 +0200194 makeInactive(true /* animate */);
Jorim Jaggi251957d2014-04-09 04:24:09 +0200195 }
196 };
197
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700198 @Override
Selim Cinek6183d122016-01-14 18:48:41 -0800199 public boolean onInterceptTouchEvent(MotionEvent ev) {
200 if (mDimmed && !mActivated
201 && ev.getActionMasked() == MotionEvent.ACTION_DOWN && disallowSingleClick(ev)) {
202 return true;
Jorim Jaggi251957d2014-04-09 04:24:09 +0200203 }
Selim Cinek6183d122016-01-14 18:48:41 -0800204 return super.onInterceptTouchEvent(ev);
205 }
206
207 protected boolean disallowSingleClick(MotionEvent ev) {
208 return false;
Jorim Jaggi251957d2014-04-09 04:24:09 +0200209 }
210
Mady Mellorf0625802016-02-11 18:03:48 -0800211 protected boolean handleSlideBack() {
212 return false;
213 }
214
Selim Cinek697178b2014-07-02 19:40:30 +0200215 @Override
Selim Cinek570981d2015-12-01 11:37:01 -0800216 public boolean onTouchEvent(MotionEvent event) {
217 boolean result;
Selim Cinek6183d122016-01-14 18:48:41 -0800218 if (mDimmed) {
219 boolean wasActivated = mActivated;
Selim Cinek570981d2015-12-01 11:37:01 -0800220 result = handleTouchEventDimmed(event);
Selim Cinek6183d122016-01-14 18:48:41 -0800221 if (wasActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
222 mFalsingManager.onNotificationDoubleTap();
223 removeCallbacks(mTapTimeoutRunnable);
224 }
Selim Cinek570981d2015-12-01 11:37:01 -0800225 } else {
226 result = super.onTouchEvent(event);
227 }
Selim Cinek570981d2015-12-01 11:37:01 -0800228 return result;
229 }
230
231 @Override
Selim Cinek697178b2014-07-02 19:40:30 +0200232 public void drawableHotspotChanged(float x, float y) {
233 if (!mDimmed){
234 mBackgroundNormal.drawableHotspotChanged(x, y);
235 }
236 }
237
Selim Cinekb2da91b2014-09-02 17:35:20 +0200238 @Override
239 protected void drawableStateChanged() {
240 super.drawableStateChanged();
241 if (mDimmed) {
242 mBackgroundDimmed.setState(getDrawableState());
243 } else {
244 mBackgroundNormal.setState(getDrawableState());
245 }
246 }
247
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200248 private boolean handleTouchEventDimmed(MotionEvent event) {
Jorim Jaggi251957d2014-04-09 04:24:09 +0200249 int action = event.getActionMasked();
Jorim Jaggi251957d2014-04-09 04:24:09 +0200250 switch (action) {
251 case MotionEvent.ACTION_DOWN:
252 mDownX = event.getX();
253 mDownY = event.getY();
Selim Cinek570981d2015-12-01 11:37:01 -0800254 mTrackTouch = true;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200255 if (mDownY > getActualHeight()) {
Selim Cinek570981d2015-12-01 11:37:01 -0800256 mTrackTouch = false;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200257 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200258 break;
259 case MotionEvent.ACTION_MOVE:
260 if (!isWithinTouchSlop(event)) {
Selim Cineka32ab602014-06-11 15:06:01 +0200261 makeInactive(true /* animate */);
Selim Cinek570981d2015-12-01 11:37:01 -0800262 mTrackTouch = false;
Jorim Jaggi251957d2014-04-09 04:24:09 +0200263 }
264 break;
265 case MotionEvent.ACTION_UP:
266 if (isWithinTouchSlop(event)) {
Mady Mellorf0625802016-02-11 18:03:48 -0800267 if (handleSlideBack()) {
268 return true;
269 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200270 if (!mActivated) {
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200271 makeActive();
Jorim Jaggi251957d2014-04-09 04:24:09 +0200272 postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
273 } else {
Selim Cinek570981d2015-12-01 11:37:01 -0800274 if (!performClick()) {
275 return false;
Selim Cineka32ab602014-06-11 15:06:01 +0200276 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200277 }
278 } else {
Selim Cineka32ab602014-06-11 15:06:01 +0200279 makeInactive(true /* animate */);
Selim Cinek570981d2015-12-01 11:37:01 -0800280 mTrackTouch = false;
Jorim Jaggi251957d2014-04-09 04:24:09 +0200281 }
282 break;
283 case MotionEvent.ACTION_CANCEL:
Selim Cineka32ab602014-06-11 15:06:01 +0200284 makeInactive(true /* animate */);
Selim Cinek570981d2015-12-01 11:37:01 -0800285 mTrackTouch = false;
Jorim Jaggi251957d2014-04-09 04:24:09 +0200286 break;
287 default:
288 break;
289 }
Selim Cinek570981d2015-12-01 11:37:01 -0800290 return mTrackTouch;
Jorim Jaggi251957d2014-04-09 04:24:09 +0200291 }
292
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200293 private void makeActive() {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700294 mFalsingManager.onNotificationActive();
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200295 startActivateAnimation(false /* reverse */);
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200296 mActivated = true;
Jorim Jaggiecbab362014-04-23 16:13:15 +0200297 if (mOnActivatedListener != null) {
298 mOnActivatedListener.onActivated(this);
299 }
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200300 }
301
Selim Cinekd35c2792016-01-21 13:20:57 -0800302 private void startActivateAnimation(final boolean reverse) {
Selim Cinekf4d7fc32014-09-26 17:15:34 +0200303 if (!isAttachedToWindow()) {
304 return;
305 }
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200306 int widthHalf = mBackgroundNormal.getWidth()/2;
307 int heightHalf = mBackgroundNormal.getActualHeight()/2;
308 float radius = (float) Math.sqrt(widthHalf*widthHalf + heightHalf*heightHalf);
Selim Cinek6aaf2172014-08-25 19:29:49 +0200309 Animator animator;
310 if (reverse) {
311 animator = ViewAnimationUtils.createCircularReveal(mBackgroundNormal,
312 widthHalf, heightHalf, radius, 0);
313 } else {
314 animator = ViewAnimationUtils.createCircularReveal(mBackgroundNormal,
315 widthHalf, heightHalf, 0, radius);
316 }
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200317 mBackgroundNormal.setVisibility(View.VISIBLE);
318 Interpolator interpolator;
319 Interpolator alphaInterpolator;
320 if (!reverse) {
Selim Cinekc18010f2016-01-20 13:41:30 -0800321 interpolator = Interpolators.LINEAR_OUT_SLOW_IN;
322 alphaInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200323 } else {
324 interpolator = ACTIVATE_INVERSE_INTERPOLATOR;
325 alphaInterpolator = ACTIVATE_INVERSE_ALPHA_INTERPOLATOR;
326 }
327 animator.setInterpolator(interpolator);
328 animator.setDuration(ACTIVATE_ANIMATION_LENGTH);
329 if (reverse) {
330 mBackgroundNormal.setAlpha(1f);
331 animator.addListener(new AnimatorListenerAdapter() {
332 @Override
333 public void onAnimationEnd(Animator animation) {
Selim Cinek23e6acb2014-08-12 16:01:41 +0200334 if (mDimmed) {
335 mBackgroundNormal.setVisibility(View.INVISIBLE);
336 }
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200337 }
338 });
Selim Cinek6aaf2172014-08-25 19:29:49 +0200339 animator.start();
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200340 } else {
341 mBackgroundNormal.setAlpha(0.4f);
342 animator.start();
343 }
344 mBackgroundNormal.animate()
345 .alpha(reverse ? 0f : 1f)
346 .setInterpolator(alphaInterpolator)
Selim Cinekd35c2792016-01-21 13:20:57 -0800347 .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
348 @Override
349 public void onAnimationUpdate(ValueAnimator animation) {
350 float animatedFraction = animation.getAnimatedFraction();
351 if (reverse) {
352 animatedFraction = 1.0f - animatedFraction;
353 }
354 setNormalBackgroundVisibilityAmount(animatedFraction);
355 }
356 })
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200357 .setDuration(ACTIVATE_ANIMATION_LENGTH);
358 }
359
Jorim Jaggi251957d2014-04-09 04:24:09 +0200360 /**
361 * Cancels the hotspot and makes the notification inactive.
362 */
Selim Cineka32ab602014-06-11 15:06:01 +0200363 public void makeInactive(boolean animate) {
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200364 if (mActivated) {
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200365 if (mDimmed) {
Selim Cineka32ab602014-06-11 15:06:01 +0200366 if (animate) {
367 startActivateAnimation(true /* reverse */);
368 } else {
369 mBackgroundNormal.setVisibility(View.INVISIBLE);
370 }
Jorim Jaggibccb9122014-05-08 14:55:48 +0200371 }
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200372 mActivated = false;
Jorim Jaggi251957d2014-04-09 04:24:09 +0200373 }
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200374 if (mOnActivatedListener != null) {
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200375 mOnActivatedListener.onActivationReset(this);
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200376 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200377 removeCallbacks(mTapTimeoutRunnable);
378 }
379
380 private boolean isWithinTouchSlop(MotionEvent event) {
381 return Math.abs(event.getX() - mDownX) < mTouchSlop
382 && Math.abs(event.getY() - mDownY) < mTouchSlop;
383 }
384
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200385 public void setDimmed(boolean dimmed, boolean fade) {
Jorim Jaggi251957d2014-04-09 04:24:09 +0200386 if (mDimmed != dimmed) {
387 mDimmed = dimmed;
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200388 if (fade) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100389 fadeDimmedBackground();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200390 } else {
Jorim Jaggi3c3c3fc2014-05-20 23:16:42 +0200391 updateBackground();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200392 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200393 }
394 }
395
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100396 public void setDark(boolean dark, boolean fade, long delay) {
397 super.setDark(dark, fade, delay);
398 if (mDark == dark) {
399 return;
John Spurlockbf370992014-06-17 13:58:31 -0400400 }
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100401 mDark = dark;
Selim Cinek34d93b02015-10-22 12:30:38 -0700402 if (!dark && fade && !shouldHideBackground()) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100403 if (mActivated) {
404 mBackgroundDimmed.setVisibility(View.VISIBLE);
405 mBackgroundNormal.setVisibility(View.VISIBLE);
Selim Cinekc430a5b2014-12-10 16:29:01 +0100406 } else if (mDimmed) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100407 mBackgroundDimmed.setVisibility(View.VISIBLE);
408 mBackgroundNormal.setVisibility(View.INVISIBLE);
Selim Cinekc430a5b2014-12-10 16:29:01 +0100409 } else {
410 mBackgroundDimmed.setVisibility(View.INVISIBLE);
411 mBackgroundNormal.setVisibility(View.VISIBLE);
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100412 }
Selim Cinekc430a5b2014-12-10 16:29:01 +0100413 fadeInFromDark(delay);
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100414 } else {
415 updateBackground();
416 }
Selim Cinekd35c2792016-01-21 13:20:57 -0800417 updateOutlineAlpha();
418 }
419
420 private void updateOutlineAlpha() {
421 if (mDark) {
422 setOutlineAlpha(0f);
423 return;
424 }
425 float alpha = NotificationStackScrollLayout.BACKGROUND_ALPHA_DIMMED;
426 alpha = (alpha + (1.0f - alpha) * mNormalBackgroundVisibilityAmount);
Selim Cinek277a8aa2016-01-22 12:12:37 -0800427 alpha *= mShadowAlpha;
Selim Cinekd35c2792016-01-21 13:20:57 -0800428 if (mFadeInFromDarkAnimator != null) {
429 alpha *= mFadeInFromDarkAnimator.getAnimatedFraction();
430 }
431 setOutlineAlpha(alpha);
432 }
433
434 public void setNormalBackgroundVisibilityAmount(float normalBackgroundVisibilityAmount) {
435 mNormalBackgroundVisibilityAmount = normalBackgroundVisibilityAmount;
436 updateOutlineAlpha();
437 }
John Spurlockbf370992014-06-17 13:58:31 -0400438
Selim Cinek697178b2014-07-02 19:40:30 +0200439 public void setShowingLegacyBackground(boolean showing) {
440 mShowingLegacyBackground = showing;
441 updateBackgroundTint();
Jorim Jaggi46739852014-04-15 09:58:24 +0200442 }
443
Selim Cinek3d2b94bf2014-07-02 22:12:47 +0200444 @Override
445 public void setBelowSpeedBump(boolean below) {
446 super.setBelowSpeedBump(below);
447 if (below != mIsBelowSpeedBump) {
448 mIsBelowSpeedBump = below;
449 updateBackgroundTint();
450 }
451 }
452
Selim Cinek697178b2014-07-02 19:40:30 +0200453 /**
454 * Sets the tint color of the background
455 */
456 public void setTintColor(int color) {
457 mBgTint = color;
458 updateBackgroundTint();
459 }
460
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700461 protected void updateBackgroundTint() {
Chet Haase5058c382015-01-06 06:29:35 -0800462 int color = getBgColor();
Selim Cinekb2da91b2014-09-02 17:35:20 +0200463 int rippleColor = getRippleColor();
Selim Cinek697178b2014-07-02 19:40:30 +0200464 if (color == mNormalColor) {
465 // We don't need to tint a normal notification
466 color = 0;
467 }
468 mBackgroundDimmed.setTint(color);
469 mBackgroundNormal.setTint(color);
Selim Cinekb2da91b2014-09-02 17:35:20 +0200470 mBackgroundDimmed.setRippleColor(rippleColor);
471 mBackgroundNormal.setRippleColor(rippleColor);
Dan Sandlerfe266a32014-05-15 22:28:06 -0400472 }
473
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100474 /**
Selim Cinekc430a5b2014-12-10 16:29:01 +0100475 * Fades in the background when exiting dark mode.
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100476 */
Selim Cinekc430a5b2014-12-10 16:29:01 +0100477 private void fadeInFromDark(long delay) {
478 final View background = mDimmed ? mBackgroundDimmed : mBackgroundNormal;
479 background.setAlpha(0f);
480 background.setPivotX(mBackgroundDimmed.getWidth() / 2f);
481 background.setPivotY(getActualHeight() / 2f);
482 background.setScaleX(DARK_EXIT_SCALE_START);
483 background.setScaleY(DARK_EXIT_SCALE_START);
484 background.animate()
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100485 .alpha(1f)
486 .scaleX(1f)
487 .scaleY(1f)
488 .setDuration(DARK_ANIMATION_LENGTH)
489 .setStartDelay(delay)
Selim Cinekc18010f2016-01-20 13:41:30 -0800490 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100491 .setListener(new AnimatorListenerAdapter() {
492 @Override
493 public void onAnimationCancel(Animator animation) {
494 // Jump state if we are cancelled
Selim Cinekc430a5b2014-12-10 16:29:01 +0100495 background.setScaleX(1f);
496 background.setScaleY(1f);
497 background.setAlpha(1f);
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100498 }
499 })
Selim Cinekd35c2792016-01-21 13:20:57 -0800500 .setUpdateListener(mBackgroundVisibilityUpdater)
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100501 .start();
Selim Cinekd35c2792016-01-21 13:20:57 -0800502 mFadeInFromDarkAnimator = TimeAnimator.ofFloat(0.0f, 1.0f);
503 mFadeInFromDarkAnimator.setDuration(DARK_ANIMATION_LENGTH);
504 mFadeInFromDarkAnimator.setStartDelay(delay);
505 mFadeInFromDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
506 mFadeInFromDarkAnimator.addListener(mFadeInEndListener);
507 mFadeInFromDarkAnimator.addUpdateListener(mUpdateOutlineListener);
508 mFadeInFromDarkAnimator.start();
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100509 }
510
511 /**
512 * Fades the background when the dimmed state changes.
513 */
514 private void fadeDimmedBackground() {
515 mBackgroundDimmed.animate().cancel();
Selim Cinek59d97232014-10-09 15:54:40 -0700516 mBackgroundNormal.animate().cancel();
Selim Cinek34d93b02015-10-22 12:30:38 -0700517 if (!shouldHideBackground()) {
518 if (mDimmed) {
519 mBackgroundDimmed.setVisibility(View.VISIBLE);
520 } else {
521 mBackgroundNormal.setVisibility(View.VISIBLE);
522 }
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200523 }
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200524 float startAlpha = mDimmed ? 1f : 0;
525 float endAlpha = mDimmed ? 0 : 1f;
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200526 int duration = BACKGROUND_ANIMATION_LENGTH_MS;
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200527 // Check whether there is already a background animation running.
528 if (mBackgroundAnimator != null) {
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200529 startAlpha = (Float) mBackgroundAnimator.getAnimatedValue();
Jorim Jaggi98fb09c2014-05-01 22:40:56 +0200530 duration = (int) mBackgroundAnimator.getCurrentPlayTime();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200531 mBackgroundAnimator.removeAllListeners();
532 mBackgroundAnimator.cancel();
Jorim Jaggi98fb09c2014-05-01 22:40:56 +0200533 if (duration <= 0) {
Jorim Jaggi3c3c3fc2014-05-20 23:16:42 +0200534 updateBackground();
Jorim Jaggi98fb09c2014-05-01 22:40:56 +0200535 return;
536 }
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200537 }
538 mBackgroundNormal.setAlpha(startAlpha);
539 mBackgroundAnimator =
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200540 ObjectAnimator.ofFloat(mBackgroundNormal, View.ALPHA, startAlpha, endAlpha);
Selim Cinekc18010f2016-01-20 13:41:30 -0800541 mBackgroundAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200542 mBackgroundAnimator.setDuration(duration);
543 mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
544 @Override
545 public void onAnimationEnd(Animator animation) {
546 if (mDimmed) {
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200547 mBackgroundNormal.setVisibility(View.INVISIBLE);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200548 } else {
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200549 mBackgroundDimmed.setVisibility(View.INVISIBLE);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200550 }
551 mBackgroundAnimator = null;
552 }
553 });
Selim Cinekd35c2792016-01-21 13:20:57 -0800554 mBackgroundAnimator.addUpdateListener(mBackgroundVisibilityUpdater);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200555 mBackgroundAnimator.start();
556 }
557
Selim Cinek34d93b02015-10-22 12:30:38 -0700558 protected void updateBackground() {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100559 cancelFadeAnimations();
Selim Cinek34d93b02015-10-22 12:30:38 -0700560 if (shouldHideBackground()) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100561 mBackgroundDimmed.setVisibility(View.INVISIBLE);
562 mBackgroundNormal.setVisibility(View.INVISIBLE);
563 } else if (mDimmed) {
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200564 mBackgroundDimmed.setVisibility(View.VISIBLE);
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200565 mBackgroundNormal.setVisibility(View.INVISIBLE);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200566 } else {
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200567 mBackgroundDimmed.setVisibility(View.INVISIBLE);
568 mBackgroundNormal.setVisibility(View.VISIBLE);
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200569 mBackgroundNormal.setAlpha(1f);
Selim Cineka32ab602014-06-11 15:06:01 +0200570 removeCallbacks(mTapTimeoutRunnable);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200571 }
Selim Cinekd35c2792016-01-21 13:20:57 -0800572 setNormalBackgroundVisibilityAmount(
573 mBackgroundNormal.getVisibility() == View.VISIBLE ? 1.0f : 0.0f);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200574 }
575
Selim Cinek34d93b02015-10-22 12:30:38 -0700576 protected boolean shouldHideBackground() {
577 return mDark;
578 }
579
Selim Cinek59d97232014-10-09 15:54:40 -0700580 private void cancelFadeAnimations() {
581 if (mBackgroundAnimator != null) {
582 mBackgroundAnimator.cancel();
583 }
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100584 mBackgroundDimmed.animate().cancel();
Selim Cinek59d97232014-10-09 15:54:40 -0700585 mBackgroundNormal.animate().cancel();
586 }
587
Jorim Jaggibe565df2014-04-28 17:51:23 +0200588 @Override
589 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
590 super.onLayout(changed, left, top, right, bottom);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200591 setPivotX(getWidth() / 2);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200592 }
593
594 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200595 public void setActualHeight(int actualHeight, boolean notifyListeners) {
596 super.setActualHeight(actualHeight, notifyListeners);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200597 setPivotY(actualHeight / 2);
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200598 mBackgroundNormal.setActualHeight(actualHeight);
599 mBackgroundDimmed.setActualHeight(actualHeight);
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200600 }
601
602 @Override
603 public void setClipTopAmount(int clipTopAmount) {
604 super.setClipTopAmount(clipTopAmount);
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200605 mBackgroundNormal.setClipTopAmount(clipTopAmount);
606 mBackgroundDimmed.setClipTopAmount(clipTopAmount);
Jorim Jaggi46739852014-04-15 09:58:24 +0200607 }
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200608
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200609 @Override
Jorim Jaggi60d07c52014-07-31 15:38:21 +0200610 public void performRemoveAnimation(long duration, float translationDirection,
611 Runnable onFinishedRunnable) {
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200612 enableAppearDrawing(true);
613 if (mDrawingAppearAnimation) {
614 startAppearAnimation(false /* isAppearing */, translationDirection,
Jorim Jaggi60d07c52014-07-31 15:38:21 +0200615 0, duration, onFinishedRunnable);
Selim Cinek95ed5922014-08-28 14:30:12 +0200616 } else if (onFinishedRunnable != null) {
617 onFinishedRunnable.run();
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200618 }
619 }
620
621 @Override
Jorim Jaggi60d07c52014-07-31 15:38:21 +0200622 public void performAddAnimation(long delay, long duration) {
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200623 enableAppearDrawing(true);
624 if (mDrawingAppearAnimation) {
Jorim Jaggi60d07c52014-07-31 15:38:21 +0200625 startAppearAnimation(true /* isAppearing */, -1.0f, delay, duration, null);
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200626 }
627 }
628
Jorim Jaggi60d07c52014-07-31 15:38:21 +0200629 private void startAppearAnimation(boolean isAppearing, float translationDirection, long delay,
630 long duration, final Runnable onFinishedRunnable) {
Selim Cinek2cd45df2015-06-09 18:00:07 -0700631 cancelAppearAnimation();
Chris Wren310df312014-10-31 14:29:46 -0400632 mAnimationTranslationY = translationDirection * getActualHeight();
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200633 if (mAppearAnimationFraction == -1.0f) {
634 // not initialized yet, we start anew
635 if (isAppearing) {
636 mAppearAnimationFraction = 0.0f;
637 mAppearAnimationTranslation = mAnimationTranslationY;
638 } else {
639 mAppearAnimationFraction = 1.0f;
640 mAppearAnimationTranslation = 0;
641 }
642 }
643
644 float targetValue;
645 if (isAppearing) {
646 mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
Selim Cinekc18010f2016-01-20 13:41:30 -0800647 mCurrentAlphaInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200648 targetValue = 1.0f;
649 } else {
Selim Cinekc18010f2016-01-20 13:41:30 -0800650 mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200651 mCurrentAlphaInterpolator = mSlowOutLinearInInterpolator;
652 targetValue = 0.0f;
653 }
654 mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
655 targetValue);
Selim Cinekc18010f2016-01-20 13:41:30 -0800656 mAppearAnimator.setInterpolator(Interpolators.LINEAR);
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200657 mAppearAnimator.setDuration(
Jorim Jaggi60d07c52014-07-31 15:38:21 +0200658 (long) (duration * Math.abs(mAppearAnimationFraction - targetValue)));
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200659 mAppearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
660 @Override
661 public void onAnimationUpdate(ValueAnimator animation) {
662 mAppearAnimationFraction = (float) animation.getAnimatedValue();
663 updateAppearAnimationAlpha();
664 updateAppearRect();
665 invalidate();
666 }
667 });
668 if (delay > 0) {
669 // we need to apply the initial state already to avoid drawn frames in the wrong state
670 updateAppearAnimationAlpha();
671 updateAppearRect();
672 mAppearAnimator.setStartDelay(delay);
673 }
674 mAppearAnimator.addListener(new AnimatorListenerAdapter() {
675 private boolean mWasCancelled;
676
677 @Override
678 public void onAnimationEnd(Animator animation) {
679 if (onFinishedRunnable != null) {
680 onFinishedRunnable.run();
681 }
682 if (!mWasCancelled) {
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200683 enableAppearDrawing(false);
684 }
685 }
686
687 @Override
688 public void onAnimationStart(Animator animation) {
689 mWasCancelled = false;
690 }
691
692 @Override
693 public void onAnimationCancel(Animator animation) {
694 mWasCancelled = true;
695 }
696 });
697 mAppearAnimator.start();
698 }
699
Selim Cinek2cd45df2015-06-09 18:00:07 -0700700 private void cancelAppearAnimation() {
701 if (mAppearAnimator != null) {
702 mAppearAnimator.cancel();
Selim Cinekb65c6db2015-12-28 12:48:15 +0100703 mAppearAnimator = null;
Selim Cinek2cd45df2015-06-09 18:00:07 -0700704 }
705 }
706
707 public void cancelAppearDrawing() {
708 cancelAppearAnimation();
709 enableAppearDrawing(false);
710 }
711
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200712 private void updateAppearRect() {
713 float inverseFraction = (1.0f - mAppearAnimationFraction);
714 float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction);
715 float translateYTotalAmount = translationFraction * mAnimationTranslationY;
716 mAppearAnimationTranslation = translateYTotalAmount;
717
718 // handle width animation
719 float widthFraction = (inverseFraction - (1.0f - HORIZONTAL_ANIMATION_START))
720 / (HORIZONTAL_ANIMATION_START - HORIZONTAL_ANIMATION_END);
721 widthFraction = Math.min(1.0f, Math.max(0.0f, widthFraction));
722 widthFraction = mCurrentAppearInterpolator.getInterpolation(widthFraction);
723 float left = (getWidth() * (0.5f - HORIZONTAL_COLLAPSED_REST_PARTIAL / 2.0f) *
724 widthFraction);
725 float right = getWidth() - left;
726
727 // handle top animation
728 float heightFraction = (inverseFraction - (1.0f - VERTICAL_ANIMATION_START)) /
729 VERTICAL_ANIMATION_START;
730 heightFraction = Math.max(0.0f, heightFraction);
731 heightFraction = mCurrentAppearInterpolator.getInterpolation(heightFraction);
732
733 float top;
734 float bottom;
Chris Wren310df312014-10-31 14:29:46 -0400735 final int actualHeight = getActualHeight();
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200736 if (mAnimationTranslationY > 0.0f) {
Chris Wren310df312014-10-31 14:29:46 -0400737 bottom = actualHeight - heightFraction * mAnimationTranslationY * 0.1f
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200738 - translateYTotalAmount;
739 top = bottom * heightFraction;
740 } else {
Chris Wren310df312014-10-31 14:29:46 -0400741 top = heightFraction * (actualHeight + mAnimationTranslationY) * 0.1f -
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200742 translateYTotalAmount;
Chris Wren310df312014-10-31 14:29:46 -0400743 bottom = actualHeight * (1 - heightFraction) + top * heightFraction;
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200744 }
745 mAppearAnimationRect.set(left, top, right, bottom);
746 setOutlineRect(left, top + mAppearAnimationTranslation, right,
747 bottom + mAppearAnimationTranslation);
748 }
749
750 private void updateAppearAnimationAlpha() {
Selim Cinek560e64d2015-06-09 19:58:11 -0700751 float contentAlphaProgress = mAppearAnimationFraction;
752 contentAlphaProgress = contentAlphaProgress / (1.0f - ALPHA_ANIMATION_END);
753 contentAlphaProgress = Math.min(1.0f, contentAlphaProgress);
754 contentAlphaProgress = mCurrentAlphaInterpolator.getInterpolation(contentAlphaProgress);
755 setContentAlpha(contentAlphaProgress);
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200756 }
757
Selim Cinek560e64d2015-06-09 19:58:11 -0700758 private void setContentAlpha(float contentAlpha) {
Selim Cinek560e64d2015-06-09 19:58:11 -0700759 View contentView = getContentView();
Jorim Jaggi1f98c622015-07-20 11:43:27 -0700760 if (contentView.hasOverlappingRendering()) {
761 int layerType = contentAlpha == 0.0f || contentAlpha == 1.0f ? LAYER_TYPE_NONE
762 : LAYER_TYPE_HARDWARE;
763 int currentLayerType = contentView.getLayerType();
764 if (currentLayerType != layerType) {
765 contentView.setLayerType(layerType, null);
766 }
Selim Cinek560e64d2015-06-09 19:58:11 -0700767 }
768 contentView.setAlpha(contentAlpha);
769 }
770
771 protected abstract View getContentView();
772
Selim Cinek34d93b02015-10-22 12:30:38 -0700773 public int getBgColor() {
Selim Cinek697178b2014-07-02 19:40:30 +0200774 if (mBgTint != 0) {
775 return mBgTint;
776 } else if (mShowingLegacyBackground) {
777 return mLegacyColor;
Selim Cinek3d2b94bf2014-07-02 22:12:47 +0200778 } else if (mIsBelowSpeedBump) {
779 return mLowPriorityColor;
Selim Cinek697178b2014-07-02 19:40:30 +0200780 } else {
781 return mNormalColor;
782 }
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200783 }
784
Selim Cinekb5605e52015-02-20 18:21:41 +0100785 protected int getRippleColor() {
Selim Cinekb2da91b2014-09-02 17:35:20 +0200786 if (mBgTint != 0) {
787 return mTintedRippleColor;
788 } else if (mShowingLegacyBackground) {
789 return mTintedRippleColor;
790 } else if (mIsBelowSpeedBump) {
791 return mLowPriorityRippleColor;
792 } else {
793 return mNormalRippleColor;
794 }
795 }
796
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200797 /**
798 * When we draw the appear animation, we render the view in a bitmap and render this bitmap
799 * as a shader of a rect. This call creates the Bitmap and switches the drawing mode,
800 * such that the normal drawing of the views does not happen anymore.
801 *
802 * @param enable Should it be enabled.
803 */
804 private void enableAppearDrawing(boolean enable) {
805 if (enable != mDrawingAppearAnimation) {
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200806 mDrawingAppearAnimation = enable;
Selim Cinek560e64d2015-06-09 19:58:11 -0700807 if (!enable) {
808 setContentAlpha(1.0f);
Selim Cinekb65c6db2015-12-28 12:48:15 +0100809 mAppearAnimationFraction = -1;
810 setOutlineRect(null);
Selim Cinek560e64d2015-06-09 19:58:11 -0700811 }
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200812 invalidate();
813 }
814 }
815
816 @Override
817 protected void dispatchDraw(Canvas canvas) {
Selim Cinek560e64d2015-06-09 19:58:11 -0700818 if (mDrawingAppearAnimation) {
819 canvas.save();
820 canvas.translate(0, mAppearAnimationTranslation);
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200821 }
Selim Cinek560e64d2015-06-09 19:58:11 -0700822 super.dispatchDraw(canvas);
823 if (mDrawingAppearAnimation) {
824 canvas.restore();
825 }
Selim Cinek8efa6dd2014-05-19 16:27:37 +0200826 }
827
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200828 public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
829 mOnActivatedListener = onActivatedListener;
830 }
831
Christoph Studer22f2ee52014-07-29 22:57:21 +0200832 public void reset() {
833 setTintColor(0);
834 setShowingLegacyBackground(false);
835 setBelowSpeedBump(false);
836 }
837
Selim Cinek34d93b02015-10-22 12:30:38 -0700838 public boolean hasSameBgColor(ActivatableNotificationView otherView) {
839 return getBgColor() == otherView.getBgColor();
840 }
841
Selim Cinek277a8aa2016-01-22 12:12:37 -0800842 @Override
843 public float getShadowAlpha() {
844 return mShadowAlpha;
845 }
846
847 @Override
848 public void setShadowAlpha(float shadowAlpha) {
849 if (shadowAlpha != mShadowAlpha) {
850 mShadowAlpha = shadowAlpha;
851 updateOutlineAlpha();
852 }
853 }
854
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200855 public interface OnActivatedListener {
Selim Cineka32ab602014-06-11 15:06:01 +0200856 void onActivated(ActivatableNotificationView view);
857 void onActivationReset(ActivatableNotificationView view);
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859}