NavigationBarView.java revision dba935659024a9ca83cb6bd3f1a9970e277f7658
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 disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
120        final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
121        final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0);
122
123        getBackButton()   .setVisibility(disableBack       ? View.INVISIBLE : View.VISIBLE);
124        getHomeButton()   .setVisibility(disableHome       ? View.INVISIBLE : View.VISIBLE);
125        getRecentsButton().setVisibility(disableRecent     ? View.INVISIBLE : View.VISIBLE);
126    }
127
128    public void setMenuVisibility(final boolean show) {
129        setMenuVisibility(show, false);
130    }
131
132    public void setMenuVisibility(final boolean show, final boolean force) {
133        if (!force && mShowMenu == show) return;
134
135        mShowMenu = show;
136
137        getMenuButton().setVisibility(mShowMenu ? View.VISIBLE : View.INVISIBLE);
138    }
139
140    public void setLowProfile(final boolean lightsOut) {
141        setLowProfile(lightsOut, true, false);
142    }
143
144    public void setLowProfile(final boolean lightsOut, final boolean animate, final boolean force) {
145        if (!force && lightsOut == mLowProfile) return;
146
147        mLowProfile = lightsOut;
148
149        if (DEBUG) Slog.d(TAG, "setting lights " + (lightsOut?"out":"on"));
150
151        final View navButtons = mCurrentView.findViewById(R.id.nav_buttons);
152        final View lowLights = mCurrentView.findViewById(R.id.lights_out);
153
154        // ok, everyone, stop it right there
155        navButtons.animate().cancel();
156        lowLights.animate().cancel();
157
158        if (!animate) {
159            navButtons.setAlpha(lightsOut ? 0f : 1f);
160
161            lowLights.setAlpha(lightsOut ? 1f : 0f);
162            lowLights.setVisibility(lightsOut ? View.VISIBLE : View.GONE);
163        } else {
164            navButtons.animate()
165                .alpha(lightsOut ? 0f : 1f)
166                .setDuration(lightsOut ? 600 : 200)
167                .start();
168
169            lowLights.setOnTouchListener(mLightsOutListener);
170            if (lowLights.getVisibility() == View.GONE) {
171                lowLights.setAlpha(0f);
172                lowLights.setVisibility(View.VISIBLE);
173            }
174            lowLights.animate()
175                .alpha(lightsOut ? 1f : 0f)
176                .setStartDelay(lightsOut ? 500 : 0)
177                .setDuration(lightsOut ? 1000 : 300)
178                .setInterpolator(new AccelerateInterpolator(2.0f))
179                .setListener(lightsOut ? null : new AnimatorListenerAdapter() {
180                    @Override
181                    public void onAnimationEnd(Animator _a) {
182                        lowLights.setVisibility(View.GONE);
183                    }
184                })
185                .start();
186        }
187    }
188
189    public void setHidden(final boolean hide) {
190        if (hide == mHidden) return;
191
192        mHidden = hide;
193        Slog.d(TAG,
194            (hide ? "HIDING" : "SHOWING") + " navigation bar");
195
196        // bring up the lights no matter what
197        setLowProfile(false);
198    }
199
200    public void onFinishInflate() {
201        mRotatedViews[Surface.ROTATION_0] =
202        mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
203
204        mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
205
206        mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
207                                                ? findViewById(R.id.rot90)
208                                                : findViewById(R.id.rot270);
209
210        for (View v : mRotatedViews) {
211            // this helps avoid drawing artifacts with glowing navigation keys
212            ViewGroup group = (ViewGroup) v.findViewById(R.id.nav_buttons);
213            group.setMotionEventSplittingEnabled(false);
214        }
215        mCurrentView = mRotatedViews[Surface.ROTATION_0];
216    }
217
218    public void reorient() {
219        final int rot = mDisplay.getRotation();
220        for (int i=0; i<4; i++) {
221            mRotatedViews[i].setVisibility(View.GONE);
222        }
223        mCurrentView = mRotatedViews[rot];
224        mCurrentView.setVisibility(View.VISIBLE);
225        mVertical = (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270);
226
227        // force the low profile & disabled states into compliance
228        setLowProfile(mLowProfile, false, true /* force */);
229        setDisabledFlags(mDisabledFlags, true /* force */);
230        setMenuVisibility(mShowMenu, true /* force */);
231
232        if (DEBUG_DEADZONE) {
233            mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
234        }
235
236        if (DEBUG) {
237            Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
238        }
239    }
240}
241