blob: 7adda001bfcbf10997bbe8db9d08bde610d59af3 [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.os.ServiceManager;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.animation.AccelerateInterpolator;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Surface;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.content.res.Configuration;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
public class NavigationBarView extends LinearLayout {
final static boolean DEBUG = false;
final static String TAG = "PhoneStatusBar/NavigationBarView";
final static boolean DEBUG_DEADZONE = false;
final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen
protected IStatusBarService mBarService;
final Display mDisplay;
View mCurrentView = null;
View[] mRotatedViews = new View[4];
AnimatorSet mLastAnimator = null;
int mBarSize;
boolean mVertical;
boolean mHidden, mLowProfile;
int mDisabledFlags = 0;
public View getRecentsButton() {
return mCurrentView.findViewById(R.id.recent_apps);
}
public View getMenuButton() {
return mCurrentView.findViewById(R.id.menu);
}
public View getBackButton() {
return mCurrentView.findViewById(R.id.back);
}
public View getHomeButton() {
return mCurrentView.findViewById(R.id.home);
}
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
mHidden = false;
mDisplay = ((WindowManager)context.getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay();
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
final Resources res = mContext.getResources();
mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
mVertical = false;
}
View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// even though setting the systemUI visibility below will turn these views
// on, we need them to come up faster so that they can catch this motion
// event
setLowProfile(false, false, false);
try {
mBarService.setSystemUiVisibility(0);
} catch (android.os.RemoteException ex) {
}
}
return false;
}
};
public void setDisabledFlags(int disabledFlags) {
setDisabledFlags(disabledFlags, false);
}
public void setDisabledFlags(int disabledFlags, boolean force) {
if (!force && mDisabledFlags == disabledFlags) return;
mDisabledFlags = disabledFlags;
final boolean disableNavigation = ((disabledFlags & View.STATUS_BAR_DISABLE_NAVIGATION) != 0);
final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0);
getBackButton() .setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
getHomeButton() .setVisibility(disableNavigation ? View.INVISIBLE : View.VISIBLE);
getRecentsButton().setVisibility(disableNavigation ? View.INVISIBLE : View.VISIBLE);
getMenuButton() .setVisibility(disableNavigation ? View.INVISIBLE : View.VISIBLE);
}
public void setLowProfile(final boolean lightsOut) {
setLowProfile(lightsOut, true, false);
}
public void setLowProfile(final boolean lightsOut, final boolean animate, final boolean force) {
if (!force && lightsOut == mLowProfile) return;
mLowProfile = lightsOut;
if (DEBUG) Slog.d(TAG, "setting lights " + (lightsOut?"out":"on"));
final View navButtons = mCurrentView.findViewById(R.id.nav_buttons);
final View lowLights = mCurrentView.findViewById(R.id.lights_out);
// ok, everyone, stop it right there
navButtons.animate().cancel();
lowLights.animate().cancel();
if (!animate) {
navButtons.setAlpha(lightsOut ? 0f : 1f);
lowLights.setAlpha(lightsOut ? 1f : 0f);
lowLights.setVisibility(lightsOut ? View.VISIBLE : View.GONE);
} else {
navButtons.animate()
.alpha(lightsOut ? 0f : 1f)
.setDuration(lightsOut ? 600 : 200)
.start();
lowLights.setOnTouchListener(mLightsOutListener);
if (lowLights.getVisibility() == View.GONE) {
lowLights.setAlpha(0f);
lowLights.setVisibility(View.VISIBLE);
}
lowLights.animate()
.alpha(lightsOut ? 1f : 0f)
.setStartDelay(lightsOut ? 500 : 0)
.setDuration(lightsOut ? 1000 : 300)
.setInterpolator(new AccelerateInterpolator(2.0f))
.setListener(lightsOut ? null : new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator _a) {
lowLights.setVisibility(View.GONE);
}
})
.start();
}
}
public void setHidden(final boolean hide) {
if (hide == mHidden) return;
mHidden = hide;
Slog.d(TAG,
(hide ? "HIDING" : "SHOWING") + " navigation bar");
// bring up the lights no matter what
setLowProfile(false);
if (!ANIMATE_HIDE_TRANSITION) {
setVisibility(hide ? View.GONE : View.VISIBLE);
return;
}
float oldAlpha = mCurrentView.getAlpha();
if (DEBUG) {
Slog.d(TAG, "animating alpha: " + oldAlpha + " -> "
+ (!hide ? 1f : 0f));
}
if (mLastAnimator != null && mLastAnimator.isRunning()) mLastAnimator.cancel();
if (!hide) {
setVisibility(View.VISIBLE);
}
// play us off, animatorset
mLastAnimator = new AnimatorSet();
mLastAnimator.playTogether(
ObjectAnimator.ofFloat(mCurrentView, "alpha", hide ? 0f : 1f),
ObjectAnimator.ofFloat(mCurrentView,
mVertical ? "translationX" : "translationY",
hide ? mBarSize : 0)
);
mLastAnimator.setDuration(!hide ? 250 : 1000);
mLastAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator _a) {
mLastAnimator = null;
if (hide) {
setVisibility(View.GONE);
}
}
});
mLastAnimator.start();
}
public void onFinishInflate() {
mRotatedViews[Surface.ROTATION_0] =
mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
? findViewById(R.id.rot90)
: findViewById(R.id.rot270);
for (View v : mRotatedViews) {
// this helps avoid drawing artifacts with glowing navigation keys
ViewGroup group = (ViewGroup) v.findViewById(R.id.nav_buttons);
group.setMotionEventSplittingEnabled(false);
}
mCurrentView = mRotatedViews[Surface.ROTATION_0];
}
public void reorient() {
final int rot = mDisplay.getRotation();
for (int i=0; i<4; i++) {
mRotatedViews[i].setVisibility(View.GONE);
}
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
mVertical = (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270);
// force the low profile & disabled states into compliance
setLowProfile(mLowProfile, false, true /* force */);
setDisabledFlags(mDisabledFlags, true /* force */);
if (DEBUG_DEADZONE) {
mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
}
if (DEBUG) {
Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
}
}
}