Home | History | Annotate | Download | only in views
      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.recents.views;
     18 
     19 import android.animation.ObjectAnimator;
     20 import android.animation.ValueAnimator;
     21 import android.graphics.Outline;
     22 import android.graphics.Rect;
     23 import android.view.View;
     24 import android.view.ViewOutlineProvider;
     25 
     26 import com.android.systemui.recents.RecentsConfiguration;
     27 
     28 /* An outline provider that has a clip and outline that can be animated. */
     29 public class AnimateableViewBounds extends ViewOutlineProvider {
     30 
     31     RecentsConfiguration mConfig;
     32 
     33     TaskView mSourceView;
     34     Rect mTmpRect = new Rect();
     35     Rect mClipRect = new Rect();
     36     Rect mClipBounds = new Rect();
     37     Rect mOutlineClipRect = new Rect();
     38     int mCornerRadius;
     39     float mAlpha = 1f;
     40     final float mMinAlpha = 0.25f;
     41 
     42     ObjectAnimator mClipTopAnimator;
     43     ObjectAnimator mClipRightAnimator;
     44     ObjectAnimator mClipBottomAnimator;
     45 
     46     public AnimateableViewBounds(TaskView source, int cornerRadius) {
     47         mConfig = RecentsConfiguration.getInstance();
     48         mSourceView = source;
     49         mCornerRadius = cornerRadius;
     50         setClipTop(getClipTop());
     51         setClipRight(getClipRight());
     52         setClipBottom(getClipBottom());
     53         setOutlineClipBottom(getOutlineClipBottom());
     54     }
     55 
     56     @Override
     57     public void getOutline(View view, Outline outline) {
     58         outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
     59         outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left),
     60                 Math.max(mClipRect.top, mOutlineClipRect.top),
     61                 mSourceView.getWidth() - Math.max(mClipRect.right, mOutlineClipRect.right),
     62                 mSourceView.getHeight() - Math.max(mClipRect.bottom, mOutlineClipRect.bottom),
     63                 mCornerRadius);
     64     }
     65 
     66     /** Sets the view outline alpha. */
     67     void setAlpha(float alpha) {
     68         if (Float.compare(alpha, mAlpha) != 0) {
     69             mAlpha = alpha;
     70             mSourceView.invalidateOutline();
     71         }
     72     }
     73 
     74     /** Animates the top clip. */
     75     void animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener) {
     76         if (mClipTopAnimator != null) {
     77             mClipTopAnimator.removeAllListeners();
     78             mClipTopAnimator.cancel();
     79         }
     80         mClipTopAnimator = ObjectAnimator.ofInt(this, "clipTop", top);
     81         mClipTopAnimator.setDuration(duration);
     82         mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
     83         if (updateListener != null) {
     84             mClipTopAnimator.addUpdateListener(updateListener);
     85         }
     86         mClipTopAnimator.start();
     87     }
     88 
     89     /** Sets the top clip. */
     90     public void setClipTop(int top) {
     91         if (top != mClipRect.top) {
     92             mClipRect.top = top;
     93             mSourceView.invalidateOutline();
     94             updateClipBounds();
     95         }
     96     }
     97 
     98     /** Returns the top clip. */
     99     public int getClipTop() {
    100         return mClipRect.top;
    101     }
    102 
    103     /** Animates the right clip. */
    104     void animateClipRight(int right, int duration) {
    105         if (mClipRightAnimator != null) {
    106             mClipRightAnimator.removeAllListeners();
    107             mClipRightAnimator.cancel();
    108         }
    109         mClipRightAnimator = ObjectAnimator.ofInt(this, "clipRight", right);
    110         mClipRightAnimator.setDuration(duration);
    111         mClipRightAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
    112         mClipRightAnimator.start();
    113     }
    114 
    115     /** Sets the right clip. */
    116     public void setClipRight(int right) {
    117         if (right != mClipRect.right) {
    118             mClipRect.right = right;
    119             mSourceView.invalidateOutline();
    120             updateClipBounds();
    121         }
    122     }
    123 
    124     /** Returns the right clip. */
    125     public int getClipRight() {
    126         return mClipRect.right;
    127     }
    128 
    129     /** Animates the bottom clip. */
    130     void animateClipBottom(int bottom, int duration) {
    131         if (mClipBottomAnimator != null) {
    132             mClipBottomAnimator.removeAllListeners();
    133             mClipBottomAnimator.cancel();
    134         }
    135         mClipBottomAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
    136         mClipBottomAnimator.setDuration(duration);
    137         mClipBottomAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
    138         mClipBottomAnimator.start();
    139     }
    140 
    141     /** Sets the bottom clip. */
    142     public void setClipBottom(int bottom) {
    143         if (bottom != mClipRect.bottom) {
    144             mClipRect.bottom = bottom;
    145             mSourceView.invalidateOutline();
    146             updateClipBounds();
    147             if (!mConfig.useHardwareLayers) {
    148                 mSourceView.mThumbnailView.updateVisibility(
    149                         bottom - mSourceView.getPaddingBottom());
    150             }
    151         }
    152     }
    153 
    154     /** Returns the bottom clip. */
    155     public int getClipBottom() {
    156         return mClipRect.bottom;
    157     }
    158 
    159     /** Sets the outline bottom clip. */
    160     public void setOutlineClipBottom(int bottom) {
    161         if (bottom != mOutlineClipRect.bottom) {
    162             mOutlineClipRect.bottom = bottom;
    163             mSourceView.invalidateOutline();
    164         }
    165     }
    166 
    167     /** Gets the outline bottom clip. */
    168     public int getOutlineClipBottom() {
    169         return mOutlineClipRect.bottom;
    170     }
    171 
    172     private void updateClipBounds() {
    173         mClipBounds.set(mClipRect.left, mClipRect.top,
    174                 mSourceView.getWidth() - mClipRect.right,
    175                 mSourceView.getHeight() - mClipRect.bottom);
    176         mSourceView.setClipBounds(mClipBounds);
    177     }
    178 }
    179