NavigationBarView.java revision df89e65bf0fcc651d20b208c8d8d0b848fb43418
1/*
2 * Copyright (C) 2008 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
17package com.android.systemui.statusbar.phone;
18
19import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.content.Context;
22import android.content.res.Resources;
23import android.os.ServiceManager;
24import android.util.AttributeSet;
25import android.util.Slog;
26import android.view.animation.AccelerateInterpolator;
27import android.view.Display;
28import android.view.MotionEvent;
29import android.view.View;
30import android.view.ViewGroup;
31import android.view.Surface;
32import android.view.WindowManager;
33import android.widget.LinearLayout;
34
35import com.android.internal.statusbar.IStatusBarService;
36
37import com.android.systemui.R;
38
39public class NavigationBarView extends LinearLayout {
40    final static boolean DEBUG = false;
41    final static String TAG = "PhoneStatusBar/NavigationBarView";
42
43    final static boolean DEBUG_DEADZONE = false;
44
45    final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
46
47    final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen
48
49    protected IStatusBarService mBarService;
50    final Display mDisplay;
51    View mCurrentView = null;
52    View[] mRotatedViews = new View[4];
53
54    int mBarSize;
55    boolean mVertical;
56
57    boolean mHidden, mLowProfile, mShowMenu;
58    int mDisabledFlags = 0;
59
60    public View getRecentsButton() {
61        return mCurrentView.findViewById(R.id.recent_apps);
62    }
63
64    public View getMenuButton() {
65        return mCurrentView.findViewById(R.id.menu);
66    }
67
68    public View getBackButton() {
69        return mCurrentView.findViewById(R.id.back);
70    }
71
72    public View getHomeButton() {
73        return mCurrentView.findViewById(R.id.home);
74    }
75
76    public NavigationBarView(Context context, AttributeSet attrs) {
77        super(context, attrs);
78
79        mHidden = false;
80
81        mDisplay = ((WindowManager)context.getSystemService(
82                Context.WINDOW_SERVICE)).getDefaultDisplay();
83        mBarService = IStatusBarService.Stub.asInterface(
84                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
85
86        final Resources res = mContext.getResources();
87        mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
88        mVertical = false;
89        mShowMenu = false;
90    }
91
92    View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
93        @Override
94        public boolean onTouch(View v, MotionEvent ev) {
95            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
96                // even though setting the systemUI visibility below will turn these views
97                // on, we need them to come up faster so that they can catch this motion
98                // event
99                setLowProfile(false, false, false);
100
101                try {
102                    mBarService.setSystemUiVisibility(0);
103                } catch (android.os.RemoteException ex) {
104                }
105            }
106            return false;
107        }
108    };
109
110    public void setDisabledFlags(int disabledFlags) {
111        setDisabledFlags(disabledFlags, false);
112    }
113
114    public void setDisabledFlags(int disabledFlags, boolean force) {
115        if (!force && mDisabledFlags == disabledFlags) return;
116
117        mDisabledFlags = disabledFlags;
118
119        final boolean disableNavigation = ((disabledFlags & View.STATUS_BAR_DISABLE_NAVIGATION) != 0);
120        final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0);
121
122        getBackButton()   .setVisibility(disableBack       ? View.INVISIBLE : View.VISIBLE);
123        getHomeButton()   .setVisibility(disableNavigation ? View.INVISIBLE : View.VISIBLE);
124        getRecentsButton().setVisibility(disableNavigation ? View.INVISIBLE : View.VISIBLE);
125
126        getMenuButton()   .setVisibility((disableNavigation || !mShowMenu)
127                                                           ? View.INVISIBLE : View.VISIBLE);
128    }
129
130    public void setMenuVisibility(final boolean show) {
131        setMenuVisibility(show, false);
132    }
133
134    public void setMenuVisibility(final boolean show, final boolean force) {
135        if (!force && mShowMenu == show) return;
136
137        mShowMenu = show;
138
139        getMenuButton().setVisibility(
140            (0 != (mDisabledFlags & View.STATUS_BAR_DISABLE_NAVIGATION) || !mShowMenu)
141                ? View.INVISIBLE : View.VISIBLE);
142    }
143
144    public void setLowProfile(final boolean lightsOut) {
145        setLowProfile(lightsOut, true, false);
146    }
147
148    public void setLowProfile(final boolean lightsOut, final boolean animate, final boolean force) {
149        if (!force && lightsOut == mLowProfile) return;
150
151        mLowProfile = lightsOut;
152
153        if (DEBUG) Slog.d(TAG, "setting lights " + (lightsOut?"out":"on"));
154
155        final View navButtons = mCurrentView.findViewById(R.id.nav_buttons);
156        final View lowLights = mCurrentView.findViewById(R.id.lights_out);
157
158        // ok, everyone, stop it right there
159        navButtons.animate().cancel();
160        lowLights.animate().cancel();
161
162        if (!animate) {
163            navButtons.setAlpha(lightsOut ? 0f : 1f);
164
165            lowLights.setAlpha(lightsOut ? 1f : 0f);
166            lowLights.setVisibility(lightsOut ? View.VISIBLE : View.GONE);
167        } else {
168            navButtons.animate()
169                .alpha(lightsOut ? 0f : 1f)
170                .setDuration(lightsOut ? 600 : 200)
171                .start();
172
173            lowLights.setOnTouchListener(mLightsOutListener);
174            if (lowLights.getVisibility() == View.GONE) {
175                lowLights.setAlpha(0f);
176                lowLights.setVisibility(View.VISIBLE);
177            }
178            lowLights.animate()
179                .alpha(lightsOut ? 1f : 0f)
180                .setStartDelay(lightsOut ? 500 : 0)
181                .setDuration(lightsOut ? 1000 : 300)
182                .setInterpolator(new AccelerateInterpolator(2.0f))
183                .setListener(lightsOut ? null : new AnimatorListenerAdapter() {
184                    @Override
185                    public void onAnimationEnd(Animator _a) {
186                        lowLights.setVisibility(View.GONE);
187                    }
188                })
189                .start();
190        }
191    }
192
193    public void setHidden(final boolean hide) {
194        if (hide == mHidden) return;
195
196        mHidden = hide;
197        Slog.d(TAG,
198            (hide ? "HIDING" : "SHOWING") + " navigation bar");
199
200        // bring up the lights no matter what
201        setLowProfile(false);
202    }
203
204    public void onFinishInflate() {
205        mRotatedViews[Surface.ROTATION_0] =
206        mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
207
208        mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
209
210        mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
211                                                ? findViewById(R.id.rot90)
212                                                : findViewById(R.id.rot270);
213
214        for (View v : mRotatedViews) {
215            // this helps avoid drawing artifacts with glowing navigation keys
216            ViewGroup group = (ViewGroup) v.findViewById(R.id.nav_buttons);
217            group.setMotionEventSplittingEnabled(false);
218        }
219        mCurrentView = mRotatedViews[Surface.ROTATION_0];
220    }
221
222    public void reorient() {
223        final int rot = mDisplay.getRotation();
224        for (int i=0; i<4; i++) {
225            mRotatedViews[i].setVisibility(View.GONE);
226        }
227        mCurrentView = mRotatedViews[rot];
228        mCurrentView.setVisibility(View.VISIBLE);
229        mVertical = (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270);
230
231        // force the low profile & disabled states into compliance
232        setLowProfile(mLowProfile, false, true /* force */);
233        setDisabledFlags(mDisabledFlags, true /* force */);
234        setMenuVisibility(mShowMenu, true /* force */);
235
236        if (DEBUG_DEADZONE) {
237            mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
238        }
239
240        if (DEBUG) {
241            Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
242        }
243    }
244}
245