Home | History | Annotate | Download | only in car
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
      5  * except in compliance with the License. You may obtain a copy of the License at
      6  *
      7  *      http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the
     10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     11  * KIND, either express or implied. See the License for the specific language governing
     12  * permissions and limitations under the License.
     13  */
     14 package com.android.systemui.qs.car;
     15 
     16 import android.animation.Animator;
     17 import android.animation.AnimatorInflater;
     18 import android.animation.AnimatorListenerAdapter;
     19 import android.animation.AnimatorSet;
     20 import android.animation.ObjectAnimator;
     21 import android.animation.ValueAnimator;
     22 import android.app.Fragment;
     23 import android.content.Context;
     24 import android.os.Bundle;
     25 import android.support.annotation.Nullable;
     26 import android.support.annotation.VisibleForTesting;
     27 import android.support.v7.widget.GridLayoutManager;
     28 import android.view.LayoutInflater;
     29 import android.view.View;
     30 import android.view.View.OnClickListener;
     31 import android.view.ViewGroup;
     32 
     33 import com.android.systemui.R;
     34 import com.android.systemui.plugins.qs.QS;
     35 import com.android.systemui.qs.QSFooter;
     36 import com.android.systemui.statusbar.car.UserGridRecyclerView;
     37 
     38 import java.util.ArrayList;
     39 import java.util.List;
     40 
     41 /**
     42  * A quick settings fragment for the car. For auto, there is no row for quick settings or ability
     43  * to expand the quick settings panel. Instead, the only thing is that displayed is the
     44  * status bar, and a static row with access to the user switcher and settings.
     45  */
     46 public class CarQSFragment extends Fragment implements QS {
     47     private View mHeader;
     48     private View mUserSwitcherContainer;
     49     private CarQSFooter mFooter;
     50     private View mFooterUserName;
     51     private View mFooterExpandIcon;
     52     private UserGridRecyclerView mUserGridView;
     53     private AnimatorSet mAnimatorSet;
     54     private UserSwitchCallback mUserSwitchCallback;
     55 
     56     @Override
     57     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
     58             Bundle savedInstanceState) {
     59         return inflater.inflate(R.layout.car_qs_panel, container, false);
     60     }
     61 
     62     @Override
     63     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
     64         super.onViewCreated(view, savedInstanceState);
     65         mHeader = view.findViewById(R.id.header);
     66         mFooter = view.findViewById(R.id.qs_footer);
     67         mFooterUserName = mFooter.findViewById(R.id.user_name);
     68         mFooterExpandIcon = mFooter.findViewById(R.id.user_switch_expand_icon);
     69 
     70         mUserSwitcherContainer = view.findViewById(R.id.user_switcher_container);
     71 
     72         updateUserSwitcherHeight(0);
     73 
     74         Context context = getContext();
     75         mUserGridView = mUserSwitcherContainer.findViewById(R.id.user_grid);
     76         GridLayoutManager layoutManager = new GridLayoutManager(context,
     77                 context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
     78         mUserGridView.getRecyclerView().setLayoutManager(layoutManager);
     79         mUserGridView.buildAdapter();
     80 
     81         mUserSwitchCallback = new UserSwitchCallback();
     82         mFooter.setUserSwitchCallback(mUserSwitchCallback);
     83     }
     84 
     85     @Override
     86     public void hideImmediately() {
     87         getView().setVisibility(View.INVISIBLE);
     88     }
     89 
     90     @Override
     91     public void setQsExpansion(float qsExpansionFraction, float headerTranslation) {
     92         // If the header is to be completed translated down, then set it to be visible.
     93         getView().setVisibility(headerTranslation == 0 ? View.VISIBLE : View.INVISIBLE);
     94     }
     95 
     96     @Override
     97     public View getHeader() {
     98         return mHeader;
     99     }
    100 
    101     @VisibleForTesting
    102     QSFooter getFooter() {
    103         return mFooter;
    104     }
    105 
    106     @Override
    107     public void setHeaderListening(boolean listening) {
    108         mFooter.setListening(listening);
    109     }
    110 
    111     @Override
    112     public void setListening(boolean listening) {
    113         mFooter.setListening(listening);
    114     }
    115 
    116     @Override
    117     public int getQsMinExpansionHeight() {
    118         return getView().getHeight();
    119     }
    120 
    121     @Override
    122     public int getDesiredHeight() {
    123         return getView().getHeight();
    124     }
    125 
    126     @Override
    127     public void setPanelView(HeightListener notificationPanelView) {
    128         // No quick settings panel.
    129     }
    130 
    131     @Override
    132     public void setHeightOverride(int desiredHeight) {
    133         // No ability to expand quick settings.
    134     }
    135 
    136     @Override
    137     public void setHeaderClickable(boolean qsExpansionEnabled) {
    138         // Usually this sets the expand button to be clickable, but there is no quick settings to
    139         // expand.
    140     }
    141 
    142     @Override
    143     public boolean isCustomizing() {
    144         // No ability to customize the quick settings.
    145         return false;
    146     }
    147 
    148     @Override
    149     public void setOverscrolling(boolean overscrolling) {
    150         // No overscrolling to reveal quick settings.
    151     }
    152 
    153     @Override
    154     public void setExpanded(boolean qsExpanded) {
    155         // No quick settings to expand
    156     }
    157 
    158     @Override
    159     public boolean isShowingDetail() {
    160         // No detail panel to close.
    161         return false;
    162     }
    163 
    164     @Override
    165     public void closeDetail() {
    166         // No detail panel to close.
    167     }
    168 
    169     @Override
    170     public void setKeyguardShowing(boolean keyguardShowing) {
    171         // No keyguard to show.
    172     }
    173 
    174     @Override
    175     public void animateHeaderSlidingIn(long delay) {
    176         // No header to animate.
    177     }
    178 
    179     @Override
    180     public void animateHeaderSlidingOut() {
    181         // No header to animate.
    182     }
    183 
    184     @Override
    185     public void notifyCustomizeChanged() {
    186         // There is no ability to customize quick settings.
    187     }
    188 
    189     @Override
    190     public void setContainer(ViewGroup container) {
    191         // No quick settings, so no container to set.
    192     }
    193 
    194     @Override
    195     public void setExpandClickListener(OnClickListener onClickListener) {
    196         // No ability to expand the quick settings.
    197     }
    198 
    199     public class UserSwitchCallback {
    200         private boolean mShowing;
    201 
    202         public boolean isShowing() {
    203             return mShowing;
    204         }
    205 
    206         public void show() {
    207             mShowing = true;
    208             animateHeightChange(true /* opening */);
    209         }
    210 
    211         public void hide() {
    212             mShowing = false;
    213             animateHeightChange(false /* opening */);
    214         }
    215     }
    216 
    217     private void updateUserSwitcherHeight(int height) {
    218         ViewGroup.LayoutParams layoutParams = mUserSwitcherContainer.getLayoutParams();
    219         layoutParams.height = height;
    220         mUserSwitcherContainer.requestLayout();
    221     }
    222 
    223     private void animateHeightChange(boolean opening) {
    224         // Animation in progress; cancel it to avoid contention.
    225         if (mAnimatorSet != null){
    226             mAnimatorSet.cancel();
    227         }
    228 
    229         List<Animator> allAnimators = new ArrayList<>();
    230         ValueAnimator heightAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(getContext(),
    231                 opening ? R.anim.car_user_switcher_open_animation
    232                         : R.anim.car_user_switcher_close_animation);
    233         heightAnimator.addUpdateListener(valueAnimator -> {
    234             updateUserSwitcherHeight((Integer) valueAnimator.getAnimatedValue());
    235         });
    236         allAnimators.add(heightAnimator);
    237 
    238         Animator nameAnimator = AnimatorInflater.loadAnimator(getContext(),
    239                 opening ? R.anim.car_user_switcher_open_name_animation
    240                         : R.anim.car_user_switcher_close_name_animation);
    241         nameAnimator.setTarget(mFooterUserName);
    242         allAnimators.add(nameAnimator);
    243 
    244         Animator iconAnimator = AnimatorInflater.loadAnimator(getContext(),
    245                 opening ? R.anim.car_user_switcher_open_icon_animation
    246                         : R.anim.car_user_switcher_close_icon_animation);
    247         iconAnimator.setTarget(mFooterExpandIcon);
    248         allAnimators.add(iconAnimator);
    249 
    250         mAnimatorSet = new AnimatorSet();
    251         mAnimatorSet.addListener(new AnimatorListenerAdapter() {
    252             @Override
    253             public void onAnimationEnd(Animator animation) {
    254                 mAnimatorSet = null;
    255             }
    256         });
    257         mAnimatorSet.playTogether(allAnimators.toArray(new Animator[0]));
    258 
    259         // Setup all values to the start values in the animations, since there are delays, but need
    260         // to have all values start at the beginning.
    261         setupInitialValues(mAnimatorSet);
    262 
    263         mAnimatorSet.start();
    264     }
    265 
    266     private void setupInitialValues(Animator anim) {
    267         if (anim instanceof AnimatorSet) {
    268             for (Animator a : ((AnimatorSet) anim).getChildAnimations()) {
    269                 setupInitialValues(a);
    270             }
    271         } else if (anim instanceof ObjectAnimator) {
    272             ((ObjectAnimator) anim).setCurrentFraction(0.0f);
    273         }
    274     }
    275 }
    276