Java tutorial
/* * 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 java.io.File; import java.net.URISyntaxException; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.app.StatusBarManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.content.res.Resources; import android.content.SharedPreferences; import android.database.ContentObserver; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; import android.graphics.PixelFormat; import android.graphics.PorterDuff.Mode; import android.graphics.Rect; /*import android.graphics.RectF;*/ import android.net.Uri; import android.os.Handler; import android.os.Message; import android.os.ServiceManager; import android.provider.Settings; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.util.ExtendedPropertiesUtils; import android.util.Log; import android.util.Slog; import android.util.TypedValue; import android.view.animation.AccelerateInterpolator; import android.view.animation.AlphaAnimation; import android.view.Display; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.Surface; import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerImpl; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.StringBuilder; import java.math.BigInteger; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.R; import com.android.systemui.WidgetSelectActivity; import com.android.systemui.statusbar.WidgetPagerAdapter; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.DelegateViewHelper; import com.android.systemui.statusbar.policy.KeyButtonView; import com.android.systemui.statusbar.policy.ExtensibleKeyButtonView; 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]; int mBarSize; boolean mVertical; boolean mHidden, mLowProfile, mShowMenu; int mDisabledFlags = 0; int mNavigationIconHints = 0; private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon; public DelegateViewHelper mDelegateHelper; private Context mContext; // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288) final static boolean WORKAROUND_INVALID_LAYOUT = true; final static int MSG_CHECK_INVALID_LAYOUT = 8686; // Navbar Custom Targets defines. final static String ACTION_HOME = "**home**"; final static String ACTION_BACK = "**back**"; final static String ACTION_SEARCH = "**search**"; final static String ACTION_SCREENSHOT = "**screenshot**"; final static String ACTION_MENU = "**menu**"; final static String ACTION_POWER = "**power**"; final static String ACTION_NOTIFICATIONS = "**notifications**"; final static String ACTION_RECENTS = "**recents**"; final static String ACTION_IME = "**ime**"; final static String ACTION_KILL = "**kill**"; final static String ACTION_WIDGET = "**widgets**"; final static String ACTION_NULL = "**null**"; int mNumberOfButtons = 3; // Will determine if NavBar goes to the left side in Landscape Mode private boolean mLeftyMode; /* 0 = Phone UI * 1 = Tablet UI * 2 = Phablet UI */ int mTablet_UI = 0; public String[] mClickActions = new String[7]; public String[] mLongpressActions = new String[7]; public String[] mPortraitIcons = new String[7]; public final static int StockButtonsQty = 3; public final static String[] StockClickActions = { "**back**", "**home**", "**recents**", "**null**", "**null**", "**null**", "**null**" }; public final static String[] StockLongpress = { "**null**", "**null**", "**null**", "**null**", "**null**", "**null**", "**null**" }; FrameLayout rot0; FrameLayout rot90; //Definitions for NavBar Menu button customization public final static int SHOW_LEFT_MENU = 1; public final static int SHOW_RIGHT_MENU = 0; public final static int SHOW_BOTH_MENU = 2; public final static int SHOW_DONT = 4; public final static int VISIBILITY_SYSTEM = 0; public final static int VISIBILITY_SYSTEM_AND_INVIZ = 3; public final static int VISIBILITY_NEVER = 1; public final static int VISIBILITY_ALWAYS = 2; public static final int KEY_MENU_RIGHT = 2; public static final int KEY_MENU_LEFT = 5; private int currentVisibility; private int currentSetting; private boolean mHasBigMenuButton = false; // Widgets public FrameLayout mPopupView; public WindowManager mWindowManager; int originalHeight = 0; TextView mWidgetLabel; ViewPager mWidgetPager; WidgetPagerAdapter mAdapter; int widgetIds[]; float mFirstMoveY; int mCurrentWidgetPage = 0; long mDowntime; boolean mMoving = false; boolean showing = false; private class H extends Handler { public void handleMessage(Message m) { switch (m.what) { case MSG_CHECK_INVALID_LAYOUT: final String how = "" + m.obj; final int w = getWidth(); final int h = getHeight(); final int vw = mCurrentView.getWidth(); final int vh = mCurrentView.getHeight(); if (h != vh || w != vw) { Slog.w(TAG, String.format("*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)", how, w, h, vw, vh)); if (WORKAROUND_INVALID_LAYOUT) { requestLayout(); } } break; } } } public void setDelegateView(View view) { mDelegateHelper.setDelegateView(view); mDelegateHelper.setLefty(mLeftyMode); } public void setBar(BaseStatusBar phoneStatusBar) { mDelegateHelper.setBar(phoneStatusBar); } @Override public boolean onTouchEvent(MotionEvent event) { if (mDelegateHelper != null) { mDelegateHelper.onInterceptTouchEvent(event); } return true; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return mDelegateHelper.onInterceptTouchEvent(event); } private H mHandler = new H(); public View getLeftMenuButton() { return mCurrentView.findViewById(R.id.menu_left); } public View getRightMenuButton() { return mCurrentView.findViewById(R.id.menu); } public View getRecentsButton() { return mCurrentView.findViewById(R.id.recent_apps); } 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); mContext = context; 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; mShowMenu = false; mDelegateHelper = new DelegateViewHelper(this); mBackIcon = res.getDrawable(R.drawable.ic_sysbar_back); mBackLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_land); mBackAltIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime); mBackAltLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime); mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.NAV_BAR_COLOR), false, new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { updateColor(false); } }); } private void makeBar() { ((LinearLayout) rot0.findViewById(R.id.nav_buttons)).removeAllViews(); ((LinearLayout) rot0.findViewById(R.id.lights_out)).removeAllViews(); ((LinearLayout) rot90.findViewById(R.id.nav_buttons)).removeAllViews(); ((LinearLayout) rot90.findViewById(R.id.lights_out)).removeAllViews(); for (int i = 0; i <= 1; i++) { boolean landscape = (i == 1); LinearLayout navButtonLayout = (LinearLayout) (landscape ? rot90.findViewById(R.id.nav_buttons) : rot0.findViewById(R.id.nav_buttons)); LinearLayout lightsOut = (LinearLayout) (landscape ? rot90.findViewById(R.id.lights_out) : rot0.findViewById(R.id.lights_out)); // Add the Main Nav Buttons mHasBigMenuButton = false; for (int j = 0; j < mNumberOfButtons; j++) { ExtensibleKeyButtonView v = generateKey(landscape, mClickActions[j], mLongpressActions[j], mPortraitIcons[j]); v.setTag((landscape ? "key_land_" : "key_") + j); /* if(j == 0) { //dirty hack to set proper icon after showing alt icon if(landscape) mBackLandIcon = v.getDrawable(); else mBackIcon = v.getDrawable(); } */ addButton(navButtonLayout, v, landscape && !mLeftyMode); // if we are in LeftyMode, then we want to add to end, like Portrait addLightsOutButton(lightsOut, v, landscape && !mLeftyMode, false); if (v.getId() == R.id.back) { mBackIcon = mBackLandIcon = v.getDrawable(); } if (v.getId() == R.id.menu) { mHasBigMenuButton = true; } if (mNumberOfButtons == 3 && j != (mNumberOfButtons - 1)) { // add separator view here View separator = new View(mContext); separator.setLayoutParams(getSeparatorLayoutParams(landscape)); addButton(navButtonLayout, separator, landscape); addLightsOutButton(lightsOut, separator, landscape, true); } } // check to see if we already have a menu button if (!mHasBigMenuButton) { // don't add menu buttons if we already have one // add left menu if (currentSetting != SHOW_DONT) { View leftMenuKey = generateKey(landscape, KEY_MENU_LEFT); // since we didn't add these at the beginning, we need to insert it now // the behavior is backwards from landscape (ie, insert at beginning // if portrait, add to end if landscape addButton(navButtonLayout, leftMenuKey, !landscape || (landscape && mLeftyMode)); addLightsOutButton(lightsOut, leftMenuKey, !landscape || (landscape && mLeftyMode), true); } if (currentSetting != SHOW_DONT) { View rightMenuKey = generateKey(landscape, KEY_MENU_RIGHT); addButton(navButtonLayout, rightMenuKey, landscape && !mLeftyMode); addLightsOutButton(lightsOut, rightMenuKey, landscape && !mLeftyMode, true); } } } } private void addLightsOutButton(LinearLayout root, View v, boolean landscape, boolean empty) { ImageView addMe = new ImageView(mContext); addMe.setLayoutParams(v.getLayoutParams()); addMe.setImageResource( empty ? R.drawable.ic_sysbar_lights_out_dot_large : R.drawable.ic_sysbar_lights_out_dot_small); addMe.setScaleType(ImageView.ScaleType.CENTER); addMe.setVisibility(empty ? View.INVISIBLE : View.VISIBLE); if (landscape) root.addView(addMe, 0); else root.addView(addMe); } private void addButton(ViewGroup root, View addMe, boolean landscape) { if (landscape) root.addView(addMe, 0); else root.addView(addMe); } private View generateKey(boolean landscape, int keyId) { KeyButtonView v = null; Resources r = getResources(); int btnWidth = 80; switch (keyId) { case KEY_MENU_RIGHT: v = new KeyButtonView(mContext, null); v.setLayoutParams(getLayoutParams(landscape, (mTablet_UI == 1) ? 80 : 40)); v.setId(R.id.menu); v.setCode(KeyEvent.KEYCODE_MENU); if (mTablet_UI == 1) { v.setImageResource(R.drawable.ic_sysbar_menu_big); v.setVisibility(View.GONE); } else { v.setImageResource(landscape ? R.drawable.ic_sysbar_menu_land : R.drawable.ic_sysbar_menu); v.setVisibility(View.INVISIBLE); } v.setContentDescription(r.getString(R.string.accessibility_menu)); v.setGlowBackground(landscape ? R.drawable.ic_sysbar_highlight_land : R.drawable.ic_sysbar_highlight); return v; case KEY_MENU_LEFT: v = new KeyButtonView(mContext, null); v.setLayoutParams(getLayoutParams(landscape, (mTablet_UI == 1) ? 80 : 40)); v.setId(R.id.menu_left); v.setCode(KeyEvent.KEYCODE_MENU); if (mTablet_UI == 1) { v.setImageResource(R.drawable.ic_sysbar_menu_big); v.setVisibility(View.GONE); } else { v.setImageResource(landscape ? R.drawable.ic_sysbar_menu_land : R.drawable.ic_sysbar_menu); v.setVisibility(View.INVISIBLE); } v.setContentDescription(r.getString(R.string.accessibility_menu)); v.setGlowBackground(landscape ? R.drawable.ic_sysbar_highlight_land : R.drawable.ic_sysbar_highlight); return v; } return null; } private ExtensibleKeyButtonView generateKey(boolean landscape, String clickAction, String longpress, String iconUri) { final int iconSize = 80; ExtensibleKeyButtonView v = new ExtensibleKeyButtonView(mContext, null, clickAction, longpress); Log.i("key.ext", "generated ex key: " + clickAction); v.setLayoutParams(getLayoutParams(landscape, iconSize)); boolean drawableSet = false; if (iconUri != null) { if (iconUri.length() > 0) { // custom icon from the URI here File f = new File(Uri.parse(iconUri).getPath()); if (f.exists()) { v.setImageDrawable(new BitmapDrawable(getResources(), f.getAbsolutePath())); drawableSet = true; } } if (!drawableSet && clickAction != null && !clickAction.startsWith("**")) { // here it's not a system action (**action**), so it must be an // app intent try { Drawable d = mContext.getPackageManager().getActivityIcon(Intent.parseUri(clickAction, 0)); final int[] appIconPadding = getAppIconPadding(); if (landscape) v.setPaddingRelative(appIconPadding[1], appIconPadding[0], appIconPadding[3], appIconPadding[2]); else v.setPaddingRelative(appIconPadding[0], appIconPadding[1], appIconPadding[2], appIconPadding[3]); v.setImageDrawable(d); drawableSet = true; } catch (NameNotFoundException e) { e.printStackTrace(); drawableSet = false; } catch (URISyntaxException e) { e.printStackTrace(); drawableSet = false; } } } if (!drawableSet) { v.setImageDrawable(getNavbarIconImage(landscape, clickAction)); } v.setGlowBackground(landscape ? R.drawable.ic_sysbar_highlight_land : R.drawable.ic_sysbar_highlight); return v; } private int[] getAppIconPadding() { int[] padding = new int[4]; // left padding[0] = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics()); // top padding[1] = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics()); // right padding[2] = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics()); // bottom padding[3] = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()); return padding; } private LayoutParams getLayoutParams(boolean landscape, float dp) { float px = dp * getResources().getDisplayMetrics().density; return landscape ? new LayoutParams(LayoutParams.MATCH_PARENT, (int) px, 1f) : new LayoutParams((int) px, LayoutParams.MATCH_PARENT, 1f); } private LayoutParams getSeparatorLayoutParams(boolean landscape) { float px = 25 * getResources().getDisplayMetrics().density; return landscape ? new LayoutParams(LayoutParams.MATCH_PARENT, (int) px) : new LayoutParams((int) px, LayoutParams.MATCH_PARENT); } 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, View.SYSTEM_UI_FLAG_LOW_PROFILE); } catch (android.os.RemoteException ex) { } } return false; } }; public void setNavigationIconHints(int hints) { setNavigationIconHints(hints, false); } public void setNavigationIconHints(int hints, boolean force) { if (!force && hints == mNavigationIconHints) return; if (DEBUG) { android.widget.Toast.makeText(mContext, "Navigation icon hints = " + hints, 500).show(); } mNavigationIconHints = hints; // We can't gaurantee users will set these buttons as targets if (getBackButton() != null) { getBackButton().setAlpha((0 != (hints & StatusBarManager.NAVIGATION_HINT_BACK_NOP)) ? 0.5f : 1.0f); ((ImageView) getBackButton()) .setImageDrawable((0 != (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT)) ? (mVertical ? mBackAltLandIcon : mBackAltIcon) : (mVertical ? mBackLandIcon : mBackIcon)); } if (getHomeButton() != null) { getHomeButton().setAlpha((0 != (hints & StatusBarManager.NAVIGATION_HINT_HOME_NOP)) ? 0.5f : 1.0f); } if (getRecentsButton() != null) { getRecentsButton().setAlpha((0 != (hints & StatusBarManager.NAVIGATION_HINT_RECENT_NOP)) ? 0.5f : 1.0f); } } public void setDisabledFlags(int disabledFlags) { setDisabledFlags(disabledFlags, false); } public void setDisabledFlags(int disabledFlags, boolean force) { if (!force && mDisabledFlags == disabledFlags) return; mDisabledFlags = disabledFlags; final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0); final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0); final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0); if (mTablet_UI != 1) { // Tabletmode doesn't deal with slippery setSlippery(disableHome && disableRecent && disableBack); } for (int j = 0; j < mNumberOfButtons; j++) { View v = (View) findViewWithTag((mVertical ? "key_land_" : "key_") + j); if (v != null) { int vid = v.getId(); if (vid == R.id.back) { v.setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE); } else if (vid == R.id.recent_apps) { v.setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE); } else { // treat all other buttons as same rule as home v.setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE); } } } } public void setSlippery(boolean newSlippery) { WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams(); if (lp != null) { boolean oldSlippery = (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0; if (!oldSlippery && newSlippery) { lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY; } else if (oldSlippery && !newSlippery) { lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY; } else { return; } WindowManagerImpl.getDefault().updateViewLayout(this, lp); } } public boolean getMenuVisibility() { return mShowMenu; } public void setMenuVisibility(final boolean show) { setMenuVisibility(show, false); } public void setMenuVisibility(final boolean show, final boolean force) { if (!force && mShowMenu == show) return; if ((currentSetting == SHOW_DONT) || mHasBigMenuButton) { return; } mShowMenu = show; boolean localShow = show; ImageView leftButton = (ImageView) getLeftMenuButton(); ImageView rightButton = (ImageView) getRightMenuButton(); switch (currentVisibility) { case VISIBILITY_ALWAYS: localShow = true; case VISIBILITY_SYSTEM: if (mTablet_UI == 1) { rightButton.setImageResource(R.drawable.ic_sysbar_menu_big); leftButton.setImageResource(R.drawable.ic_sysbar_menu_big); } else { rightButton .setImageResource(mVertical ? R.drawable.ic_sysbar_menu_land : R.drawable.ic_sysbar_menu); leftButton.setImageResource(mVertical ? R.drawable.ic_sysbar_menu_land : R.drawable.ic_sysbar_menu); } break; case VISIBILITY_NEVER: leftButton.setImageResource(R.drawable.ic_sysbar_menu_inviz); rightButton.setImageResource(R.drawable.ic_sysbar_menu_inviz); localShow = true; break; case VISIBILITY_SYSTEM_AND_INVIZ: if (localShow) { if (mTablet_UI == 1) { rightButton.setImageResource(R.drawable.ic_sysbar_menu_big); leftButton.setImageResource(R.drawable.ic_sysbar_menu_big); } else { rightButton.setImageResource( mVertical ? R.drawable.ic_sysbar_menu_land : R.drawable.ic_sysbar_menu); leftButton.setImageResource( mVertical ? R.drawable.ic_sysbar_menu_land : R.drawable.ic_sysbar_menu); } } else { localShow = true; leftButton.setImageResource(R.drawable.ic_sysbar_menu_inviz); rightButton.setImageResource(R.drawable.ic_sysbar_menu_inviz); } break; } // do this after just in case show was changed // Tablet menu buttons should not take up space when hidden. switch (currentSetting) { case SHOW_BOTH_MENU: if (mTablet_UI == 1) { leftButton.setVisibility(localShow ? View.VISIBLE : View.GONE); rightButton.setVisibility(localShow ? View.VISIBLE : View.GONE); } else { leftButton.setVisibility(localShow ? View.VISIBLE : View.INVISIBLE); rightButton.setVisibility(localShow ? View.VISIBLE : View.INVISIBLE); } break; case SHOW_LEFT_MENU: if (mTablet_UI == 1) { leftButton.setVisibility(localShow ? View.VISIBLE : View.GONE); } else { leftButton.setVisibility(localShow ? View.VISIBLE : View.INVISIBLE); } rightButton.setVisibility((mTablet_UI == 1) ? View.GONE : View.INVISIBLE); break; default: case SHOW_RIGHT_MENU: leftButton.setVisibility((mTablet_UI == 1) ? View.GONE : View.INVISIBLE); if (mTablet_UI == 1) { rightButton.setVisibility(localShow ? View.VISIBLE : View.GONE); } else { rightButton.setVisibility(localShow ? View.VISIBLE : View.INVISIBLE); } break; } } 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 ? 750 : 250).start(); lowLights.setOnTouchListener(mLightsOutListener); if (lowLights.getVisibility() == View.GONE) { lowLights.setAlpha(0f); lowLights.setVisibility(View.VISIBLE); } lowLights.animate().alpha(lightsOut ? 1f : 0f).setDuration(lightsOut ? 750 : 250) .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); } @Override public void onFinishInflate() { rot0 = (FrameLayout) findViewById(R.id.rot0); rot90 = (FrameLayout) findViewById(R.id.rot90); 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); } updateColor(true); mCurrentView = mRotatedViews[Surface.ROTATION_0]; // this takes care of making the buttons SettingsObserver settingsObserver = new SettingsObserver(new Handler()); settingsObserver.observe(); } public void reorient() { final int rot = mDisplay.getRotation(); for (int i = 0; i < 4; i++) { mRotatedViews[i].setVisibility(View.GONE); } if (mTablet_UI != 0) { // this is either a tablet of Phablet. Need to stay at Rot_0 mCurrentView = mRotatedViews[Surface.ROTATION_0]; } else { mCurrentView = mRotatedViews[rot]; } // mCurrentView = mRotatedViews[rot]; mCurrentView.setVisibility(View.VISIBLE); // force the low profile & disabled states into compliance setLowProfile(mLowProfile, false, true /* force */); setDisabledFlags(mDisabledFlags, true /* force */); setMenuVisibility(mShowMenu, true /* force */); if (DEBUG_DEADZONE) { mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF); } if (DEBUG) { Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation()); } setNavigationIconHints(mNavigationIconHints, true); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mDelegateHelper.setInitialTouchRegion(this); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (DEBUG) Slog.d(TAG, String.format("onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh)); final boolean newVertical = w > 0 && h > w; if (newVertical != mVertical) { mVertical = newVertical; //Slog.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n")); reorient(); } postCheckForInvalidLayout("sizeChanged"); super.onSizeChanged(w, h, oldw, oldh); } /* @Override protected void onLayout (boolean changed, int left, int top, int right, int bottom) { if (DEBUG) Slog.d(TAG, String.format( "onLayout: %s (%d,%d,%d,%d)", changed?"changed":"notchanged", left, top, right, bottom)); super.onLayout(changed, left, top, right, bottom); } // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else // fails, any touch on the display will fix the layout. @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (DEBUG) Slog.d(TAG, "onInterceptTouchEvent: " + ev.toString()); if (ev.getAction() == MotionEvent.ACTION_DOWN) { postCheckForInvalidLayout("touch"); } return super.onInterceptTouchEvent(ev); } */ class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler) { super(handler); } void observe() { ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(Settings.System.getUriFor(Settings.System.MENU_LOCATION), false, this); resolver.registerContentObserver(Settings.System.getUriFor(Settings.System.MENU_VISIBILITY), false, this); resolver.registerContentObserver(Settings.System.getUriFor(Settings.System.NAVIGATION_BAR_BUTTONS_QTY), false, this); resolver.registerContentObserver(Settings.System.getUriFor(Settings.System.NAVIGATION_BAR_LEFTY_MODE), false, this); for (int j = 0; j < 7; j++) { // watch all 5 settings for changes. resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.NAVIGATION_CUSTOM_ACTIVITIES[j]), false, this); resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.NAVIGATION_LONGPRESS_ACTIVITIES[j]), false, this); resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.NAVIGATION_CUSTOM_APP_ICONS[j]), false, this); } updateSettings(); } @Override public void onChange(boolean selfChange) { updateSettings(); } } protected void updateSettings() { ContentResolver resolver = mContext.getContentResolver(); currentSetting = Settings.System.getInt(resolver, Settings.System.MENU_LOCATION, SHOW_RIGHT_MENU); currentVisibility = Settings.System.getInt(resolver, Settings.System.MENU_VISIBILITY, VISIBILITY_SYSTEM); mTablet_UI = Settings.System.getInt(resolver, Settings.System.TABLET_UI, 0); mLeftyMode = Settings.System.getBoolean(resolver, Settings.System.NAVIGATION_BAR_LEFTY_MODE, false); mNumberOfButtons = Settings.System.getInt(resolver, Settings.System.NAVIGATION_BAR_BUTTONS_QTY, 0); if (mNumberOfButtons == 0) { mNumberOfButtons = StockButtonsQty; Settings.System.putInt(resolver, Settings.System.NAVIGATION_BAR_BUTTONS_QTY, StockButtonsQty); } for (int j = 0; j < 7; j++) { mClickActions[j] = Settings.System.getString(resolver, Settings.System.NAVIGATION_CUSTOM_ACTIVITIES[j]); if (mClickActions[j] == null) { mClickActions[j] = StockClickActions[j]; Settings.System.putString(resolver, Settings.System.NAVIGATION_CUSTOM_ACTIVITIES[j], mClickActions[j]); } mLongpressActions[j] = Settings.System.getString(resolver, Settings.System.NAVIGATION_LONGPRESS_ACTIVITIES[j]); if (mLongpressActions[j] == null) { mLongpressActions[j] = StockLongpress[j]; Settings.System.putString(resolver, Settings.System.NAVIGATION_LONGPRESS_ACTIVITIES[j], mLongpressActions[j]); } mPortraitIcons[j] = Settings.System.getString(resolver, Settings.System.NAVIGATION_CUSTOM_APP_ICONS[j]); if (mPortraitIcons[j] == null) { mPortraitIcons[j] = ""; Settings.System.putString(resolver, Settings.System.NAVIGATION_CUSTOM_APP_ICONS[j], ""); } } makeBar(); } private Drawable getNavbarIconImage(boolean landscape, String uri) { if (uri == null) return getResources().getDrawable(R.drawable.ic_sysbar_null); if (uri.startsWith("**")) { if (uri.equals(ACTION_HOME)) { return getResources().getDrawable(R.drawable.ic_sysbar_home); } else if (uri.equals(ACTION_BACK)) { return getResources().getDrawable(R.drawable.ic_sysbar_back); } else if (uri.equals(ACTION_RECENTS)) { return getResources().getDrawable(R.drawable.ic_sysbar_recent); } else if (uri.equals(ACTION_SEARCH)) { return getResources().getDrawable(R.drawable.ic_sysbar_search); } else if (uri.equals(ACTION_SCREENSHOT)) { return getResources().getDrawable(R.drawable.ic_sysbar_screenshot); } else if (uri.equals(ACTION_MENU)) { return getResources().getDrawable(R.drawable.ic_sysbar_menu_big); } else if (uri.equals(ACTION_IME)) { return getResources().getDrawable(R.drawable.ic_sysbar_ime_switcher); } else if (uri.equals(ACTION_KILL)) { return getResources().getDrawable(R.drawable.ic_sysbar_killtask); } else if (uri.equals(ACTION_POWER)) { return getResources().getDrawable(R.drawable.ic_sysbar_power); } else if (uri.equals(ACTION_NOTIFICATIONS)) { return getResources().getDrawable(R.drawable.ic_sysbar_notifications); } else if (uri.equals(ACTION_WIDGET)) { return getResources().getDrawable(R.drawable.ic_sysbar_widget); } } return getResources().getDrawable(R.drawable.ic_sysbar_null); } private void postCheckForInvalidLayout(final String how) { mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget(); } private void updateColor(boolean defaults) { Bitmap bm = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); Canvas cnv = new Canvas(bm); if (defaults) { cnv.drawColor(0xFF000000); setBackground(new BitmapDrawable(bm)); return; } String setting = Settings.System.getString(mContext.getContentResolver(), Settings.System.NAV_BAR_COLOR); String[] colors = (setting == null || setting.equals("") ? ExtendedPropertiesUtils.PARANOID_COLORS_DEFAULTS[ExtendedPropertiesUtils.PARANOID_COLORS_NAVBAR] : setting).split(ExtendedPropertiesUtils.PARANOID_STRING_DELIMITER); String currentColor = colors[Integer.parseInt(colors[2])]; cnv.drawColor(new BigInteger(currentColor, 16).intValue()); TransitionDrawable transition = new TransitionDrawable( new Drawable[] { getBackground(), new BitmapDrawable(bm) }); transition.setCrossFadeEnabled(true); setBackground(transition); transition.startTransition(1000); } }