Home | History | Annotate | Download | only in statusbar
      1 /*
      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 
     17 package com.android.systemui.statusbar;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorListenerAdapter;
     21 import android.animation.ValueAnimator;
     22 import android.content.Context;
     23 import android.content.res.TypedArray;
     24 import android.graphics.Canvas;
     25 import android.graphics.Color;
     26 import android.graphics.Paint;
     27 import android.graphics.PorterDuff;
     28 import android.graphics.PorterDuffXfermode;
     29 import android.graphics.Rect;
     30 import android.util.AttributeSet;
     31 import android.view.View;
     32 import android.view.animation.Interpolator;
     33 import com.android.systemui.R;
     34 
     35 /**
     36  * A view which can draw a scrim
     37  */
     38 public class ScrimView extends View
     39 {
     40     private final Paint mPaint = new Paint();
     41     private int mScrimColor;
     42     private boolean mIsEmpty = true;
     43     private boolean mDrawAsSrc;
     44     private float mViewAlpha = 1.0f;
     45     private ValueAnimator mAlphaAnimator;
     46     private Rect mExcludedRect = new Rect();
     47     private boolean mHasExcludedArea;
     48     private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
     49             = new ValueAnimator.AnimatorUpdateListener() {
     50         @Override
     51         public void onAnimationUpdate(ValueAnimator animation) {
     52             mViewAlpha = (float) animation.getAnimatedValue();
     53             invalidate();
     54         }
     55     };
     56     private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
     57         @Override
     58         public void onAnimationEnd(Animator animation) {
     59             mAlphaAnimator = null;
     60         }
     61     };
     62     private Runnable mChangeRunnable;
     63 
     64     public ScrimView(Context context) {
     65         this(context, null);
     66     }
     67 
     68     public ScrimView(Context context, AttributeSet attrs) {
     69         this(context, attrs, 0);
     70     }
     71 
     72     public ScrimView(Context context, AttributeSet attrs, int defStyleAttr) {
     73         this(context, attrs, defStyleAttr, 0);
     74     }
     75 
     76     public ScrimView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
     77         super(context, attrs, defStyleAttr, defStyleRes);
     78 
     79         TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrimView);
     80 
     81         try {
     82             mScrimColor = ta.getColor(R.styleable.ScrimView_scrimColor, Color.BLACK);
     83         } finally {
     84             ta.recycle();
     85         }
     86     }
     87 
     88     @Override
     89     protected void onDraw(Canvas canvas) {
     90         if (mDrawAsSrc || (!mIsEmpty && mViewAlpha > 0f)) {
     91             PorterDuff.Mode mode = mDrawAsSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
     92             int color = getScrimColorWithAlpha();
     93             if (!mHasExcludedArea) {
     94                 canvas.drawColor(color, mode);
     95             } else {
     96                 mPaint.setColor(color);
     97                 if (mExcludedRect.top > 0) {
     98                     canvas.drawRect(0, 0, getWidth(), mExcludedRect.top, mPaint);
     99                 }
    100                 if (mExcludedRect.left > 0) {
    101                     canvas.drawRect(0,  mExcludedRect.top, mExcludedRect.left, mExcludedRect.bottom,
    102                             mPaint);
    103                 }
    104                 if (mExcludedRect.right < getWidth()) {
    105                     canvas.drawRect(mExcludedRect.right,
    106                             mExcludedRect.top,
    107                             getWidth(),
    108                             mExcludedRect.bottom,
    109                             mPaint);
    110                 }
    111                 if (mExcludedRect.bottom < getHeight()) {
    112                     canvas.drawRect(0,  mExcludedRect.bottom, getWidth(), getHeight(), mPaint);
    113                 }
    114             }
    115         }
    116     }
    117 
    118     public int getScrimColorWithAlpha() {
    119         int color = mScrimColor;
    120         color = Color.argb((int) (Color.alpha(color) * mViewAlpha), Color.red(color),
    121                 Color.green(color), Color.blue(color));
    122         return color;
    123     }
    124 
    125     public void setDrawAsSrc(boolean asSrc) {
    126         mDrawAsSrc = asSrc;
    127         mPaint.setXfermode(new PorterDuffXfermode(mDrawAsSrc ? PorterDuff.Mode.SRC
    128                 : PorterDuff.Mode.SRC_OVER));
    129         invalidate();
    130     }
    131 
    132     public void setScrimColor(int color) {
    133         if (color != mScrimColor) {
    134             mIsEmpty = Color.alpha(color) == 0;
    135             mScrimColor = color;
    136             invalidate();
    137             if (mChangeRunnable != null) {
    138                 mChangeRunnable.run();
    139             }
    140         }
    141     }
    142 
    143     public int getScrimColor() {
    144         return mScrimColor;
    145     }
    146 
    147     @Override
    148     public boolean hasOverlappingRendering() {
    149         return false;
    150     }
    151 
    152     public void setViewAlpha(float alpha) {
    153         if (mAlphaAnimator != null) {
    154             mAlphaAnimator.cancel();
    155         }
    156         if (alpha != mViewAlpha) {
    157             mViewAlpha = alpha;
    158             invalidate();
    159             if (mChangeRunnable != null) {
    160                 mChangeRunnable.run();
    161             }
    162         }
    163     }
    164 
    165     public void animateViewAlpha(float alpha, long durationOut, Interpolator interpolator) {
    166         if (mAlphaAnimator != null) {
    167             mAlphaAnimator.cancel();
    168         }
    169         mAlphaAnimator = ValueAnimator.ofFloat(mViewAlpha, alpha);
    170         mAlphaAnimator.addUpdateListener(mAlphaUpdateListener);
    171         mAlphaAnimator.addListener(mClearAnimatorListener);
    172         mAlphaAnimator.setInterpolator(interpolator);
    173         mAlphaAnimator.setDuration(durationOut);
    174         mAlphaAnimator.start();
    175     }
    176 
    177     public void setExcludedArea(Rect area) {
    178         if (area == null) {
    179             mHasExcludedArea = false;
    180             invalidate();
    181             return;
    182         }
    183 
    184         int left = Math.max(area.left, 0);
    185         int top = Math.max(area.top, 0);
    186         int right = Math.min(area.right, getWidth());
    187         int bottom = Math.min(area.bottom, getHeight());
    188         mExcludedRect.set(left, top, right, bottom);
    189         mHasExcludedArea = left < right && top < bottom;
    190         invalidate();
    191     }
    192 
    193     public void setChangeRunnable(Runnable changeRunnable) {
    194         mChangeRunnable = changeRunnable;
    195     }
    196 }
    197