diff options
author | Adam Powell <adamp@google.com> | 2014-05-30 15:52:44 -0700 |
---|---|---|
committer | Adam Powell <adamp@google.com> | 2014-06-01 17:15:42 -0700 |
commit | 07a74548ae5c1e064508cb1c79ac34de1142b240 (patch) | |
tree | 682c82642b80ed6150084c13358c2b73b91c176c /core | |
parent | 377801463ef75d7c14f3ef6a346d8ddccb2a4045 (diff) | |
download | frameworks_base-07a74548ae5c1e064508cb1c79ac34de1142b240.zip frameworks_base-07a74548ae5c1e064508cb1c79ac34de1142b240.tar.gz frameworks_base-07a74548ae5c1e064508cb1c79ac34de1142b240.tar.bz2 |
Further implementation for ToolbarActionBar
Integrate activity options menu and inline Toolbars. Fix a series of
small associated bugs.
Activities now (privately) offer several menu-related events directly
to the associated ActionBar. In the future this should help us
untangle some of the menu-based pasta in PhoneWindow.
Bug 15344598
Change-Id: I76211ad17d2bcbb58cf1d88914e855416d084ded
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/app/ActionBar.java | 21 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 23 | ||||
-rw-r--r-- | core/java/android/widget/ActionMenuView.java | 7 | ||||
-rw-r--r-- | core/java/android/widget/Toolbar.java | 17 | ||||
-rw-r--r-- | core/java/com/android/internal/app/ToolbarActionBar.java | 179 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/ToolbarWidgetWrapper.java | 9 |
6 files changed, 160 insertions, 96 deletions
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java index f05f4c7..d4c4318 100644 --- a/core/java/android/app/ActionBar.java +++ b/core/java/android/app/ActionBar.java @@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.ActionMode; import android.view.Gravity; +import android.view.KeyEvent; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; @@ -1013,6 +1014,26 @@ public abstract class ActionBar { return null; } + /** @hide */ + public boolean openOptionsMenu() { + return false; + } + + /** @hide */ + public boolean invalidateOptionsMenu() { + return false; + } + + /** @hide */ + public boolean onMenuKeyEvent(KeyEvent event) { + return false; + } + + /** @hide */ + public boolean collapseActionView() { + return false; + } + /** * Listener interface for ActionBar navigation events. * diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 4c32989..23b5f29 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2083,7 +2083,8 @@ public class Activity extends ContextThemeWrapper "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " + "android:windowActionBar to false in your theme to use a Toolbar instead."); } - mActionBar = new ToolbarActionBar(toolbar); + mActionBar = new ToolbarActionBar(toolbar, getTitle(), this); + mActionBar.invalidateOptionsMenu(); } /** @@ -2449,6 +2450,10 @@ public class Activity extends ContextThemeWrapper * but you can override this to do whatever you want. */ public void onBackPressed() { + if (mActionBar != null && mActionBar.collapseActionView()) { + return; + } + if (!mFragments.popBackStackImmediate()) { finishAfterTransition(); } @@ -2660,6 +2665,14 @@ public class Activity extends ContextThemeWrapper */ public boolean dispatchKeyEvent(KeyEvent event) { onUserInteraction(); + + // Let action bars open menus in response to the menu key prioritized over + // the window handling it + if (event.getKeyCode() == KeyEvent.KEYCODE_MENU && + mActionBar != null && mActionBar.onMenuKeyEvent(event)) { + return true; + } + Window win = getWindow(); if (win.superDispatchKeyEvent(event)) { return true; @@ -2907,7 +2920,9 @@ public class Activity extends ContextThemeWrapper * time it needs to be displayed. */ public void invalidateOptionsMenu() { - mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL); + if (mActionBar == null || !mActionBar.invalidateOptionsMenu()) { + mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL); + } } /** @@ -3117,7 +3132,9 @@ public class Activity extends ContextThemeWrapper * open, this method does nothing. */ public void openOptionsMenu() { - mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null); + if (mActionBar == null || !mActionBar.openOptionsMenu()) { + mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null); + } } /** diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java index a9a5eae..acee592 100644 --- a/core/java/android/widget/ActionMenuView.java +++ b/core/java/android/widget/ActionMenuView.java @@ -570,9 +570,9 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo mMenu = new MenuBuilder(context); mMenu.setCallback(new MenuBuilderCallback()); mPresenter = new ActionMenuPresenter(context); - mPresenter.setMenuView(this); mPresenter.setCallback(new ActionMenuPresenterCallback()); mMenu.addMenuPresenter(mPresenter); + mPresenter.setMenuView(this); } return mMenu; @@ -652,6 +652,11 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo return false; } + /** @hide */ + public void setExpandedActionViewsExclusive(boolean exclusive) { + mPresenter.setExpandedActionViewsExclusive(exclusive); + } + /** * Interface responsible for receiving menu item click events if the items themselves * do not have individual item click listeners. diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index c41266e..419c582 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -222,7 +222,7 @@ public class Toolbar extends ViewGroup { final CharSequence subtitle = a.getText(R.styleable.Toolbar_subtitle); if (!TextUtils.isEmpty(subtitle)) { - setSubtitle(title); + setSubtitle(subtitle); } a.recycle(); } @@ -705,10 +705,23 @@ public class Toolbar extends ViewGroup { * @return The toolbar's Menu */ public Menu getMenu() { - ensureMenuView(); + ensureMenu(); return mMenuView.getMenu(); } + private void ensureMenu() { + ensureMenuView(); + if (mMenuView.peekMenu() == null) { + // Initialize a new menu for the first time. + final MenuBuilder menu = (MenuBuilder) mMenuView.getMenu(); + if (mExpandedMenuPresenter == null) { + mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter(); + } + mMenuView.setExpandedActionViewsExclusive(true); + menu.addMenuPresenter(mExpandedMenuPresenter); + } + } + private void ensureMenuView() { if (mMenuView == null) { mMenuView = new ActionMenuView(getContext()); diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java index afb6f7c..6056bf2 100644 --- a/core/java/com/android/internal/app/ToolbarActionBar.java +++ b/core/java/com/android/internal/app/ToolbarActionBar.java @@ -23,37 +23,50 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.view.ActionMode; +import android.view.KeyEvent; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; +import android.view.Window; import android.widget.SpinnerAdapter; import android.widget.Toolbar; +import com.android.internal.view.menu.MenuBuilder; +import com.android.internal.widget.DecorToolbar; +import com.android.internal.widget.ToolbarWidgetWrapper; import java.util.ArrayList; -import java.util.Map; public class ToolbarActionBar extends ActionBar { private Toolbar mToolbar; - private View mCustomView; - - private int mDisplayOptions; - - private int mNavResId; - private int mIconResId; - private int mLogoResId; - private Drawable mNavDrawable; - private Drawable mIconDrawable; - private Drawable mLogoDrawable; - private int mTitleResId; - private int mSubtitleResId; - private CharSequence mTitle; - private CharSequence mSubtitle; + private DecorToolbar mDecorToolbar; + private Window.Callback mWindowCallback; private boolean mLastMenuVisibility; private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners = new ArrayList<OnMenuVisibilityListener>(); - public ToolbarActionBar(Toolbar toolbar) { + private final Runnable mMenuInvalidator = new Runnable() { + @Override + public void run() { + populateOptionsMenu(); + } + }; + + private final Toolbar.OnMenuItemClickListener mMenuClicker = + new Toolbar.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + return mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item); + } + }; + + public ToolbarActionBar(Toolbar toolbar, CharSequence title, Window.Callback windowCallback) { mToolbar = toolbar; + mDecorToolbar = new ToolbarWidgetWrapper(toolbar); + mWindowCallback = windowCallback; + toolbar.setOnMenuItemClickListener(mMenuClicker); + mDecorToolbar.setWindowTitle(title); } @Override @@ -63,19 +76,8 @@ public class ToolbarActionBar extends ActionBar { @Override public void setCustomView(View view, LayoutParams layoutParams) { - if (mCustomView != null) { - mToolbar.removeView(mCustomView); - } - mCustomView = view; - if (view != null) { - mToolbar.addView(view, generateLayoutParams(layoutParams)); - } - } - - private Toolbar.LayoutParams generateLayoutParams(LayoutParams lp) { - final Toolbar.LayoutParams result = new Toolbar.LayoutParams(lp); - result.gravity = lp.gravity; - return result; + view.setLayoutParams(layoutParams); + mDecorToolbar.setCustomView(view); } @Override @@ -86,48 +88,22 @@ public class ToolbarActionBar extends ActionBar { @Override public void setIcon(int resId) { - mIconResId = resId; - mIconDrawable = null; - updateToolbarLogo(); + mDecorToolbar.setIcon(resId); } @Override public void setIcon(Drawable icon) { - mIconResId = 0; - mIconDrawable = icon; - updateToolbarLogo(); + mDecorToolbar.setIcon(icon); } @Override public void setLogo(int resId) { - mLogoResId = resId; - mLogoDrawable = null; - updateToolbarLogo(); + mDecorToolbar.setLogo(resId); } @Override public void setLogo(Drawable logo) { - mLogoResId = 0; - mLogoDrawable = logo; - updateToolbarLogo(); - } - - private void updateToolbarLogo() { - Drawable drawable = null; - if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) { - final int resId; - if ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) { - resId = mLogoResId; - drawable = mLogoDrawable; - } else { - resId = mIconResId; - drawable = mIconDrawable; - } - if (resId != 0) { - drawable = mToolbar.getContext().getDrawable(resId); - } - } - mToolbar.setLogo(drawable); + mDecorToolbar.setLogo(logo); } @Override @@ -219,42 +195,22 @@ public class ToolbarActionBar extends ActionBar { @Override public void setTitle(CharSequence title) { - mTitle = title; - mTitleResId = 0; - updateToolbarTitle(); + mDecorToolbar.setTitle(title); } @Override public void setTitle(int resId) { - mTitleResId = resId; - mTitle = null; - updateToolbarTitle(); + mDecorToolbar.setTitle(resId != 0 ? mDecorToolbar.getContext().getText(resId) : null); } @Override public void setSubtitle(CharSequence subtitle) { - mSubtitle = subtitle; - mSubtitleResId = 0; - updateToolbarTitle(); + mDecorToolbar.setSubtitle(subtitle); } @Override public void setSubtitle(int resId) { - mSubtitleResId = resId; - mSubtitle = null; - updateToolbarTitle(); - } - - private void updateToolbarTitle() { - final Context context = mToolbar.getContext(); - CharSequence title = null; - CharSequence subtitle = null; - if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) { - title = mTitleResId != 0 ? context.getText(mTitleResId) : mTitle; - subtitle = mSubtitleResId != 0 ? context.getText(mSubtitleResId) : mSubtitle; - } - mToolbar.setTitle(title); - mToolbar.setSubtitle(subtitle); + mDecorToolbar.setSubtitle(resId != 0 ? mDecorToolbar.getContext().getText(resId) : null); } @Override @@ -264,9 +220,8 @@ public class ToolbarActionBar extends ActionBar { @Override public void setDisplayOptions(@DisplayOptions int options, @DisplayOptions int mask) { - final int oldOptions = mDisplayOptions; - mDisplayOptions = (options & mask) | (mDisplayOptions & ~mask); - final int optionsChanged = oldOptions ^ mDisplayOptions; + mDecorToolbar.setDisplayOptions((options & mask) | + mDecorToolbar.getDisplayOptions() & ~mask); } @Override @@ -301,7 +256,7 @@ public class ToolbarActionBar extends ActionBar { @Override public View getCustomView() { - return mCustomView; + return mDecorToolbar.getCustomView(); } @Override @@ -327,7 +282,7 @@ public class ToolbarActionBar extends ActionBar { @Override public int getDisplayOptions() { - return mDisplayOptions; + return mDecorToolbar.getDisplayOptions(); } @Override @@ -425,6 +380,54 @@ public class ToolbarActionBar extends ActionBar { return mToolbar.getVisibility() == View.VISIBLE; } + @Override + public boolean openOptionsMenu() { + return mToolbar.showOverflowMenu(); + } + + @Override + public boolean invalidateOptionsMenu() { + mToolbar.removeCallbacks(mMenuInvalidator); + mToolbar.postOnAnimation(mMenuInvalidator); + return true; + } + + @Override + public boolean collapseActionView() { + if (mToolbar.hasExpandedActionView()) { + mToolbar.collapseActionView(); + return true; + } + return false; + } + + void populateOptionsMenu() { + final Menu menu = mToolbar.getMenu(); + final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null; + if (mb != null) { + mb.stopDispatchingItemsChanged(); + } + try { + menu.clear(); + if (!mWindowCallback.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu) || + !mWindowCallback.onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu)) { + menu.clear(); + } + } finally { + if (mb != null) { + mb.startDispatchingItemsChanged(); + } + } + } + + @Override + public boolean onMenuKeyEvent(KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_UP) { + openOptionsMenu(); + } + return true; + } + public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { mMenuVisibilityListeners.add(listener); } diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java index b8dc307..3e15c32 100644 --- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java +++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Parcelable; +import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import android.view.LayoutInflater; @@ -80,16 +81,20 @@ public class ToolbarWidgetWrapper implements DecorToolbar { public ToolbarWidgetWrapper(Toolbar toolbar) { mToolbar = toolbar; + mTitle = toolbar.getTitle(); + mSubtitle = toolbar.getSubtitle(); + mTitleSet = !TextUtils.isEmpty(mTitle); + final TypedArray a = toolbar.getContext().obtainStyledAttributes(null, R.styleable.ActionBar, R.attr.actionBarStyle, 0); final CharSequence title = a.getText(R.styleable.ActionBar_title); - if (title != null) { + if (!TextUtils.isEmpty(title)) { setTitle(title); } final CharSequence subtitle = a.getText(R.styleable.ActionBar_subtitle); - if (subtitle != null) { + if (!TextUtils.isEmpty(subtitle)) { setSubtitle(subtitle); } |