Merge "Floating toolbar: Create the FloatingActionMode and use it in DecorView."
This commit is contained in:
committed by
Android (Google) Code Review
commit
2f92e9710a
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
141
core/java/com/android/internal/view/FloatingActionMode.java
Normal file
141
core/java/com/android/internal/view/FloatingActionMode.java
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user