blob: 97a18555e43230be79d312564f7afa3eb3e8585c [file] [log] [blame]
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001/*
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
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040021import android.content.Context;
Daniel Sandler60ee2562011-07-22 12:34:33 -040022import android.content.res.Resources;
Daniel Sandler48852952011-12-01 14:34:23 -050023import android.graphics.Rect;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040024import android.os.ServiceManager;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040025import android.util.AttributeSet;
Daniel Sandler60ee2562011-07-22 12:34:33 -040026import android.util.Slog;
Daniel Sandlere137a1e2011-08-17 16:47:19 -040027import android.view.animation.AccelerateInterpolator;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040028import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040029import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040030import android.view.View;
Daniel Sandler96f48182011-08-17 09:50:35 -040031import android.view.ViewGroup;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040032import android.view.Surface;
33import android.view.WindowManager;
34import android.widget.LinearLayout;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040035
Daniel Sandler48852952011-12-01 14:34:23 -050036import java.io.FileDescriptor;
37import java.io.PrintWriter;
38import java.lang.StringBuilder;
39
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040040import com.android.internal.statusbar.IStatusBarService;
41
Daniel Sandler8956dbb2011-04-22 07:55:02 -040042import com.android.systemui.R;
43
44public class NavigationBarView extends LinearLayout {
Daniel Sandler60ee2562011-07-22 12:34:33 -040045 final static boolean DEBUG = false;
Daniel Sandler6da2b762011-09-14 16:04:59 -040046 final static String TAG = "PhoneStatusBar/NavigationBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040047
Daniel Sandler41006aa2011-06-29 15:10:49 -040048 final static boolean DEBUG_DEADZONE = false;
49
Daniel Sandlerf86f8982011-05-31 15:46:13 -040050 final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
51
Daniel Sandlere137a1e2011-08-17 16:47:19 -040052 final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen
53
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040054 protected IStatusBarService mBarService;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040055 final Display mDisplay;
Daniel Sandler5c8da942011-06-28 00:29:04 -040056 View mCurrentView = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040057 View[] mRotatedViews = new View[4];
Daniel Sandler60ee2562011-07-22 12:34:33 -040058
59 int mBarSize;
60 boolean mVertical;
61
Daniel Sandler56598cd2011-09-15 16:02:56 -040062 boolean mHidden, mLowProfile, mShowMenu;
Daniel Sandler6da2b762011-09-14 16:04:59 -040063 int mDisabledFlags = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040064
Daniel Sandler5c8da942011-06-28 00:29:04 -040065 public View getRecentsButton() {
66 return mCurrentView.findViewById(R.id.recent_apps);
67 }
68
69 public View getMenuButton() {
70 return mCurrentView.findViewById(R.id.menu);
71 }
72
Mike Lockwoode3646dd2011-09-01 12:46:28 -040073 public View getBackButton() {
74 return mCurrentView.findViewById(R.id.back);
75 }
76
77 public View getHomeButton() {
78 return mCurrentView.findViewById(R.id.home);
79 }
80
Daniel Sandler8956dbb2011-04-22 07:55:02 -040081 public NavigationBarView(Context context, AttributeSet attrs) {
82 super(context, attrs);
Daniel Sandler96f48182011-08-17 09:50:35 -040083
Daniel Sandler60ee2562011-07-22 12:34:33 -040084 mHidden = false;
85
Daniel Sandler8956dbb2011-04-22 07:55:02 -040086 mDisplay = ((WindowManager)context.getSystemService(
87 Context.WINDOW_SERVICE)).getDefaultDisplay();
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040088 mBarService = IStatusBarService.Stub.asInterface(
89 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
90
Daniel Sandler60ee2562011-07-22 12:34:33 -040091 final Resources res = mContext.getResources();
92 mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
93 mVertical = false;
Daniel Sandler56598cd2011-09-15 16:02:56 -040094 mShowMenu = false;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040095 }
96
Daniel Sandlere137a1e2011-08-17 16:47:19 -040097 View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
98 @Override
99 public boolean onTouch(View v, MotionEvent ev) {
100 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
101 // even though setting the systemUI visibility below will turn these views
102 // on, we need them to come up faster so that they can catch this motion
103 // event
Daniel Sandler6da2b762011-09-14 16:04:59 -0400104 setLowProfile(false, false, false);
Daniel Sandlere137a1e2011-08-17 16:47:19 -0400105
106 try {
107 mBarService.setSystemUiVisibility(0);
108 } catch (android.os.RemoteException ex) {
109 }
110 }
111 return false;
112 }
113 };
114
Daniel Sandler6da2b762011-09-14 16:04:59 -0400115 public void setDisabledFlags(int disabledFlags) {
Daniel Sandler6da2b762011-09-14 16:04:59 -0400116 setDisabledFlags(disabledFlags, false);
117 }
118
119 public void setDisabledFlags(int disabledFlags, boolean force) {
120 if (!force && mDisabledFlags == disabledFlags) return;
121
122 mDisabledFlags = disabledFlags;
123
Daniel Sandlerdba93562011-10-06 16:39:58 -0400124 final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
125 final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400126 final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0);
Daniel Sandler029d5872011-09-12 00:58:58 -0400127
128 getBackButton() .setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Daniel Sandlerdba93562011-10-06 16:39:58 -0400129 getHomeButton() .setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
130 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
Daniel Sandler56598cd2011-09-15 16:02:56 -0400131 }
132
133 public void setMenuVisibility(final boolean show) {
134 setMenuVisibility(show, false);
135 }
136
137 public void setMenuVisibility(final boolean show, final boolean force) {
138 if (!force && mShowMenu == show) return;
139
140 mShowMenu = show;
141
Daniel Sandlerdba93562011-10-06 16:39:58 -0400142 getMenuButton().setVisibility(mShowMenu ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler029d5872011-09-12 00:58:58 -0400143 }
144
Daniel Sandlere137a1e2011-08-17 16:47:19 -0400145 public void setLowProfile(final boolean lightsOut) {
Daniel Sandler6da2b762011-09-14 16:04:59 -0400146 setLowProfile(lightsOut, true, false);
Daniel Sandlere137a1e2011-08-17 16:47:19 -0400147 }
148
Daniel Sandler6da2b762011-09-14 16:04:59 -0400149 public void setLowProfile(final boolean lightsOut, final boolean animate, final boolean force) {
150 if (!force && lightsOut == mLowProfile) return;
Daniel Sandlere137a1e2011-08-17 16:47:19 -0400151
152 mLowProfile = lightsOut;
153
154 if (DEBUG) Slog.d(TAG, "setting lights " + (lightsOut?"out":"on"));
155
156 final View navButtons = mCurrentView.findViewById(R.id.nav_buttons);
157 final View lowLights = mCurrentView.findViewById(R.id.lights_out);
158
Daniel Sandlerf0e8daa2011-09-20 10:44:59 -0400159 // ok, everyone, stop it right there
160 navButtons.animate().cancel();
161 lowLights.animate().cancel();
162
Daniel Sandlere137a1e2011-08-17 16:47:19 -0400163 if (!animate) {
Daniel Sandlerf0e8daa2011-09-20 10:44:59 -0400164 navButtons.setAlpha(lightsOut ? 0f : 1f);
165
166 lowLights.setAlpha(lightsOut ? 1f : 0f);
167 lowLights.setVisibility(lightsOut ? View.VISIBLE : View.GONE);
Daniel Sandlere137a1e2011-08-17 16:47:19 -0400168 } else {
169 navButtons.animate()
170 .alpha(lightsOut ? 0f : 1f)
171 .setDuration(lightsOut ? 600 : 200)
172 .start();
173
174 lowLights.setOnTouchListener(mLightsOutListener);
Daniel Sandlerf0e8daa2011-09-20 10:44:59 -0400175 if (lowLights.getVisibility() == View.GONE) {
176 lowLights.setAlpha(0f);
177 lowLights.setVisibility(View.VISIBLE);
178 }
Daniel Sandlere137a1e2011-08-17 16:47:19 -0400179 lowLights.animate()
180 .alpha(lightsOut ? 1f : 0f)
181 .setStartDelay(lightsOut ? 500 : 0)
182 .setDuration(lightsOut ? 1000 : 300)
183 .setInterpolator(new AccelerateInterpolator(2.0f))
184 .setListener(lightsOut ? null : new AnimatorListenerAdapter() {
185 @Override
186 public void onAnimationEnd(Animator _a) {
187 lowLights.setVisibility(View.GONE);
188 }
189 })
190 .start();
191 }
192 }
193
Daniel Sandler60ee2562011-07-22 12:34:33 -0400194 public void setHidden(final boolean hide) {
195 if (hide == mHidden) return;
196
197 mHidden = hide;
198 Slog.d(TAG,
199 (hide ? "HIDING" : "SHOWING") + " navigation bar");
200
Daniel Sandlere137a1e2011-08-17 16:47:19 -0400201 // bring up the lights no matter what
202 setLowProfile(false);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400203 }
204
205 public void onFinishInflate() {
206 mRotatedViews[Surface.ROTATION_0] =
207 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
208
209 mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
210
Daniel Sandlerf86f8982011-05-31 15:46:13 -0400211 mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
212 ? findViewById(R.id.rot90)
213 : findViewById(R.id.rot270);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400214
Daniel Sandler96f48182011-08-17 09:50:35 -0400215 for (View v : mRotatedViews) {
216 // this helps avoid drawing artifacts with glowing navigation keys
217 ViewGroup group = (ViewGroup) v.findViewById(R.id.nav_buttons);
218 group.setMotionEventSplittingEnabled(false);
219 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400220 mCurrentView = mRotatedViews[Surface.ROTATION_0];
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400221 }
222
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400223 public void reorient() {
224 final int rot = mDisplay.getRotation();
225 for (int i=0; i<4; i++) {
226 mRotatedViews[i].setVisibility(View.GONE);
227 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400228 mCurrentView = mRotatedViews[rot];
229 mCurrentView.setVisibility(View.VISIBLE);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400230 mVertical = (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400231
Daniel Sandler6da2b762011-09-14 16:04:59 -0400232 // force the low profile & disabled states into compliance
233 setLowProfile(mLowProfile, false, true /* force */);
234 setDisabledFlags(mDisabledFlags, true /* force */);
Daniel Sandler56598cd2011-09-15 16:02:56 -0400235 setMenuVisibility(mShowMenu, true /* force */);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400236
Daniel Sandler41006aa2011-06-29 15:10:49 -0400237 if (DEBUG_DEADZONE) {
238 mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
239 }
240
Daniel Sandler60ee2562011-07-22 12:34:33 -0400241 if (DEBUG) {
242 Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
243 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400244 }
Daniel Sandler48852952011-12-01 14:34:23 -0500245
246 private String getResourceName(int resId) {
247 if (resId != 0) {
248 final android.content.res.Resources res = mContext.getResources();
249 try {
250 return res.getResourceName(resId);
251 } catch (android.content.res.Resources.NotFoundException ex) {
252 return "(unknown)";
253 }
254 } else {
255 return "(null)";
256 }
257 }
258
259 private static String visibilityToString(int vis) {
260 switch (vis) {
261 case View.INVISIBLE:
262 return "INVISIBLE";
263 case View.GONE:
264 return "GONE";
265 default:
266 return "VISIBLE";
267 }
268 }
269
270 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
271 pw.println("NavigationBarView {");
272 final Rect r = new Rect();
273
274 pw.println(String.format(" this: " + PhoneStatusBar.viewInfo(this)
275 + " " + visibilityToString(getVisibility())));
276
277 getWindowVisibleDisplayFrame(r);
278 final boolean offscreen = r.right > mDisplay.getRawWidth()
279 || r.bottom > mDisplay.getRawHeight();
280 pw.println(" window: "
281 + r.toShortString()
282 + " " + visibilityToString(getWindowVisibility())
283 + (offscreen ? " OFFSCREEN!" : ""));
284
285 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s",
286 getResourceName(mCurrentView.getId()),
287 mCurrentView.getWidth(), mCurrentView.getHeight(),
288 visibilityToString(mCurrentView.getVisibility())));
289
290 pw.println(String.format(" disabled=0x%08x vertical=%s hidden=%s low=%s menu=%s",
291 mDisabledFlags,
292 mVertical ? "true" : "false",
293 mHidden ? "true" : "false",
294 mLowProfile ? "true" : "false",
295 mShowMenu ? "true" : "false"));
296
297 final View back = getBackButton();
298 final View home = getHomeButton();
299 final View recent = getRecentsButton();
300 final View menu = getMenuButton();
301
302 pw.println(" back: "
303 + PhoneStatusBar.viewInfo(back)
304 + " " + visibilityToString(back.getVisibility())
305 );
306 pw.println(" home: "
307 + PhoneStatusBar.viewInfo(home)
308 + " " + visibilityToString(home.getVisibility())
309 );
310 pw.println(" rcnt: "
311 + PhoneStatusBar.viewInfo(recent)
312 + " " + visibilityToString(recent.getVisibility())
313 );
314 pw.println(" menu: "
315 + PhoneStatusBar.viewInfo(menu)
316 + " " + visibilityToString(menu.getVisibility())
317 );
318 pw.println(" }");
319 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400320}