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