1 /*
2  * Copyright (C) 2013 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.phone;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.content.Context;
22 import android.os.ServiceManager;
23 import android.view.MotionEvent;
24 import android.view.View;
25 import android.view.animation.AccelerateInterpolator;
26 
27 import com.android.internal.statusbar.IStatusBarService;
28 import com.android.systemui.R;
29 import com.android.systemui.statusbar.policy.KeyButtonView;
30 
31 public final class NavigationBarTransitions extends BarTransitions {
32 
33     private static final int CONTENT_FADE_DURATION = 200;
34 
35     private final NavigationBarView mView;
36     private final IStatusBarService mBarService;
37 
38     private boolean mLightsOut;
39     private boolean mVertical;
40     private int mRequestedMode;
41 
NavigationBarTransitions(NavigationBarView view)42     public NavigationBarTransitions(NavigationBarView view) {
43         super(view, R.drawable.nav_background);
44         mView = view;
45         mBarService = IStatusBarService.Stub.asInterface(
46                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
47     }
48 
init(boolean isVertical)49     public void init(boolean isVertical) {
50         setVertical(isVertical);
51         applyModeBackground(-1, getMode(), false /*animate*/);
52         applyMode(getMode(), false /*animate*/, true /*force*/);
53     }
54 
setVertical(boolean isVertical)55     public void setVertical(boolean isVertical) {
56         mVertical = isVertical;
57         transitionTo(mRequestedMode, false /*animate*/);
58     }
59 
60     @Override
transitionTo(int mode, boolean animate)61     public void transitionTo(int mode, boolean animate) {
62         mRequestedMode = mode;
63         if (mVertical) {
64             // translucent mode not allowed when vertical
65             if (mode == MODE_TRANSLUCENT || mode == MODE_TRANSPARENT) {
66                 mode = MODE_OPAQUE;
67             } else if (mode == MODE_LIGHTS_OUT_TRANSPARENT) {
68                 mode = MODE_LIGHTS_OUT;
69             }
70         }
71         super.transitionTo(mode, animate);
72     }
73 
74     @Override
onTransition(int oldMode, int newMode, boolean animate)75     protected void onTransition(int oldMode, int newMode, boolean animate) {
76         super.onTransition(oldMode, newMode, animate);
77         applyMode(newMode, animate, false /*force*/);
78     }
79 
applyMode(int mode, boolean animate, boolean force)80     private void applyMode(int mode, boolean animate, boolean force) {
81         // apply to key buttons
82         final float alpha = alphaForMode(mode);
83         setKeyButtonViewQuiescentAlpha(mView.getHomeButton(), alpha, animate);
84         setKeyButtonViewQuiescentAlpha(mView.getRecentsButton(), alpha, animate);
85         setKeyButtonViewQuiescentAlpha(mView.getMenuButton(), alpha, animate);
86         setKeyButtonViewQuiescentAlpha(mView.getImeSwitchButton(), alpha, animate);
87 
88         applyBackButtonQuiescentAlpha(mode, animate);
89 
90         // apply to lights out
91         applyLightsOut(isLightsOut(mode), animate, force);
92     }
93 
alphaForMode(int mode)94     private float alphaForMode(int mode) {
95         final boolean isOpaque = mode == MODE_OPAQUE || mode == MODE_LIGHTS_OUT;
96         return isOpaque ? KeyButtonView.DEFAULT_QUIESCENT_ALPHA : 1f;
97     }
98 
applyBackButtonQuiescentAlpha(int mode, boolean animate)99     public void applyBackButtonQuiescentAlpha(int mode, boolean animate) {
100         float backAlpha = 0;
101         backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getHomeButton());
102         backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getRecentsButton());
103         backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getMenuButton());
104         backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getImeSwitchButton());
105         if (backAlpha > 0) {
106             setKeyButtonViewQuiescentAlpha(mView.getBackButton(), backAlpha, animate);
107         }
108     }
109 
maxVisibleQuiescentAlpha(float max, View v)110     private static float maxVisibleQuiescentAlpha(float max, View v) {
111         if ((v instanceof KeyButtonView) && v.isShown()) {
112             return Math.max(max, ((KeyButtonView)v).getQuiescentAlpha());
113         }
114         return max;
115     }
116 
setKeyButtonViewQuiescentAlpha(View button, float alpha, boolean animate)117     private void setKeyButtonViewQuiescentAlpha(View button, float alpha, boolean animate) {
118         if (button instanceof KeyButtonView) {
119             ((KeyButtonView) button).setQuiescentAlpha(alpha, animate);
120         }
121     }
122 
applyLightsOut(boolean lightsOut, boolean animate, boolean force)123     private void applyLightsOut(boolean lightsOut, boolean animate, boolean force) {
124         if (!force && lightsOut == mLightsOut) return;
125 
126         mLightsOut = lightsOut;
127 
128         final View navButtons = mView.getCurrentView().findViewById(R.id.nav_buttons);
129         final View lowLights = mView.getCurrentView().findViewById(R.id.lights_out);
130 
131         // ok, everyone, stop it right there
132         navButtons.animate().cancel();
133         lowLights.animate().cancel();
134 
135         final float navButtonsAlpha = lightsOut ? 0f : 1f;
136         final float lowLightsAlpha = lightsOut ? 1f : 0f;
137 
138         if (!animate) {
139             navButtons.setAlpha(navButtonsAlpha);
140             lowLights.setAlpha(lowLightsAlpha);
141             lowLights.setVisibility(lightsOut ? View.VISIBLE : View.GONE);
142         } else {
143             final int duration = lightsOut ? LIGHTS_OUT_DURATION : LIGHTS_IN_DURATION;
144             navButtons.animate()
145                 .alpha(navButtonsAlpha)
146                 .setDuration(duration)
147                 .start();
148 
149             lowLights.setOnTouchListener(mLightsOutListener);
150             if (lowLights.getVisibility() == View.GONE) {
151                 lowLights.setAlpha(0f);
152                 lowLights.setVisibility(View.VISIBLE);
153             }
154             lowLights.animate()
155                 .alpha(lowLightsAlpha)
156                 .setDuration(duration)
157                 .setInterpolator(new AccelerateInterpolator(2.0f))
158                 .setListener(lightsOut ? null : new AnimatorListenerAdapter() {
159                     @Override
160                     public void onAnimationEnd(Animator _a) {
161                         lowLights.setVisibility(View.GONE);
162                     }
163                 })
164                 .start();
165         }
166     }
167 
168     private final View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
169         @Override
170         public boolean onTouch(View v, MotionEvent ev) {
171             if (ev.getAction() == MotionEvent.ACTION_DOWN) {
172                 // even though setting the systemUI visibility below will turn these views
173                 // on, we need them to come up faster so that they can catch this motion
174                 // event
175                 applyLightsOut(false, false, false);
176 
177                 try {
178                     mBarService.setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE,
179                             "LightsOutListener");
180                 } catch (android.os.RemoteException ex) {
181                 }
182             }
183             return false;
184         }
185     };
186 }
187