summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/PhoneWindow.java109
-rw-r--r--core/java/com/android/internal/view/FloatingActionMode.java141
2 files changed, 241 insertions, 9 deletions
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java
index cb32697..38f4d1c 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/android/view/PhoneWindow.java
@@ -29,6 +29,7 @@ import android.os.UserHandle;
import com.android.internal.R;
import com.android.internal.util.ScreenShapeHelper;
+import com.android.internal.view.FloatingActionMode;
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
import com.android.internal.view.menu.ContextMenuBuilder;
@@ -41,6 +42,7 @@ import com.android.internal.view.menu.MenuView;
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.BackgroundFallback;
import com.android.internal.widget.DecorContentParent;
+import com.android.internal.widget.FloatingToolbar;
import com.android.internal.widget.SwipeDismissLayout;
import android.app.ActivityManager;
@@ -2179,6 +2181,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private ActionBarContextView mPrimaryActionModeView;
private PopupWindow mPrimaryActionModePopup;
private Runnable mShowPrimaryActionModePopup;
+ private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
+ private View mFloatingActionModeOriginatingView;
+ private FloatingToolbar mFloatingToolbar;
// View added at runtime to draw under the status bar area
private View mStatusGuard;
@@ -2703,18 +2708,18 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (mode.getType() == ActionMode.TYPE_PRIMARY) {
cleanupPrimaryActionMode();
mPrimaryActionMode = mode;
- } else {
+ } else if (mode.getType() == ActionMode.TYPE_FLOATING) {
+ if (mFloatingActionMode != null) {
+ mFloatingActionMode.finish();
+ }
mFloatingActionMode = mode;
}
} else {
- if (type == ActionMode.TYPE_PRIMARY) {
- cleanupPrimaryActionMode();
- mode = createStandaloneActionMode(wrappedCallback);
- if (mode != null && callback.onCreateActionMode(mode, mode.getMenu())) {
- setHandledPrimaryActionMode(mode);
- } else {
- mode = null;
- }
+ mode = createActionMode(type, wrappedCallback, originatingView);
+ if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
+ setHandledActionMode(mode);
+ } else {
+ mode = null;
}
}
if (mode != null && getCallback() != null && !isDestroyed()) {
@@ -2737,6 +2742,21 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
+ private void cleanupFloatingActionModeViews() {
+ if (mFloatingToolbar != null) {
+ mFloatingToolbar.dismiss();
+ mFloatingToolbar = null;
+ }
+ if (mFloatingActionModeOriginatingView != null) {
+ if (mFloatingToolbarPreDrawListener != null) {
+ mFloatingActionModeOriginatingView.getViewTreeObserver()
+ .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
+ mFloatingToolbarPreDrawListener = null;
+ }
+ mFloatingActionModeOriginatingView = null;
+ }
+ }
+
public void startChanging() {
mChanging = true;
}
@@ -3128,6 +3148,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (cb != null && !isDestroyed() && mFeatureId < 0) {
cb.onWindowFocusChanged(hasWindowFocus);
}
+
+ if (mFloatingToolbar != null) {
+ if (hasWindowFocus) {
+ mFloatingToolbar.show();
+ } else {
+ mFloatingToolbar.dismiss();
+ }
+ }
}
void updateWindowResizeState() {
@@ -3179,6 +3207,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
mPrimaryActionModePopup = null;
}
+ if (mFloatingToolbar != null) {
+ mFloatingToolbar.dismiss();
+ mFloatingToolbar = null;
+ }
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
if (st != null && st.menu != null && mFeatureId < 0) {
@@ -3220,7 +3252,27 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
updateColorViewTranslations();
}
+ private ActionMode createActionMode(
+ int type, ActionMode.Callback2 callback, View originatingView) {
+ switch (type) {
+ case ActionMode.TYPE_PRIMARY:
+ default:
+ return createStandaloneActionMode(callback);
+ case ActionMode.TYPE_FLOATING:
+ return createFloatingActionMode(originatingView, callback);
+ }
+ }
+
+ private void setHandledActionMode(ActionMode mode) {
+ if (mode.getType() == ActionMode.TYPE_PRIMARY) {
+ setHandledPrimaryActionMode(mode);
+ } else if (mode.getType() == ActionMode.TYPE_FLOATING) {
+ setHandledFloatingActionMode(mode);
+ }
+ }
+
private ActionMode createStandaloneActionMode(ActionMode.Callback callback) {
+ cleanupPrimaryActionMode();
if (mPrimaryActionModeView == null) {
if (isFloating()) {
// Use the action bar theme.
@@ -3291,6 +3343,35 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
+ private ActionMode createFloatingActionMode(
+ View originatingView, ActionMode.Callback2 callback) {
+ if (mFloatingActionMode != null) {
+ mFloatingActionMode.finish();
+ }
+ cleanupFloatingActionModeViews();
+ mFloatingToolbar = new FloatingToolbar(mContext, PhoneWindow.this);
+ final FloatingActionMode mode = new FloatingActionMode(
+ mContext, callback, originatingView, mFloatingToolbar);
+ mFloatingActionModeOriginatingView = originatingView;
+ mFloatingToolbarPreDrawListener =
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mode.updateViewLocationInWindow();
+ return true;
+ }
+ };
+ return mode;
+ }
+
+ private void setHandledFloatingActionMode(ActionMode mode) {
+ mFloatingActionMode = mode;
+ mFloatingActionMode.invalidate();
+ mFloatingToolbar.show();
+ mFloatingActionModeOriginatingView.getViewTreeObserver()
+ .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
+ }
+
/**
* Clears out internal references when the action mode is destroyed.
*/
@@ -3328,6 +3409,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
mPrimaryActionMode = null;
} else if (mode == mFloatingActionMode) {
+ cleanupFloatingActionModeViews();
mFloatingActionMode = null;
}
if (getCallback() != null && !isDestroyed()) {
@@ -3339,6 +3421,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
requestFitSystemWindows();
}
+
+ @Override
+ public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
+ if (mWrapped instanceof ActionMode.Callback2) {
+ ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
+ } else {
+ super.onGetContentRect(mode, view, outRect);
+ }
+ }
}
}
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
new file mode 100644
index 0000000..aacdb34
--- /dev/null
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -0,0 +1,141 @@
+/*
+ * 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.graphics.Rect;
+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.FloatingToolbar;
+
+public class FloatingActionMode extends ActionMode {
+
+ private final Context mContext;
+ private final ActionMode.Callback2 mCallback;
+ private final MenuBuilder mMenu;
+ private final FloatingToolbar mFloatingToolbar;
+ private final Rect mContentRect;
+ private final Rect mContentRectOnWindow;
+ private final Rect mPreviousContentRectOnWindow;
+ private final int[] mViewPosition;
+ private final View mOriginatingView;
+
+ public FloatingActionMode(
+ Context context, ActionMode.Callback2 callback, View originatingView,
+ FloatingToolbar floatingToolbar) {
+ mContext = context;
+ mCallback = callback;
+ mMenu = new MenuBuilder(context).setDefaultShowAsAction(
+ MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ mFloatingToolbar = floatingToolbar
+ .setMenu(mMenu)
+ .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ return mCallback.onActionItemClicked(FloatingActionMode.this, item);
+ }
+ });
+ setType(ActionMode.TYPE_FLOATING);
+ mContentRect = new Rect();
+ mContentRectOnWindow = new Rect();
+ mPreviousContentRectOnWindow = new Rect();
+ mViewPosition = new int[2];
+ mOriginatingView = originatingView;
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {}
+
+ @Override
+ public void setTitle(int resId) {}
+
+ @Override
+ public void setSubtitle(CharSequence subtitle) {}
+
+ @Override
+ public void setSubtitle(int resId) {}
+
+ @Override
+ public void setCustomView(View view) {}
+
+ @Override
+ public void invalidate() {
+ mCallback.onPrepareActionMode(this, mMenu);
+ mFloatingToolbar.updateLayout();
+ invalidateContentRect();
+ }
+
+ @Override
+ public void invalidateContentRect() {
+ mCallback.onGetContentRect(this, mOriginatingView, mContentRect);
+ repositionToolbar();
+ }
+
+ public void updateViewLocationInWindow() {
+ mOriginatingView.getLocationInWindow(mViewPosition);
+ repositionToolbar();
+ }
+
+ private void repositionToolbar() {
+ mContentRectOnWindow.set(
+ mContentRect.left + mViewPosition[0],
+ mContentRect.top + mViewPosition[1],
+ mContentRect.right + mViewPosition[0],
+ mContentRect.bottom + mViewPosition[1]);
+ if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) {
+ mFloatingToolbar.setContentRect(mContentRectOnWindow);
+ mFloatingToolbar.updateLayout();
+ }
+ mPreviousContentRectOnWindow.set(mContentRectOnWindow);
+ }
+
+ @Override
+ public void finish() {
+ mCallback.onDestroyActionMode(this);
+ }
+
+ @Override
+ public Menu getMenu() {
+ return mMenu;
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getSubtitle() {
+ return null;
+ }
+
+ @Override
+ public View getCustomView() {
+ return null;
+ }
+
+ @Override
+ public MenuInflater getMenuInflater() {
+ return new MenuInflater(mContext);
+ }
+
+}