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.content.Context;
     20 import android.view.View;
     21 
     22 import com.android.systemui.Interpolators;
     23 import com.android.systemui.R;
     24 import com.android.systemui.recents.Recents;
     25 import com.android.systemui.recents.RecentsActivity;
     26 import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
     27 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
     28 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
     29 import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
     30 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
     31 import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
     32 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
     33 import com.android.systemui.recents.model.TaskStack;
     34 
     35 /** Manages the scrims for the various system bars. */
     36 public class SystemBarScrimViews {
     37 
     38     private static final int DEFAULT_ANIMATION_DURATION = 150;
     39 
     40     private Context mContext;
     41 
     42     private View mNavBarScrimView;
     43 
     44     private boolean mHasNavBarScrim;
     45     private boolean mShouldAnimateNavBarScrim;
     46     private boolean mHasTransposedNavBar;
     47     private boolean mHasDockedTasks;
     48     private int mNavBarScrimEnterDuration;
     49 
     50     public SystemBarScrimViews(RecentsActivity activity) {
     51         mContext = activity;
     52         mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
     53         mNavBarScrimView.forceHasOverlappingRendering(false);
     54         mNavBarScrimEnterDuration = activity.getResources().getInteger(
     55                 R.integer.recents_nav_bar_scrim_enter_duration);
     56         mHasNavBarScrim = Recents.getSystemServices().hasTransposedNavigationBar();
     57         mHasDockedTasks = Recents.getSystemServices().hasDockedTask();
     58     }
     59 
     60     /**
     61      * Updates the nav bar scrim.
     62      */
     63     public void updateNavBarScrim(boolean animateNavBarScrim, boolean hasStackTasks,
     64             AnimationProps animation) {
     65         prepareEnterRecentsAnimation(isNavBarScrimRequired(hasStackTasks), animateNavBarScrim);
     66         if (animateNavBarScrim && animation != null) {
     67             animateNavBarScrimVisibility(true, animation);
     68         }
     69     }
     70 
     71     /**
     72      * Prepares the scrim views for animating when entering Recents. This will be called before
     73      * the first draw, unless we are updating the scrim on configuration change.
     74      */
     75     private void prepareEnterRecentsAnimation(boolean hasNavBarScrim, boolean animateNavBarScrim) {
     76         mHasNavBarScrim = hasNavBarScrim;
     77         mShouldAnimateNavBarScrim = animateNavBarScrim;
     78 
     79         mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
     80                 View.VISIBLE : View.INVISIBLE);
     81     }
     82 
     83     /**
     84      * Animates the nav bar scrim visibility.
     85      */
     86     private void animateNavBarScrimVisibility(boolean visible, AnimationProps animation) {
     87         int toY = 0;
     88         if (visible) {
     89             mNavBarScrimView.setVisibility(View.VISIBLE);
     90             mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
     91         } else {
     92             toY = mNavBarScrimView.getMeasuredHeight();
     93         }
     94         if (animation != AnimationProps.IMMEDIATE) {
     95             mNavBarScrimView.animate()
     96                     .translationY(toY)
     97                     .setDuration(animation.getDuration(AnimationProps.BOUNDS))
     98                     .setInterpolator(animation.getInterpolator(AnimationProps.BOUNDS))
     99                     .start();
    100         } else {
    101             mNavBarScrimView.setTranslationY(toY);
    102         }
    103     }
    104 
    105     /**
    106      * @return Whether to show the nav bar scrim.
    107      */
    108     private boolean isNavBarScrimRequired(boolean hasStackTasks) {
    109         return hasStackTasks && !mHasTransposedNavBar && !mHasDockedTasks;
    110     }
    111 
    112     /**** EventBus events ****/
    113 
    114     /**
    115      * Starts animating the scrim views when entering Recents.
    116      */
    117     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
    118         if (mHasNavBarScrim) {
    119             AnimationProps animation = mShouldAnimateNavBarScrim
    120                     ? new AnimationProps()
    121                             .setDuration(AnimationProps.BOUNDS, mNavBarScrimEnterDuration)
    122                             .setInterpolator(AnimationProps.BOUNDS, Interpolators.DECELERATE_QUINT)
    123                     : AnimationProps.IMMEDIATE;
    124             animateNavBarScrimVisibility(true, animation);
    125         }
    126     }
    127 
    128     /**
    129      * Starts animating the scrim views when leaving Recents (either via launching a task, or
    130      * going home).
    131      */
    132     public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
    133         if (mHasNavBarScrim) {
    134             AnimationProps animation = createBoundsAnimation(
    135                     TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION);
    136             animateNavBarScrimVisibility(false, animation);
    137         }
    138     }
    139 
    140     public final void onBusEvent(DismissAllTaskViewsEvent event) {
    141         if (mHasNavBarScrim) {
    142             AnimationProps animation = createBoundsAnimation(
    143                     TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION);
    144             animateNavBarScrimVisibility(false, animation);
    145         }
    146     }
    147 
    148     public final void onBusEvent(ConfigurationChangedEvent event) {
    149         if (event.fromDeviceOrientationChange) {
    150             mHasNavBarScrim = Recents.getSystemServices().hasTransposedNavigationBar();
    151         }
    152         animateScrimToCurrentNavBarState(event.hasStackTasks);
    153     }
    154 
    155     public final void onBusEvent(MultiWindowStateChangedEvent event) {
    156         mHasDockedTasks = event.inMultiWindow;
    157         animateScrimToCurrentNavBarState(event.stack.getStackTaskCount() > 0);
    158     }
    159 
    160     public final void onBusEvent(final DragEndEvent event) {
    161         // Hide the nav bar scrims once we drop to a dock region
    162         if (event.dropTarget instanceof TaskStack.DockState) {
    163             animateScrimToCurrentNavBarState(false /* hasStackTasks */);
    164         }
    165     }
    166 
    167     public final void onBusEvent(final DragEndCancelledEvent event) {
    168         // Restore the scrims to the normal state
    169         animateScrimToCurrentNavBarState(event.stack.getStackTaskCount() > 0);
    170     }
    171 
    172     /**
    173      * Animates the scrim to match the state of the current nav bar.
    174      */
    175     private void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
    176         boolean hasNavBarScrim = isNavBarScrimRequired(hasStackTasks);
    177         if (mHasNavBarScrim != hasNavBarScrim) {
    178             AnimationProps animation = hasNavBarScrim
    179                     ? createBoundsAnimation(DEFAULT_ANIMATION_DURATION)
    180                     : AnimationProps.IMMEDIATE;
    181             animateNavBarScrimVisibility(hasNavBarScrim, animation);
    182         }
    183         mHasNavBarScrim = hasNavBarScrim;
    184     }
    185 
    186     /**
    187      * @return a default animation to aniamte the bounds of the scrim.
    188      */
    189     private AnimationProps createBoundsAnimation(int duration) {
    190         return new AnimationProps()
    191                 .setDuration(AnimationProps.BOUNDS, duration)
    192                 .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
    193     }
    194 }
    195