Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2015 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.internal.view; |
| 18 | |
Abodunrinwa Toki | 17293cc | 2017-05-22 14:16:04 +0100 | [diff] [blame] | 19 | import android.annotation.NonNull; |
Abodunrinwa Toki | 29cb768 | 2018-04-11 21:24:20 +0100 | [diff] [blame] | 20 | import android.annotation.Nullable; |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 21 | import android.content.Context; |
Abodunrinwa Toki | 49f1a76 | 2016-08-03 20:07:15 -0700 | [diff] [blame] | 22 | import android.graphics.Point; |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 23 | import android.graphics.Rect; |
| 24 | import android.view.ActionMode; |
| 25 | import android.view.Menu; |
| 26 | import android.view.MenuInflater; |
| 27 | import android.view.MenuItem; |
| 28 | import android.view.View; |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 29 | import android.view.ViewConfiguration; |
Justin Klaassen | 6183b72 | 2016-04-26 20:19:07 -0700 | [diff] [blame] | 30 | import android.view.ViewGroup; |
| 31 | import android.view.ViewParent; |
Abodunrinwa Toki | 49f1a76 | 2016-08-03 20:07:15 -0700 | [diff] [blame] | 32 | import android.view.WindowManager; |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 33 | |
Abodunrinwa Toki | 29cb768 | 2018-04-11 21:24:20 +0100 | [diff] [blame] | 34 | import android.widget.PopupWindow; |
Abodunrinwa Toki | 15a6c89 | 2015-06-16 23:17:19 +0100 | [diff] [blame] | 35 | import com.android.internal.R; |
Clara Bayarri | 0d7d4ef | 2015-05-13 15:12:12 +0100 | [diff] [blame] | 36 | import com.android.internal.util.Preconditions; |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 37 | import com.android.internal.view.menu.MenuBuilder; |
| 38 | import com.android.internal.widget.FloatingToolbar; |
| 39 | |
Abodunrinwa Toki | c107b0e | 2015-06-25 21:33:51 -0700 | [diff] [blame] | 40 | import java.util.Arrays; |
| 41 | |
Abodunrinwa Toki | 17293cc | 2017-05-22 14:16:04 +0100 | [diff] [blame] | 42 | public final class FloatingActionMode extends ActionMode { |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 43 | |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 44 | private static final int MAX_HIDE_DURATION = 3000; |
Abodunrinwa Toki | b9acbe4 | 2015-09-16 19:47:38 +0100 | [diff] [blame] | 45 | private static final int MOVING_HIDE_DELAY = 50; |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 46 | |
Abodunrinwa Toki | 17293cc | 2017-05-22 14:16:04 +0100 | [diff] [blame] | 47 | @NonNull private final Context mContext; |
| 48 | @NonNull private final ActionMode.Callback2 mCallback; |
| 49 | @NonNull private final MenuBuilder mMenu; |
| 50 | @NonNull private final Rect mContentRect; |
| 51 | @NonNull private final Rect mContentRectOnScreen; |
| 52 | @NonNull private final Rect mPreviousContentRectOnScreen; |
| 53 | @NonNull private final int[] mViewPositionOnScreen; |
| 54 | @NonNull private final int[] mPreviousViewPositionOnScreen; |
| 55 | @NonNull private final int[] mRootViewPositionOnScreen; |
| 56 | @NonNull private final Rect mViewRectOnScreen; |
| 57 | @NonNull private final Rect mPreviousViewRectOnScreen; |
| 58 | @NonNull private final Rect mScreenRect; |
| 59 | @NonNull private final View mOriginatingView; |
| 60 | @NonNull private final Point mDisplaySize; |
Abodunrinwa Toki | 15a6c89 | 2015-06-16 23:17:19 +0100 | [diff] [blame] | 61 | private final int mBottomAllowance; |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 62 | |
| 63 | private final Runnable mMovingOff = new Runnable() { |
| 64 | public void run() { |
Abodunrinwa Toki | d1eb19c | 2016-07-21 11:10:19 +0100 | [diff] [blame] | 65 | if (isViewStillActive()) { |
| 66 | mFloatingToolbarVisibilityHelper.setMoving(false); |
| 67 | mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); |
| 68 | } |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 69 | } |
| 70 | }; |
| 71 | |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 72 | private final Runnable mHideOff = new Runnable() { |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 73 | public void run() { |
Abodunrinwa Toki | d1eb19c | 2016-07-21 11:10:19 +0100 | [diff] [blame] | 74 | if (isViewStillActive()) { |
| 75 | mFloatingToolbarVisibilityHelper.setHideRequested(false); |
| 76 | mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); |
| 77 | } |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 78 | } |
| 79 | }; |
| 80 | |
Abodunrinwa Toki | 17293cc | 2017-05-22 14:16:04 +0100 | [diff] [blame] | 81 | @NonNull private FloatingToolbar mFloatingToolbar; |
| 82 | @NonNull private FloatingToolbarVisibilityHelper mFloatingToolbarVisibilityHelper; |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 83 | |
| 84 | public FloatingActionMode( |
Abodunrinwa Toki | 17293cc | 2017-05-22 14:16:04 +0100 | [diff] [blame] | 85 | Context context, ActionMode.Callback2 callback, |
| 86 | View originatingView, FloatingToolbar floatingToolbar) { |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 87 | mContext = Preconditions.checkNotNull(context); |
| 88 | mCallback = Preconditions.checkNotNull(callback); |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 89 | mMenu = new MenuBuilder(context).setDefaultShowAsAction( |
| 90 | MenuItem.SHOW_AS_ACTION_IF_ROOM); |
Clara Bayarri | 0d7d4ef | 2015-05-13 15:12:12 +0100 | [diff] [blame] | 91 | setType(ActionMode.TYPE_FLOATING); |
Clara Bayarri | ea2d644 | 2015-09-01 11:26:46 +0100 | [diff] [blame] | 92 | mMenu.setCallback(new MenuBuilder.Callback() { |
| 93 | @Override |
| 94 | public void onMenuModeChange(MenuBuilder menu) {} |
| 95 | |
| 96 | @Override |
| 97 | public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { |
| 98 | return mCallback.onActionItemClicked(FloatingActionMode.this, item); |
| 99 | } |
| 100 | }); |
Clara Bayarri | 0d7d4ef | 2015-05-13 15:12:12 +0100 | [diff] [blame] | 101 | mContentRect = new Rect(); |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 102 | mContentRectOnScreen = new Rect(); |
| 103 | mPreviousContentRectOnScreen = new Rect(); |
| 104 | mViewPositionOnScreen = new int[2]; |
| 105 | mPreviousViewPositionOnScreen = new int[2]; |
| 106 | mRootViewPositionOnScreen = new int[2]; |
| 107 | mViewRectOnScreen = new Rect(); |
| 108 | mPreviousViewRectOnScreen = new Rect(); |
Abodunrinwa Toki | a8151e4 | 2015-05-06 18:57:06 +0100 | [diff] [blame] | 109 | mScreenRect = new Rect(); |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 110 | mOriginatingView = Preconditions.checkNotNull(originatingView); |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 111 | mOriginatingView.getLocationOnScreen(mViewPositionOnScreen); |
Abodunrinwa Toki | 15a6c89 | 2015-06-16 23:17:19 +0100 | [diff] [blame] | 112 | // Allow the content rect to overshoot a little bit beyond the |
| 113 | // bottom view bound if necessary. |
| 114 | mBottomAllowance = context.getResources() |
| 115 | .getDimensionPixelSize(R.dimen.content_rect_bottom_clip_allowance); |
Abodunrinwa Toki | 49f1a76 | 2016-08-03 20:07:15 -0700 | [diff] [blame] | 116 | mDisplaySize = new Point(); |
Abodunrinwa Toki | 17293cc | 2017-05-22 14:16:04 +0100 | [diff] [blame] | 117 | setFloatingToolbar(Preconditions.checkNotNull(floatingToolbar)); |
Clara Bayarri | 0d7d4ef | 2015-05-13 15:12:12 +0100 | [diff] [blame] | 118 | } |
| 119 | |
Abodunrinwa Toki | 17293cc | 2017-05-22 14:16:04 +0100 | [diff] [blame] | 120 | private void setFloatingToolbar(FloatingToolbar floatingToolbar) { |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 121 | mFloatingToolbar = floatingToolbar |
| 122 | .setMenu(mMenu) |
Abodunrinwa Toki | 17293cc | 2017-05-22 14:16:04 +0100 | [diff] [blame] | 123 | .setOnMenuItemClickListener(item -> mMenu.performItemAction(item, 0)); |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 124 | mFloatingToolbarVisibilityHelper = new FloatingToolbarVisibilityHelper(mFloatingToolbar); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 125 | mFloatingToolbarVisibilityHelper.activate(); |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | @Override |
| 129 | public void setTitle(CharSequence title) {} |
| 130 | |
| 131 | @Override |
| 132 | public void setTitle(int resId) {} |
| 133 | |
| 134 | @Override |
| 135 | public void setSubtitle(CharSequence subtitle) {} |
| 136 | |
| 137 | @Override |
| 138 | public void setSubtitle(int resId) {} |
| 139 | |
| 140 | @Override |
| 141 | public void setCustomView(View view) {} |
| 142 | |
| 143 | @Override |
| 144 | public void invalidate() { |
| 145 | mCallback.onPrepareActionMode(this, mMenu); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 146 | invalidateContentRect(); // Will re-layout and show the toolbar if necessary. |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 147 | } |
| 148 | |
| 149 | @Override |
| 150 | public void invalidateContentRect() { |
| 151 | mCallback.onGetContentRect(this, mOriginatingView, mContentRect); |
| 152 | repositionToolbar(); |
| 153 | } |
| 154 | |
| 155 | public void updateViewLocationInWindow() { |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 156 | mOriginatingView.getLocationOnScreen(mViewPositionOnScreen); |
| 157 | mOriginatingView.getRootView().getLocationOnScreen(mRootViewPositionOnScreen); |
| 158 | mOriginatingView.getGlobalVisibleRect(mViewRectOnScreen); |
| 159 | mViewRectOnScreen.offset(mRootViewPositionOnScreen[0], mRootViewPositionOnScreen[1]); |
Abodunrinwa Toki | c107b0e | 2015-06-25 21:33:51 -0700 | [diff] [blame] | 160 | |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 161 | if (!Arrays.equals(mViewPositionOnScreen, mPreviousViewPositionOnScreen) |
| 162 | || !mViewRectOnScreen.equals(mPreviousViewRectOnScreen)) { |
Abodunrinwa Toki | c107b0e | 2015-06-25 21:33:51 -0700 | [diff] [blame] | 163 | repositionToolbar(); |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 164 | mPreviousViewPositionOnScreen[0] = mViewPositionOnScreen[0]; |
| 165 | mPreviousViewPositionOnScreen[1] = mViewPositionOnScreen[1]; |
| 166 | mPreviousViewRectOnScreen.set(mViewRectOnScreen); |
Abodunrinwa Toki | c107b0e | 2015-06-25 21:33:51 -0700 | [diff] [blame] | 167 | } |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 168 | } |
| 169 | |
| 170 | private void repositionToolbar() { |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 171 | mContentRectOnScreen.set(mContentRect); |
Justin Klaassen | 6183b72 | 2016-04-26 20:19:07 -0700 | [diff] [blame] | 172 | |
| 173 | // Offset the content rect into screen coordinates, taking into account any transformations |
| 174 | // that may be applied to the originating view or its ancestors. |
| 175 | final ViewParent parent = mOriginatingView.getParent(); |
| 176 | if (parent instanceof ViewGroup) { |
| 177 | ((ViewGroup) parent).getChildVisibleRect( |
Abodunrinwa Toki | 4e7a120 | 2016-05-03 18:23:12 +0100 | [diff] [blame] | 178 | mOriginatingView, mContentRectOnScreen, |
| 179 | null /* offset */, true /* forceParentCheck */); |
Justin Klaassen | 6183b72 | 2016-04-26 20:19:07 -0700 | [diff] [blame] | 180 | mContentRectOnScreen.offset(mRootViewPositionOnScreen[0], mRootViewPositionOnScreen[1]); |
| 181 | } else { |
| 182 | mContentRectOnScreen.offset(mViewPositionOnScreen[0], mViewPositionOnScreen[1]); |
| 183 | } |
Abodunrinwa Toki | a8151e4 | 2015-05-06 18:57:06 +0100 | [diff] [blame] | 184 | |
| 185 | if (isContentRectWithinBounds()) { |
| 186 | mFloatingToolbarVisibilityHelper.setOutOfBounds(false); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 187 | // Make sure that content rect is not out of the view's visible bounds. |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 188 | mContentRectOnScreen.set( |
| 189 | Math.max(mContentRectOnScreen.left, mViewRectOnScreen.left), |
| 190 | Math.max(mContentRectOnScreen.top, mViewRectOnScreen.top), |
| 191 | Math.min(mContentRectOnScreen.right, mViewRectOnScreen.right), |
| 192 | Math.min(mContentRectOnScreen.bottom, |
| 193 | mViewRectOnScreen.bottom + mBottomAllowance)); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 194 | |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 195 | if (!mContentRectOnScreen.equals(mPreviousContentRectOnScreen)) { |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 196 | // Content rect is moving. |
| 197 | mOriginatingView.removeCallbacks(mMovingOff); |
| 198 | mFloatingToolbarVisibilityHelper.setMoving(true); |
| 199 | mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY); |
| 200 | |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 201 | mFloatingToolbar.setContentRect(mContentRectOnScreen); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 202 | mFloatingToolbar.updateLayout(); |
| 203 | } |
Abodunrinwa Toki | a8151e4 | 2015-05-06 18:57:06 +0100 | [diff] [blame] | 204 | } else { |
| 205 | mFloatingToolbarVisibilityHelper.setOutOfBounds(true); |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 206 | mContentRectOnScreen.setEmpty(); |
Abodunrinwa Toki | a8151e4 | 2015-05-06 18:57:06 +0100 | [diff] [blame] | 207 | } |
Abodunrinwa Toki | b9acbe4 | 2015-09-16 19:47:38 +0100 | [diff] [blame] | 208 | mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 209 | |
Yohei Yukawa | bafc908 | 2015-07-14 05:59:05 -0700 | [diff] [blame] | 210 | mPreviousContentRectOnScreen.set(mContentRectOnScreen); |
Abodunrinwa Toki | a8151e4 | 2015-05-06 18:57:06 +0100 | [diff] [blame] | 211 | } |
| 212 | |
| 213 | private boolean isContentRectWithinBounds() { |
Abodunrinwa Toki | 49f1a76 | 2016-08-03 20:07:15 -0700 | [diff] [blame] | 214 | mContext.getSystemService(WindowManager.class) |
| 215 | .getDefaultDisplay().getRealSize(mDisplaySize); |
| 216 | mScreenRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); |
Abodunrinwa Toki | a8151e4 | 2015-05-06 18:57:06 +0100 | [diff] [blame] | 217 | |
Clara Bayarri | f95ed10 | 2015-08-12 19:46:47 +0100 | [diff] [blame] | 218 | return intersectsClosed(mContentRectOnScreen, mScreenRect) |
| 219 | && intersectsClosed(mContentRectOnScreen, mViewRectOnScreen); |
| 220 | } |
| 221 | |
| 222 | /* |
| 223 | * Same as Rect.intersects, but includes cases where the rectangles touch. |
| 224 | */ |
| 225 | private static boolean intersectsClosed(Rect a, Rect b) { |
| 226 | return a.left <= b.right && b.left <= a.right |
| 227 | && a.top <= b.bottom && b.top <= a.bottom; |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 228 | } |
| 229 | |
| 230 | @Override |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 231 | public void hide(long duration) { |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 232 | if (duration == ActionMode.DEFAULT_HIDE_DURATION) { |
| 233 | duration = ViewConfiguration.getDefaultActionModeHideDuration(); |
| 234 | } |
| 235 | duration = Math.min(MAX_HIDE_DURATION, duration); |
| 236 | mOriginatingView.removeCallbacks(mHideOff); |
| 237 | if (duration <= 0) { |
| 238 | mHideOff.run(); |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 239 | } else { |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 240 | mFloatingToolbarVisibilityHelper.setHideRequested(true); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 241 | mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 242 | mOriginatingView.postDelayed(mHideOff, duration); |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 243 | } |
| 244 | } |
| 245 | |
Abodunrinwa Toki | 29cb768 | 2018-04-11 21:24:20 +0100 | [diff] [blame] | 246 | /** |
| 247 | * If this is set to true, the action mode view will dismiss itself on touch events outside of |
| 248 | * its window. This only makes sense if the action mode view is a PopupWindow that is touchable |
| 249 | * but not focusable, which means touches outside of the window will be delivered to the window |
| 250 | * behind. The default is false. |
| 251 | * |
| 252 | * This is for internal use only and the approach to this may change. |
| 253 | * @hide |
| 254 | * |
| 255 | * @param outsideTouchable whether or not this action mode is "outside touchable" |
| 256 | * @param onDismiss optional. Sets a callback for when this action mode popup dismisses itself |
| 257 | */ |
| 258 | public void setOutsideTouchable( |
| 259 | boolean outsideTouchable, @Nullable PopupWindow.OnDismissListener onDismiss) { |
| 260 | mFloatingToolbar.setOutsideTouchable(outsideTouchable, onDismiss); |
| 261 | } |
| 262 | |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 263 | @Override |
Abodunrinwa Toki | 972ab4f | 2015-06-17 18:04:23 +0100 | [diff] [blame] | 264 | public void onWindowFocusChanged(boolean hasWindowFocus) { |
Abodunrinwa Toki | 972ab4f | 2015-06-17 18:04:23 +0100 | [diff] [blame] | 265 | mFloatingToolbarVisibilityHelper.setWindowFocused(hasWindowFocus); |
| 266 | mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); |
| 267 | } |
| 268 | |
| 269 | @Override |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 270 | public void finish() { |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 271 | reset(); |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 272 | mCallback.onDestroyActionMode(this); |
| 273 | } |
| 274 | |
| 275 | @Override |
| 276 | public Menu getMenu() { |
| 277 | return mMenu; |
| 278 | } |
| 279 | |
| 280 | @Override |
| 281 | public CharSequence getTitle() { |
| 282 | return null; |
| 283 | } |
| 284 | |
| 285 | @Override |
| 286 | public CharSequence getSubtitle() { |
| 287 | return null; |
| 288 | } |
| 289 | |
| 290 | @Override |
| 291 | public View getCustomView() { |
| 292 | return null; |
| 293 | } |
| 294 | |
| 295 | @Override |
| 296 | public MenuInflater getMenuInflater() { |
| 297 | return new MenuInflater(mContext); |
| 298 | } |
| 299 | |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 300 | private void reset() { |
Abodunrinwa Toki | 972ab4f | 2015-06-17 18:04:23 +0100 | [diff] [blame] | 301 | mFloatingToolbar.dismiss(); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 302 | mFloatingToolbarVisibilityHelper.deactivate(); |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 303 | mOriginatingView.removeCallbacks(mMovingOff); |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 304 | mOriginatingView.removeCallbacks(mHideOff); |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 305 | } |
| 306 | |
Abodunrinwa Toki | d1eb19c | 2016-07-21 11:10:19 +0100 | [diff] [blame] | 307 | private boolean isViewStillActive() { |
| 308 | return mOriginatingView.getWindowVisibility() == View.VISIBLE |
| 309 | && mOriginatingView.isShown(); |
| 310 | } |
| 311 | |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 312 | /** |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 313 | * A helper for showing/hiding the floating toolbar depending on certain states. |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 314 | */ |
| 315 | private static final class FloatingToolbarVisibilityHelper { |
| 316 | |
Abodunrinwa Toki | 4a7aeb3 | 2017-07-13 02:06:56 +0100 | [diff] [blame] | 317 | private static final long MIN_SHOW_DURATION_FOR_MOVE_HIDE = 500; |
| 318 | |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 319 | private final FloatingToolbar mToolbar; |
| 320 | |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 321 | private boolean mHideRequested; |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 322 | private boolean mMoving; |
| 323 | private boolean mOutOfBounds; |
Abodunrinwa Toki | 972ab4f | 2015-06-17 18:04:23 +0100 | [diff] [blame] | 324 | private boolean mWindowFocused = true; |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 325 | |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 326 | private boolean mActive; |
| 327 | |
Abodunrinwa Toki | 4a7aeb3 | 2017-07-13 02:06:56 +0100 | [diff] [blame] | 328 | private long mLastShowTime; |
| 329 | |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 330 | public FloatingToolbarVisibilityHelper(FloatingToolbar toolbar) { |
| 331 | mToolbar = Preconditions.checkNotNull(toolbar); |
| 332 | } |
| 333 | |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 334 | public void activate() { |
| 335 | mHideRequested = false; |
| 336 | mMoving = false; |
| 337 | mOutOfBounds = false; |
Abodunrinwa Toki | 972ab4f | 2015-06-17 18:04:23 +0100 | [diff] [blame] | 338 | mWindowFocused = true; |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 339 | |
| 340 | mActive = true; |
| 341 | } |
| 342 | |
| 343 | public void deactivate() { |
| 344 | mActive = false; |
| 345 | mToolbar.dismiss(); |
| 346 | } |
| 347 | |
Abodunrinwa Toki | 9e21128 | 2015-06-05 02:46:57 +0100 | [diff] [blame] | 348 | public void setHideRequested(boolean hide) { |
| 349 | mHideRequested = hide; |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 350 | } |
| 351 | |
| 352 | public void setMoving(boolean moving) { |
Abodunrinwa Toki | 4a7aeb3 | 2017-07-13 02:06:56 +0100 | [diff] [blame] | 353 | // Avoid unintended flickering by allowing the toolbar to show long enough before |
| 354 | // triggering the 'moving' flag - which signals a hide. |
| 355 | final boolean showingLongEnough = |
| 356 | System.currentTimeMillis() - mLastShowTime > MIN_SHOW_DURATION_FOR_MOVE_HIDE; |
| 357 | if (!moving || showingLongEnough) { |
| 358 | mMoving = moving; |
| 359 | } |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 360 | } |
| 361 | |
| 362 | public void setOutOfBounds(boolean outOfBounds) { |
| 363 | mOutOfBounds = outOfBounds; |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 364 | } |
| 365 | |
Abodunrinwa Toki | 972ab4f | 2015-06-17 18:04:23 +0100 | [diff] [blame] | 366 | public void setWindowFocused(boolean windowFocused) { |
| 367 | mWindowFocused = windowFocused; |
| 368 | } |
| 369 | |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 370 | public void updateToolbarVisibility() { |
| 371 | if (!mActive) { |
| 372 | return; |
| 373 | } |
| 374 | |
Abodunrinwa Toki | 972ab4f | 2015-06-17 18:04:23 +0100 | [diff] [blame] | 375 | if (mHideRequested || mMoving || mOutOfBounds || !mWindowFocused) { |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 376 | mToolbar.hide(); |
Abodunrinwa Toki | f444b5c | 2015-06-16 15:47:04 +0100 | [diff] [blame] | 377 | } else { |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 378 | mToolbar.show(); |
Abodunrinwa Toki | 4a7aeb3 | 2017-07-13 02:06:56 +0100 | [diff] [blame] | 379 | mLastShowTime = System.currentTimeMillis(); |
Abodunrinwa Toki | fd3a3a1 | 2015-05-05 20:04:34 +0100 | [diff] [blame] | 380 | } |
| 381 | } |
| 382 | } |
Clara Bayarri | 838e36c | 2015-03-17 23:10:44 +0000 | [diff] [blame] | 383 | } |