From 5d27977f9da482627ceb19317a2cd70467aff046 Mon Sep 17 00:00:00 2001 From: Adam Powell Date: Tue, 27 Jul 2010 16:34:07 -0700 Subject: Action modes without action bar Change-Id: I0367ab35e598a17980bd373b30828175f6283acc --- api/current.xml | 68 ++++++++---- core/java/android/app/Activity.java | 4 +- core/java/android/view/MenuInflater.java | 4 + core/java/android/view/Window.java | 7 +- .../com/android/internal/app/ActionBarImpl.java | 22 ++-- .../internal/view/StandaloneActionMode.java | 123 +++++++++++++++++++++ .../internal/widget/ActionBarContextView.java | 4 +- core/res/res/layout-xlarge/screen_action_bar.xml | 45 ++++++++ core/res/res/layout/screen.xml | 7 ++ core/res/res/layout/screen_custom_title.xml | 7 ++ core/res/res/layout/screen_progress.xml | 7 ++ core/res/res/layout/screen_title.xml | 6 + core/res/res/layout/screen_title_icons.xml | 6 + core/res/res/layout/screen_xlarge_action_bar.xml | 45 -------- core/res/res/values/attrs.xml | 16 ++- core/res/res/values/public.xml | 5 +- core/res/res/values/themes.xml | 4 +- .../android/internal/policy/impl/PhoneWindow.java | 74 +++++++++++-- 18 files changed, 356 insertions(+), 98 deletions(-) create mode 100644 core/java/com/android/internal/view/StandaloneActionMode.java create mode 100644 core/res/res/layout-xlarge/screen_action_bar.xml delete mode 100644 core/res/res/layout/screen_xlarge_action_bar.xml diff --git a/api/current.xml b/api/current.xml index a7e6c526d3da..850073e47964 100644 --- a/api/current.xml +++ b/api/current.xml @@ -2088,55 +2088,55 @@ visibility="public" > - - - - - + + + + + + - - - - + + mCustomView; - public ContextModeImpl(ActionMode.Callback callback) { + public ActionModeImpl(ActionMode.Callback callback) { mCallback = callback; mMenu = new MenuBuilder(mActionView.getContext()); mMenu.setCallback(this); @@ -379,8 +379,8 @@ public class ActionBarImpl extends ActionBar { @Override public void finish() { - if (mContextMode != this) { - // Not the active context mode - no-op + if (mActionMode != this) { + // Not the active action mode - no-op return; } @@ -395,7 +395,7 @@ public class ActionBarImpl extends ActionBar { // TODO Animate this mLowerContextView.setVisibility(View.GONE); } - mContextMode = null; + mActionMode = null; } @Override diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java new file mode 100644 index 000000000000..13eda1035fd6 --- /dev/null +++ b/core/java/com/android/internal/view/StandaloneActionMode.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2010 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.internal.view; + +import com.android.internal.view.menu.MenuBuilder; +import com.android.internal.view.menu.MenuPopupHelper; +import com.android.internal.view.menu.SubMenuBuilder; +import com.android.internal.widget.ActionBarContextView; + +import android.content.Context; +import android.view.ActionMode; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +import java.lang.ref.WeakReference; + +public class StandaloneActionMode extends ActionMode implements MenuBuilder.Callback { + private Context mContext; + private ActionBarContextView mContextView; + private ActionMode.Callback mCallback; + private WeakReference mCustomView; + private boolean mFinished; + + private MenuBuilder mMenu; + + public StandaloneActionMode(Context context, ActionBarContextView view, + ActionMode.Callback callback) { + mContext = context; + mContextView = view; + mCallback = callback; + + mMenu = new MenuBuilder(context); + mMenu.setCallback(this); + } + + @Override + public void setTitle(CharSequence title) { + mContextView.setTitle(title); + } + + @Override + public void setSubtitle(CharSequence subtitle) { + mContextView.setSubtitle(subtitle); + } + + @Override + public void setCustomView(View view) { + mContextView.setCustomView(view); + mCustomView = view != null ? new WeakReference(view) : null; + } + + @Override + public void invalidate() { + mCallback.onPrepareActionMode(this, mMenu); + } + + @Override + public void finish() { + if (mFinished) { + return; + } + mFinished = true; + + mCallback.onDestroyActionMode(this); + mContextView.setVisibility(View.GONE); + } + + @Override + public Menu getMenu() { + return mMenu; + } + + @Override + public CharSequence getTitle() { + return mContextView.getTitle(); + } + + @Override + public CharSequence getSubtitle() { + return mContextView.getSubtitle(); + } + + @Override + public View getCustomView() { + return mCustomView != null ? mCustomView.get() : null; + } + + public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { + return mCallback.onActionItemClicked(this, item); + } + + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + } + + public boolean onSubMenuSelected(SubMenuBuilder subMenu) { + if (!subMenu.hasVisibleItems()) { + return true; + } + + new MenuPopupHelper(mContext, subMenu).show(); + return true; + } + + public void onCloseSubMenu(SubMenuBuilder menu) { + } + + public void onMenuModeChange(MenuBuilder menu) { + } +} diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index a185e2123164..0bedc4e0ce1f 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -70,9 +70,9 @@ public class ActionBarContextView extends ViewGroup { mItemPadding = a.getDimensionPixelOffset( com.android.internal.R.styleable.Theme_actionButtonPadding, 0); setBackgroundDrawable(a.getDrawable( - com.android.internal.R.styleable.Theme_actionBarContextBackground)); + com.android.internal.R.styleable.Theme_actionModeBackground)); mCloseDrawable = a.getDrawable( - com.android.internal.R.styleable.Theme_actionBarCloseContextDrawable); + com.android.internal.R.styleable.Theme_actionModeCloseDrawable); mItemMargin = mItemPadding / 2; mContentHeight = diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml new file mode 100644 index 000000000000..41ce8e467490 --- /dev/null +++ b/core/res/res/layout-xlarge/screen_action_bar.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + diff --git a/core/res/res/layout/screen.xml b/core/res/res/layout/screen.xml index dfa973198047..0269bf1aaa6f 100644 --- a/core/res/res/layout/screen.xml +++ b/core/res/res/layout/screen.xml @@ -25,6 +25,13 @@ This is the basic layout for a screen, with all of its features enabled. android:layout_width="match_parent" android:layout_height="match_parent" > + + + + + + + + + + + + + - - - - - - - - - - - diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 4edd96459668..d1024fe58bab 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -251,6 +251,10 @@ + + + @@ -444,8 +448,15 @@ - - + + + + + + + + + @@ -987,6 +998,7 @@ + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 34dd46c57f4d..f1ff3a3b7cf3 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1306,8 +1306,9 @@ - - + + + diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index bce0e02f67bb..998480d835b5 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -206,8 +206,8 @@ 12dip - @android:drawable/action_bar_context_background - @android:drawable/ic_menu_close_clear_cancel + @android:drawable/action_bar_context_background + @android:drawable/ic_menu_close_clear_cancel diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 2976e3eeda89..458ac9deb7d4 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -24,12 +24,14 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; +import com.android.internal.view.StandaloneActionMode; import com.android.internal.view.menu.ContextMenuBuilder; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuDialogHelper; import com.android.internal.view.menu.MenuPopupHelper; import com.android.internal.view.menu.MenuView; import com.android.internal.view.menu.SubMenuBuilder; +import com.android.internal.widget.ActionBarContextView; import com.android.internal.widget.ActionBarView; import android.app.KeyguardManager; @@ -1638,6 +1640,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private boolean mWatchingForMenu; private int mDownY; + private ActionMode mActionMode; + private ActionBarContextView mActionModeView; + public DecorView(Context context, int featureId) { super(context); mFeatureId = featureId; @@ -1935,7 +1940,33 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public ActionMode startActionMode(ActionMode.Callback callback) { - return getCallback().onStartActionMode(callback); + if (mActionMode != null) { + mActionMode.finish(); + } + + ActionMode mode = getCallback().onStartActionMode(callback); + if (mode != null) { + mActionMode = mode; + } else { + if (mActionModeView == null) { + mActionModeView = (ActionBarContextView) findViewById( + com.android.internal.R.id.action_mode_bar); + } + + if (mActionModeView != null) { + mode = new StandaloneActionMode(getContext(), mActionModeView, + new ActionModeCallbackWrapper(callback)); + if (callback.onCreateActionMode(mode, mode.getMenu())) { + mode.invalidate(); + mActionModeView.initForMode(mode); + mActionModeView.setVisibility(View.VISIBLE); + mActionMode = mode; + } else { + mActionMode = null; + } + } + } + return mActionMode; } public void startChanging() { @@ -2117,6 +2148,35 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (keepOn) PhoneWindow.this.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); else PhoneWindow.this.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } + + /** + * Clears out internal reference when the action mode is destroyed. + */ + private class ActionModeCallbackWrapper implements ActionMode.Callback { + private ActionMode.Callback mWrapped; + + public ActionModeCallbackWrapper(ActionMode.Callback wrapped) { + mWrapped = wrapped; + } + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + return mWrapped.onCreateActionMode(mode, menu); + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return mWrapped.onPrepareActionMode(mode, menu); + } + + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + return mWrapped.onActionItemClicked(mode, item); + } + + public void onDestroyActionMode(ActionMode mode) { + mWrapped.onDestroyActionMode(mode); + mActionModeView.removeAllViews(); + mActionMode = null; + } + } } protected DecorView generateDecor() { @@ -2170,6 +2230,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { requestFeature(FEATURE_ACTION_BAR); } + if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionModeOverlay, false)) { + requestFeature(FEATURE_ACTION_MODE_OVERLAY); + } + if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) { setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN&(~getForcedWindowFlags())); } @@ -2252,13 +2316,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (mIsFloating) { layoutResource = com.android.internal.R.layout.dialog_title; } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) { - Configuration config = getContext().getResources().getConfiguration(); - if ((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_XLARGE) == - Configuration.SCREENLAYOUT_SIZE_XLARGE) { - layoutResource = com.android.internal.R.layout.screen_xlarge_action_bar; - } else { - layoutResource = com.android.internal.R.layout.screen_action_bar; - } + layoutResource = com.android.internal.R.layout.screen_action_bar; } else { layoutResource = com.android.internal.R.layout.screen_title; } -- cgit v1.2.3-59-g8ed1b