Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 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 | |
| 17 | package com.android.systemui.statusbar.phone; |
| 18 | |
Daniel Sandler | 1d4d30a | 2011-04-28 12:35:29 -0400 | [diff] [blame] | 19 | import android.animation.Animator; |
| 20 | import android.animation.AnimatorListenerAdapter; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 21 | import android.content.Context; |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 22 | import android.content.res.Resources; |
Daniel Sandler | 4885295 | 2011-12-01 14:34:23 -0500 | [diff] [blame] | 23 | import android.graphics.Rect; |
Daniel Sandler | 1d4d30a | 2011-04-28 12:35:29 -0400 | [diff] [blame] | 24 | import android.os.ServiceManager; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 25 | import android.util.AttributeSet; |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 26 | import android.util.Slog; |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 27 | import android.view.animation.AccelerateInterpolator; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 28 | import android.view.Display; |
Daniel Sandler | 1d4d30a | 2011-04-28 12:35:29 -0400 | [diff] [blame] | 29 | import android.view.MotionEvent; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 30 | import android.view.View; |
Daniel Sandler | 96f4818 | 2011-08-17 09:50:35 -0400 | [diff] [blame] | 31 | import android.view.ViewGroup; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 32 | import android.view.Surface; |
| 33 | import android.view.WindowManager; |
| 34 | import android.widget.LinearLayout; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 35 | |
Daniel Sandler | 4885295 | 2011-12-01 14:34:23 -0500 | [diff] [blame] | 36 | import java.io.FileDescriptor; |
| 37 | import java.io.PrintWriter; |
| 38 | import java.lang.StringBuilder; |
| 39 | |
Daniel Sandler | 1d4d30a | 2011-04-28 12:35:29 -0400 | [diff] [blame] | 40 | import com.android.internal.statusbar.IStatusBarService; |
| 41 | |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 42 | import com.android.systemui.R; |
| 43 | |
| 44 | public class NavigationBarView extends LinearLayout { |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 45 | final static boolean DEBUG = false; |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 46 | final static String TAG = "PhoneStatusBar/NavigationBarView"; |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 47 | |
Daniel Sandler | 41006aa | 2011-06-29 15:10:49 -0400 | [diff] [blame] | 48 | final static boolean DEBUG_DEADZONE = false; |
| 49 | |
Daniel Sandler | f86f898 | 2011-05-31 15:46:13 -0400 | [diff] [blame] | 50 | final static boolean NAVBAR_ALWAYS_AT_RIGHT = true; |
| 51 | |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 52 | final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen |
| 53 | |
Daniel Sandler | 1d4d30a | 2011-04-28 12:35:29 -0400 | [diff] [blame] | 54 | protected IStatusBarService mBarService; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 55 | final Display mDisplay; |
Daniel Sandler | 5c8da94 | 2011-06-28 00:29:04 -0400 | [diff] [blame] | 56 | View mCurrentView = null; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 57 | View[] mRotatedViews = new View[4]; |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 58 | |
| 59 | int mBarSize; |
| 60 | boolean mVertical; |
| 61 | |
Daniel Sandler | 56598cd | 2011-09-15 16:02:56 -0400 | [diff] [blame] | 62 | boolean mHidden, mLowProfile, mShowMenu; |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 63 | int mDisabledFlags = 0; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 64 | |
Daniel Sandler | 5c8da94 | 2011-06-28 00:29:04 -0400 | [diff] [blame] | 65 | 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 Lockwood | e3646dd | 2011-09-01 12:46:28 -0400 | [diff] [blame] | 73 | 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 Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 81 | public NavigationBarView(Context context, AttributeSet attrs) { |
| 82 | super(context, attrs); |
Daniel Sandler | 96f4818 | 2011-08-17 09:50:35 -0400 | [diff] [blame] | 83 | |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 84 | mHidden = false; |
| 85 | |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 86 | mDisplay = ((WindowManager)context.getSystemService( |
| 87 | Context.WINDOW_SERVICE)).getDefaultDisplay(); |
Daniel Sandler | 1d4d30a | 2011-04-28 12:35:29 -0400 | [diff] [blame] | 88 | mBarService = IStatusBarService.Stub.asInterface( |
| 89 | ServiceManager.getService(Context.STATUS_BAR_SERVICE)); |
| 90 | |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 91 | final Resources res = mContext.getResources(); |
| 92 | mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size); |
| 93 | mVertical = false; |
Daniel Sandler | 56598cd | 2011-09-15 16:02:56 -0400 | [diff] [blame] | 94 | mShowMenu = false; |
Daniel Sandler | 1d4d30a | 2011-04-28 12:35:29 -0400 | [diff] [blame] | 95 | } |
| 96 | |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 97 | 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 Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 104 | setLowProfile(false, false, false); |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 105 | |
| 106 | try { |
| 107 | mBarService.setSystemUiVisibility(0); |
| 108 | } catch (android.os.RemoteException ex) { |
| 109 | } |
| 110 | } |
| 111 | return false; |
| 112 | } |
| 113 | }; |
| 114 | |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 115 | public void setDisabledFlags(int disabledFlags) { |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 116 | 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 Sandler | dba9356 | 2011-10-06 16:39:58 -0400 | [diff] [blame] | 124 | final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0); |
| 125 | final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0); |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 126 | final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0); |
Daniel Sandler | 029d587 | 2011-09-12 00:58:58 -0400 | [diff] [blame] | 127 | |
| 128 | getBackButton() .setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE); |
Daniel Sandler | dba9356 | 2011-10-06 16:39:58 -0400 | [diff] [blame] | 129 | getHomeButton() .setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE); |
| 130 | getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE); |
Daniel Sandler | 56598cd | 2011-09-15 16:02:56 -0400 | [diff] [blame] | 131 | } |
| 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 Sandler | dba9356 | 2011-10-06 16:39:58 -0400 | [diff] [blame] | 142 | getMenuButton().setVisibility(mShowMenu ? View.VISIBLE : View.INVISIBLE); |
Daniel Sandler | 029d587 | 2011-09-12 00:58:58 -0400 | [diff] [blame] | 143 | } |
| 144 | |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 145 | public void setLowProfile(final boolean lightsOut) { |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 146 | setLowProfile(lightsOut, true, false); |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 147 | } |
| 148 | |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 149 | public void setLowProfile(final boolean lightsOut, final boolean animate, final boolean force) { |
| 150 | if (!force && lightsOut == mLowProfile) return; |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 151 | |
| 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 Sandler | f0e8daa | 2011-09-20 10:44:59 -0400 | [diff] [blame] | 159 | // ok, everyone, stop it right there |
| 160 | navButtons.animate().cancel(); |
| 161 | lowLights.animate().cancel(); |
| 162 | |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 163 | if (!animate) { |
Daniel Sandler | f0e8daa | 2011-09-20 10:44:59 -0400 | [diff] [blame] | 164 | navButtons.setAlpha(lightsOut ? 0f : 1f); |
| 165 | |
| 166 | lowLights.setAlpha(lightsOut ? 1f : 0f); |
| 167 | lowLights.setVisibility(lightsOut ? View.VISIBLE : View.GONE); |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 168 | } else { |
| 169 | navButtons.animate() |
| 170 | .alpha(lightsOut ? 0f : 1f) |
| 171 | .setDuration(lightsOut ? 600 : 200) |
| 172 | .start(); |
| 173 | |
| 174 | lowLights.setOnTouchListener(mLightsOutListener); |
Daniel Sandler | f0e8daa | 2011-09-20 10:44:59 -0400 | [diff] [blame] | 175 | if (lowLights.getVisibility() == View.GONE) { |
| 176 | lowLights.setAlpha(0f); |
| 177 | lowLights.setVisibility(View.VISIBLE); |
| 178 | } |
Daniel Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 179 | 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 Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 194 | 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 Sandler | e137a1e | 2011-08-17 16:47:19 -0400 | [diff] [blame] | 201 | // bring up the lights no matter what |
| 202 | setLowProfile(false); |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 203 | } |
| 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 Sandler | f86f898 | 2011-05-31 15:46:13 -0400 | [diff] [blame] | 211 | mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT |
| 212 | ? findViewById(R.id.rot90) |
| 213 | : findViewById(R.id.rot270); |
Daniel Sandler | 5c8da94 | 2011-06-28 00:29:04 -0400 | [diff] [blame] | 214 | |
Daniel Sandler | 96f4818 | 2011-08-17 09:50:35 -0400 | [diff] [blame] | 215 | 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 Sandler | 5c8da94 | 2011-06-28 00:29:04 -0400 | [diff] [blame] | 220 | mCurrentView = mRotatedViews[Surface.ROTATION_0]; |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 221 | } |
| 222 | |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 223 | 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 Sandler | 5c8da94 | 2011-06-28 00:29:04 -0400 | [diff] [blame] | 228 | mCurrentView = mRotatedViews[rot]; |
| 229 | mCurrentView.setVisibility(View.VISIBLE); |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 230 | mVertical = (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270); |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 231 | |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 232 | // force the low profile & disabled states into compliance |
| 233 | setLowProfile(mLowProfile, false, true /* force */); |
| 234 | setDisabledFlags(mDisabledFlags, true /* force */); |
Daniel Sandler | 56598cd | 2011-09-15 16:02:56 -0400 | [diff] [blame] | 235 | setMenuVisibility(mShowMenu, true /* force */); |
Daniel Sandler | 6da2b76 | 2011-09-14 16:04:59 -0400 | [diff] [blame] | 236 | |
Daniel Sandler | 41006aa | 2011-06-29 15:10:49 -0400 | [diff] [blame] | 237 | if (DEBUG_DEADZONE) { |
| 238 | mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF); |
| 239 | } |
| 240 | |
Daniel Sandler | 60ee256 | 2011-07-22 12:34:33 -0400 | [diff] [blame] | 241 | if (DEBUG) { |
| 242 | Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation()); |
| 243 | } |
Daniel Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 244 | } |
Daniel Sandler | 4885295 | 2011-12-01 14:34:23 -0500 | [diff] [blame] | 245 | |
| 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 Sandler | 8956dbb | 2011-04-22 07:55:02 -0400 | [diff] [blame] | 320 | } |