Merge "Floating toolbars: Encapsulate StandaloneActionMode view creation."
This commit is contained in:
committed by
Android (Google) Code Review
commit
6f542f5a40
@@ -2694,73 +2694,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
if (mActionModeView != null) {
|
||||
mActionModeView.killMode();
|
||||
}
|
||||
ActionModeWrapper wrapperMode =
|
||||
new ActionModeWrapper(mContext, wrappedCallback);
|
||||
ActionModeWrapper wrapperMode = new ActionModeWrapper(
|
||||
mContext, wrappedCallback, new StandaloneActionModeProvider());
|
||||
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);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
ViewStub stub = (ViewStub) findViewById(
|
||||
R.id.action_mode_bar_stub);
|
||||
if (stub != null) {
|
||||
mActionModeView = (ActionBarContextView) stub.inflate();
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
mActionMode = wrapperMode;
|
||||
wrapperMode.lockType();
|
||||
mActionMode.invalidate();
|
||||
} else {
|
||||
mActionMode = null;
|
||||
}
|
||||
@@ -3258,6 +3197,82 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
updateColorViewTranslations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates the view creation for {@link StandaloneActionMode}.
|
||||
*/
|
||||
private class StandaloneActionModeProvider
|
||||
implements ActionModeWrapper.ActionModeProvider {
|
||||
|
||||
@Override
|
||||
public ActionMode createActionMode(android.view.ActionMode.Callback callback,
|
||||
MenuBuilder menuBuilder) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
ViewStub stub = (ViewStub) findViewById(
|
||||
R.id.action_mode_bar_stub);
|
||||
if (stub != null) {
|
||||
mActionModeView = (ActionBarContextView) stub.inflate();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mActionModeView != null) {
|
||||
ActionMode mode = new StandaloneActionMode(
|
||||
mActionModeView.getContext(), mActionModeView,
|
||||
callback, mActionModePopup == null, menuBuilder);
|
||||
mActionModeView.killMode();
|
||||
mActionModeView.initForMode(mode);
|
||||
mActionModeView.setVisibility(View.VISIBLE);
|
||||
if (mActionModePopup != null) {
|
||||
post(mShowActionModePopup);
|
||||
}
|
||||
mActionModeView.sendAccessibilityEvent(
|
||||
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
return mode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out internal reference when the action mode is destroyed.
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,6 @@ 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
|
||||
@@ -32,6 +31,22 @@ import com.android.internal.widget.ActionBarContextView;
|
||||
*/
|
||||
public class ActionModeWrapper extends ActionMode {
|
||||
|
||||
/**
|
||||
* Interface to defer the ActionMode creation until the type is chosen.
|
||||
*/
|
||||
public interface ActionModeProvider {
|
||||
/**
|
||||
* Create the desired ActionMode, that will immediately be used as the current active mode
|
||||
* in the decorator.
|
||||
*
|
||||
* @param callback The {@link ActionMode.Callback} to be used.
|
||||
* @param menuBuilder The {@link MenuBuilder} that should be used by the created
|
||||
* {@link ActionMode}. This will already have been populated.
|
||||
* @return A new {@link ActionMode} ready to be used that uses menuBuilder as its menu.
|
||||
*/
|
||||
ActionMode createActionMode(ActionMode.Callback callback, MenuBuilder menuBuilder);
|
||||
}
|
||||
|
||||
private ActionMode mActionMode;
|
||||
private final Context mContext;
|
||||
private MenuBuilder mMenu;
|
||||
@@ -41,16 +56,16 @@ public class ActionModeWrapper extends ActionMode {
|
||||
private CharSequence mTitle;
|
||||
private CharSequence mSubtitle;
|
||||
private View mCustomView;
|
||||
|
||||
private final ActionModeProvider mActionModeProvider;
|
||||
|
||||
// Fields for StandaloneActionMode
|
||||
private ActionBarContextView mActionModeView;
|
||||
private boolean mIsFocusable;
|
||||
|
||||
public ActionModeWrapper(Context context, ActionMode.Callback callback) {
|
||||
public ActionModeWrapper(
|
||||
Context context, ActionMode.Callback callback, ActionModeProvider actionModeProvider) {
|
||||
mContext = context;
|
||||
mMenu = new MenuBuilder(context).setDefaultShowAsAction(
|
||||
MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
mCallback = callback;
|
||||
mActionModeProvider = actionModeProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,9 +122,7 @@ public class ActionModeWrapper extends ActionMode {
|
||||
switch (getType()) {
|
||||
case ActionMode.TYPE_PRIMARY:
|
||||
default:
|
||||
mActionMode = new StandaloneActionMode(
|
||||
mActionModeView.getContext(),
|
||||
mActionModeView, mCallback, mIsFocusable, mMenu);
|
||||
mActionMode = mActionModeProvider.createActionMode(mCallback, mMenu);
|
||||
break;
|
||||
case ActionMode.TYPE_FLOATING:
|
||||
// Not implemented yet.
|
||||
@@ -189,12 +202,4 @@ public class ActionModeWrapper extends ActionMode {
|
||||
return new MenuInflater(mContext);
|
||||
}
|
||||
|
||||
public void setActionModeView(ActionBarContextView actionModeView) {
|
||||
mActionModeView = actionModeView;
|
||||
}
|
||||
|
||||
public void setFocusable(boolean focusable) {
|
||||
mIsFocusable = focusable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user