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