1a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek/* 2a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * Copyright (C) 2014 The Android Open Source Project 3a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * 4a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * Licensed under the Apache License, Version 2.0 (the "License"); 5a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * you may not use this file except in compliance with the License. 6a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * You may obtain a copy of the License at 7a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * 8a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * http://www.apache.org/licenses/LICENSE-2.0 9a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * 10a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * Unless required by applicable law or agreed to in writing, software 11a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * distributed under the License is distributed on an "AS IS" BASIS, 12a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * See the License for the specific language governing permissions and 14a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * limitations under the License 15a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek */ 16a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 17a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekpackage com.android.systemui.statusbar; 18a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 19a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.animation.Animator; 20a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.animation.AnimatorListenerAdapter; 21a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.animation.ValueAnimator; 22a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.content.Context; 23a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.graphics.Canvas; 24a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.graphics.Color; 256811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinekimport android.graphics.Paint; 26a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.graphics.PorterDuff; 276811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinekimport android.graphics.PorterDuffXfermode; 286811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinekimport android.graphics.Rect; 29a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.util.AttributeSet; 30a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.view.View; 31a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekimport android.view.animation.Interpolator; 32a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 33a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek/** 34a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek * A view which can draw a scrim 35a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek */ 36a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinekpublic class ScrimView extends View 37a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek{ 386811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek private final Paint mPaint = new Paint(); 39a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek private int mScrimColor; 402bc5406d7aa78a24f907e45690525e6633a78f21Jorim Jaggi private boolean mIsEmpty = true; 41a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek private boolean mDrawAsSrc; 42a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek private float mViewAlpha = 1.0f; 43a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek private ValueAnimator mAlphaAnimator; 446811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek private Rect mExcludedRect = new Rect(); 456811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek private boolean mHasExcludedArea; 46a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener 47a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek = new ValueAnimator.AnimatorUpdateListener() { 48a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek @Override 49a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public void onAnimationUpdate(ValueAnimator animation) { 50a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mViewAlpha = (float) animation.getAnimatedValue(); 51a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek invalidate(); 52a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 53a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek }; 54a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() { 55a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek @Override 56a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public void onAnimationEnd(Animator animation) { 57a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator = null; 58a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 59a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek }; 60d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek private Runnable mChangeRunnable; 61a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 62a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public ScrimView(Context context) { 63a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek this(context, null); 64a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 65a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 66a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public ScrimView(Context context, AttributeSet attrs) { 67a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek this(context, attrs, 0); 68a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 69a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 70a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public ScrimView(Context context, AttributeSet attrs, int defStyleAttr) { 71a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek this(context, attrs, defStyleAttr, 0); 72a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 73a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 74a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public ScrimView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 75a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek super(context, attrs, defStyleAttr, defStyleRes); 76a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 77a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 78a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek @Override 79a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek protected void onDraw(Canvas canvas) { 800e66439387e36876de94a60658917a7f3b0e6d27Jorim Jaggi if (mDrawAsSrc || (!mIsEmpty && mViewAlpha > 0f)) { 81a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek PorterDuff.Mode mode = mDrawAsSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER; 82d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek int color = getScrimColorWithAlpha(); 836811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek if (!mHasExcludedArea) { 846811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek canvas.drawColor(color, mode); 856811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek } else { 866811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek mPaint.setColor(color); 876811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek if (mExcludedRect.top > 0) { 886811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek canvas.drawRect(0, 0, getWidth(), mExcludedRect.top, mPaint); 896811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek } 906811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek if (mExcludedRect.left > 0) { 916811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek canvas.drawRect(0, mExcludedRect.top, mExcludedRect.left, mExcludedRect.bottom, 926811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek mPaint); 936811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek } 946811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek if (mExcludedRect.right < getWidth()) { 956811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek canvas.drawRect(mExcludedRect.right, 966811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek mExcludedRect.top, 976811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek getWidth(), 986811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek mExcludedRect.bottom, 996811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek mPaint); 1006811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek } 1016811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek if (mExcludedRect.bottom < getHeight()) { 1026811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek canvas.drawRect(0, mExcludedRect.bottom, getWidth(), getHeight(), mPaint); 1036811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek } 1046811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek } 105a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 106a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 107a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 108d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek public int getScrimColorWithAlpha() { 109d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek int color = mScrimColor; 110d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek color = Color.argb((int) (Color.alpha(color) * mViewAlpha), Color.red(color), 111d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek Color.green(color), Color.blue(color)); 112d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek return color; 113d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek } 114d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek 115a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public void setDrawAsSrc(boolean asSrc) { 116a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mDrawAsSrc = asSrc; 1176811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek mPaint.setXfermode(new PorterDuffXfermode(mDrawAsSrc ? PorterDuff.Mode.SRC 1186811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek : PorterDuff.Mode.SRC_OVER)); 119a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek invalidate(); 120a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 121a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 122a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public void setScrimColor(int color) { 123a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek if (color != mScrimColor) { 124a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mIsEmpty = Color.alpha(color) == 0; 125a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mScrimColor = color; 126a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek invalidate(); 127d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek if (mChangeRunnable != null) { 128d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek mChangeRunnable.run(); 129d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek } 130a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 131a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 132a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 133a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public int getScrimColor() { 134a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek return mScrimColor; 135a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 136a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 137a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek @Override 138a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public boolean hasOverlappingRendering() { 139a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek return false; 140a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 141a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 142a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public void setViewAlpha(float alpha) { 143a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek if (mAlphaAnimator != null) { 144a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator.cancel(); 145a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 146d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek if (alpha != mViewAlpha) { 147d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek mViewAlpha = alpha; 148d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek invalidate(); 149d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek if (mChangeRunnable != null) { 150d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek mChangeRunnable.run(); 151d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek } 152d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek } 153a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 154a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek 155a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek public void animateViewAlpha(float alpha, long durationOut, Interpolator interpolator) { 156a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek if (mAlphaAnimator != null) { 157a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator.cancel(); 158a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 159a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator = ValueAnimator.ofFloat(mViewAlpha, alpha); 160a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator.addUpdateListener(mAlphaUpdateListener); 161a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator.addListener(mClearAnimatorListener); 162a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator.setInterpolator(interpolator); 163a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator.setDuration(durationOut); 164a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek mAlphaAnimator.start(); 165a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek } 1666811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek 1676811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek public void setExcludedArea(Rect area) { 1686811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek if (area == null) { 1696811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek mHasExcludedArea = false; 1706811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek invalidate(); 1716811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek return; 1726811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek } 173936233c78e7c6e6e21c876af70b1d5374d4c063aJorim Jaggi 174936233c78e7c6e6e21c876af70b1d5374d4c063aJorim Jaggi int left = Math.max(area.left, 0); 175936233c78e7c6e6e21c876af70b1d5374d4c063aJorim Jaggi int top = Math.max(area.top, 0); 176936233c78e7c6e6e21c876af70b1d5374d4c063aJorim Jaggi int right = Math.min(area.right, getWidth()); 177936233c78e7c6e6e21c876af70b1d5374d4c063aJorim Jaggi int bottom = Math.min(area.bottom, getHeight()); 178936233c78e7c6e6e21c876af70b1d5374d4c063aJorim Jaggi mExcludedRect.set(left, top, right, bottom); 179936233c78e7c6e6e21c876af70b1d5374d4c063aJorim Jaggi mHasExcludedArea = left < right && top < bottom; 1806811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek invalidate(); 1816811d728fb988a32cbfc836b768a261a7f60c98aSelim Cinek } 182d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek 183d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek public void setChangeRunnable(Runnable changeRunnable) { 184d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek mChangeRunnable = changeRunnable; 185d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek } 186a0fad3ba06d0352f640532e69ed3d540b3795535Selim Cinek} 187