Loading core/java/android/view/PhoneWindow.java +100 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -2703,20 +2708,20 @@ 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); mode = createActionMode(type, wrappedCallback, originatingView); if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) { setHandledActionMode(mode); } else { mode = null; } } } if (mode != null && getCallback() != null && !isDestroyed()) { try { getCallback().onActionModeStarted(mode); Loading @@ -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; } Loading Loading @@ -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() { Loading Loading @@ -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) { Loading Loading @@ -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. Loading Loading @@ -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. */ Loading Loading @@ -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()) { Loading @@ -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); } } } } Loading core/java/com/android/internal/view/FloatingActionMode.java 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * 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); } } Loading
core/java/android/view/PhoneWindow.java +100 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -2703,20 +2708,20 @@ 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); mode = createActionMode(type, wrappedCallback, originatingView); if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) { setHandledActionMode(mode); } else { mode = null; } } } if (mode != null && getCallback() != null && !isDestroyed()) { try { getCallback().onActionModeStarted(mode); Loading @@ -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; } Loading Loading @@ -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() { Loading Loading @@ -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) { Loading Loading @@ -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. Loading Loading @@ -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. */ Loading Loading @@ -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()) { Loading @@ -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); } } } } Loading
core/java/com/android/internal/view/FloatingActionMode.java 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * 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); } }