diff options
4 files changed, 278 insertions, 67 deletions
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java index ca8a68a..c1498ec 100644 --- a/core/java/android/view/PhoneWindow.java +++ b/core/java/android/view/PhoneWindow.java @@ -25,7 +25,9 @@ import static android.view.WindowManager.LayoutParams.*; import android.app.ActivityManagerNative; import android.app.SearchManager; import android.os.UserHandle; + import com.android.internal.R; +import com.android.internal.view.ActionModeWrapper; import com.android.internal.view.RootViewSurfaceTaker; import com.android.internal.view.StandaloneActionMode; import com.android.internal.view.menu.ContextMenuBuilder; @@ -2689,72 +2691,78 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (mode != null) { mActionMode = mode; } else { - if (mActionModeView == null) { - if (isFloating()) { - // Use the action bar theme. - final TypedValue outValue = new TypedValue(); - final Theme baseTheme = mContext.getTheme(); - baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true); - - final Context actionBarContext; - if (outValue.resourceId != 0) { - final Theme actionBarTheme = mContext.getResources().newTheme(); - actionBarTheme.setTo(baseTheme); - actionBarTheme.applyStyle(outValue.resourceId, true); - - actionBarContext = new ContextThemeWrapper(mContext, 0); - actionBarContext.getTheme().setTo(actionBarTheme); - } else { - actionBarContext = mContext; - } + if (mActionModeView != null) { + mActionModeView.killMode(); + } + ActionModeWrapper wrapperMode = + new ActionModeWrapper(mContext, wrappedCallback); + if (callback.onCreateActionMode(wrapperMode, wrapperMode.getMenu())) { + if (wrapperMode.getType() == ActionMode.TYPE_PRIMARY) { + if (mActionModeView == null) { + if (isFloating()) { + // Use the action bar theme. + final TypedValue outValue = new TypedValue(); + final Theme baseTheme = mContext.getTheme(); + baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true); + + final Context actionBarContext; + if (outValue.resourceId != 0) { + final Theme actionBarTheme = mContext.getResources().newTheme(); + actionBarTheme.setTo(baseTheme); + actionBarTheme.applyStyle(outValue.resourceId, true); + + actionBarContext = new ContextThemeWrapper(mContext, 0); + actionBarContext.getTheme().setTo(actionBarTheme); + } else { + actionBarContext = mContext; + } - mActionModeView = new ActionBarContextView(actionBarContext); - mActionModePopup = new PopupWindow(actionBarContext, null, - R.attr.actionModePopupWindowStyle); - mActionModePopup.setWindowLayoutType( - WindowManager.LayoutParams.TYPE_APPLICATION); - mActionModePopup.setContentView(mActionModeView); - mActionModePopup.setWidth(MATCH_PARENT); - - actionBarContext.getTheme().resolveAttribute( - R.attr.actionBarSize, outValue, true); - final int height = TypedValue.complexToDimensionPixelSize(outValue.data, - actionBarContext.getResources().getDisplayMetrics()); - mActionModeView.setContentHeight(height); - mActionModePopup.setHeight(WRAP_CONTENT); - mShowActionModePopup = new Runnable() { - public void run() { - mActionModePopup.showAtLocation( - mActionModeView.getApplicationWindowToken(), - Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); + mActionModeView = new ActionBarContextView(actionBarContext); + mActionModePopup = new PopupWindow(actionBarContext, null, + R.attr.actionModePopupWindowStyle); + mActionModePopup.setWindowLayoutType( + WindowManager.LayoutParams.TYPE_APPLICATION); + mActionModePopup.setContentView(mActionModeView); + mActionModePopup.setWidth(MATCH_PARENT); + + actionBarContext.getTheme().resolveAttribute( + R.attr.actionBarSize, outValue, true); + final int height = TypedValue.complexToDimensionPixelSize(outValue.data, + actionBarContext.getResources().getDisplayMetrics()); + mActionModeView.setContentHeight(height); + mActionModePopup.setHeight(WRAP_CONTENT); + mShowActionModePopup = new Runnable() { + public void run() { + mActionModePopup.showAtLocation( + mActionModeView.getApplicationWindowToken(), + Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); + } + }; + } else { + ViewStub stub = (ViewStub) findViewById( + R.id.action_mode_bar_stub); + if (stub != null) { + mActionModeView = (ActionBarContextView) stub.inflate(); + } } - }; - } else { - ViewStub stub = (ViewStub) findViewById( - R.id.action_mode_bar_stub); - if (stub != null) { - mActionModeView = (ActionBarContextView) stub.inflate(); } - } - } - - if (mActionModeView != null) { - mActionModeView.killMode(); - mode = new StandaloneActionMode(mActionModeView.getContext(), mActionModeView, - wrappedCallback, mActionModePopup == null); - if (callback.onCreateActionMode(mode, mode.getMenu())) { - mode.invalidate(); - mActionModeView.initForMode(mode); - mActionModeView.setVisibility(View.VISIBLE); - mActionMode = mode; - if (mActionModePopup != null) { - post(mShowActionModePopup); + if (mActionModeView != null) { + wrapperMode.setActionModeView(mActionModeView); + wrapperMode.setFocusable(mActionModePopup == null); + wrapperMode.lockType(); + wrapperMode.invalidate(); + mActionModeView.initForMode(wrapperMode); + mActionModeView.setVisibility(View.VISIBLE); + mActionMode = wrapperMode; + if (mActionModePopup != null) { + post(mShowActionModePopup); + } + mActionModeView.sendAccessibilityEvent( + AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } - mActionModeView.sendAccessibilityEvent( - AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); - } else { - mActionMode = null; } + } else { + mActionMode = null; } } if (mActionMode != null && getCallback() != null && !isDestroyed()) { diff --git a/core/java/com/android/internal/view/ActionModeWrapper.java b/core/java/com/android/internal/view/ActionModeWrapper.java new file mode 100644 index 0000000..ef1981a --- /dev/null +++ b/core/java/com/android/internal/view/ActionModeWrapper.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2015 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 android.content.Context; +import android.view.ActionMode; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; + +import com.android.internal.view.menu.MenuBuilder; +import com.android.internal.widget.ActionBarContextView; + +/** + * ActionMode implementation that wraps several actions modes and creates them on the fly depending + * on the ActionMode type chosen by the client. + */ +public class ActionModeWrapper extends ActionMode { + + private ActionMode mActionMode; + private final Context mContext; + private MenuBuilder mMenu; + private final ActionMode.Callback mCallback; + private boolean mTypeLocked = false; + + private CharSequence mTitle; + private CharSequence mSubtitle; + private View mCustomView; + + // Fields for StandaloneActionMode + private ActionBarContextView mActionModeView; + private boolean mIsFocusable; + + public ActionModeWrapper(Context context, ActionMode.Callback callback) { + mContext = context; + mMenu = new MenuBuilder(context).setDefaultShowAsAction( + MenuItem.SHOW_AS_ACTION_IF_ROOM); + mCallback = callback; + } + + @Override + public void setTitle(CharSequence title) { + if (mActionMode != null) { + mActionMode.setTitle(title); + } else { + mTitle = title; + } + } + + @Override + public void setTitle(int resId) { + if (mActionMode != null) { + mActionMode.setTitle(resId); + } else { + mTitle = resId != 0 ? mContext.getString(resId) : null; + } + } + + @Override + public void setSubtitle(CharSequence subtitle) { + if (mActionMode != null) { + mActionMode.setSubtitle(subtitle); + } else { + mSubtitle = subtitle; + } + } + + @Override + public void setSubtitle(int resId) { + if (mActionMode != null) { + mActionMode.setSubtitle(resId); + } else { + mSubtitle = resId != 0 ? mContext.getString(resId) : null; + } + } + + @Override + public void setCustomView(View view) { + if (mActionMode != null) { + mActionMode.setCustomView(view); + } else { + mCustomView = view; + } + } + + /** + * Set the current type as final and create the necessary ActionMode. After this call, any + * changes to the ActionMode type will be ignored. + */ + public void lockType() { + mTypeLocked = true; + switch (getType()) { + case ActionMode.TYPE_PRIMARY: + default: + mActionMode = new StandaloneActionMode( + mActionModeView.getContext(), + mActionModeView, mCallback, mIsFocusable, mMenu); + break; + case ActionMode.TYPE_FLOATING: + // Not implemented yet. + break; + } + + if (mActionMode == null) { + return; + } + + mActionMode.setTitle(mTitle); + mActionMode.setSubtitle(mSubtitle); + if (mCustomView != null) { + mActionMode.setCustomView(mCustomView); + } + + mTitle = null; + mSubtitle = null; + mCustomView = null; + } + + @Override + public void setType(int type) { + if (!mTypeLocked) { + super.setType(type); + } else { + throw new IllegalStateException( + "You can't change the ActionMode's type after onCreateActionMode."); + } + } + + @Override + public void invalidate() { + if (mActionMode != null) { + mActionMode.invalidate(); + } + } + + @Override + public void finish() { + if (mActionMode != null) { + mActionMode.finish(); + } + } + + @Override + public Menu getMenu() { + return mMenu; + } + + @Override + public CharSequence getTitle() { + if (mActionMode != null) { + return mActionMode.getTitle(); + } + return mTitle; + } + + @Override + public CharSequence getSubtitle() { + if (mActionMode != null) { + return mActionMode.getSubtitle(); + } + return mSubtitle; + } + + @Override + public View getCustomView() { + if (mActionMode != null) { + return mActionMode.getCustomView(); + } + return mCustomView; + } + + @Override + public MenuInflater getMenuInflater() { + return new MenuInflater(mContext); + } + + public void setActionModeView(ActionBarContextView actionModeView) { + mActionModeView = actionModeView; + } + + public void setFocusable(boolean focusable) { + mIsFocusable = focusable; + } + +} diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java index d5d3602..2812b77 100644 --- a/core/java/com/android/internal/view/StandaloneActionMode.java +++ b/core/java/com/android/internal/view/StandaloneActionMode.java @@ -20,6 +20,7 @@ import com.android.internal.view.menu.MenuPopupHelper; import com.android.internal.view.menu.SubMenuBuilder; import com.android.internal.widget.ActionBarContextView; +import android.annotation.Nullable; import android.content.Context; import android.view.ActionMode; import android.view.Menu; @@ -41,13 +42,15 @@ public class StandaloneActionMode extends ActionMode implements MenuBuilder.Call private MenuBuilder mMenu; public StandaloneActionMode(Context context, ActionBarContextView view, - ActionMode.Callback callback, boolean isFocusable) { + ActionMode.Callback callback, boolean isFocusable, @Nullable MenuBuilder menuBuilder) { mContext = context; mContextView = view; mCallback = callback; - mMenu = new MenuBuilder(view.getContext()).setDefaultShowAsAction( - MenuItem.SHOW_AS_ACTION_IF_ROOM); + mMenu = (menuBuilder != null) + ? menuBuilder + : new MenuBuilder(view.getContext()).setDefaultShowAsAction( + MenuItem.SHOW_AS_ACTION_IF_ROOM); mMenu.setCallback(this); mFocusable = isFocusable; } @@ -64,12 +67,12 @@ public class StandaloneActionMode extends ActionMode implements MenuBuilder.Call @Override public void setTitle(int resId) { - setTitle(mContext.getString(resId)); + setTitle(resId != 0 ? mContext.getString(resId) : null); } @Override public void setSubtitle(int resId) { - setSubtitle(mContext.getString(resId)); + setSubtitle(resId != 0 ? mContext.getString(resId) : null); } @Override diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 5d3f464..ae5999a 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -158,7 +158,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi removeView(mCustomView); } mCustomView = view; - if (mTitleLayout != null) { + if (view != null && mTitleLayout != null) { removeView(mTitleLayout); mTitleLayout = null; } |