1838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri/* 2838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * Copyright (C) 2015 The Android Open Source Project 3838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * 4838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * Licensed under the Apache License, Version 2.0 (the "License"); 5838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * you may not use this file except in compliance with the License. 6838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * You may obtain a copy of the License at 7838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * 8838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * http://www.apache.org/licenses/LICENSE-2.0 9838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * 10838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * Unless required by applicable law or agreed to in writing, software 11838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * distributed under the License is distributed on an "AS IS" BASIS, 12838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * See the License for the specific language governing permissions and 14838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri * limitations under the License. 15838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri */ 16838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 17838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarripackage com.android.internal.view; 18838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 1917293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Tokiimport android.annotation.NonNull; 20838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport android.content.Context; 2149f1a76a4412ef4e36f1f647fa7ec182e6cf9b58Abodunrinwa Tokiimport android.graphics.Point; 22838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport android.graphics.Rect; 23838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport android.view.ActionMode; 24838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport android.view.Menu; 25838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport android.view.MenuInflater; 26838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport android.view.MenuItem; 27838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport android.view.View; 289e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Tokiimport android.view.ViewConfiguration; 296183b722de89d69ce16890db809a14ac03ab89feJustin Klaassenimport android.view.ViewGroup; 306183b722de89d69ce16890db809a14ac03ab89feJustin Klaassenimport android.view.ViewParent; 3149f1a76a4412ef4e36f1f647fa7ec182e6cf9b58Abodunrinwa Tokiimport android.view.WindowManager; 32838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 3315a6c89f46420371115b1648bd2f3925f4bcf7edAbodunrinwa Tokiimport com.android.internal.R; 340d7d4ef56083543d58ef5835ec594865a547347cClara Bayarriimport com.android.internal.util.Preconditions; 35838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport com.android.internal.view.menu.MenuBuilder; 36838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarriimport com.android.internal.widget.FloatingToolbar; 37838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 38c107b0ecdcd4e2f89ae4bec818c3a94f45c3c15eAbodunrinwa Tokiimport java.util.Arrays; 39c107b0ecdcd4e2f89ae4bec818c3a94f45c3c15eAbodunrinwa Toki 4017293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Tokipublic final class FloatingActionMode extends ActionMode { 41838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 429e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki private static final int MAX_HIDE_DURATION = 3000; 43b9acbe40d298612a2ab6bfb15842e63ff8f09af5Abodunrinwa Toki private static final int MOVING_HIDE_DELAY = 50; 44fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 4517293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final Context mContext; 4617293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final ActionMode.Callback2 mCallback; 4717293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final MenuBuilder mMenu; 4817293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final Rect mContentRect; 4917293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final Rect mContentRectOnScreen; 5017293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final Rect mPreviousContentRectOnScreen; 5117293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final int[] mViewPositionOnScreen; 5217293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final int[] mPreviousViewPositionOnScreen; 5317293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final int[] mRootViewPositionOnScreen; 5417293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final Rect mViewRectOnScreen; 5517293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final Rect mPreviousViewRectOnScreen; 5617293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final Rect mScreenRect; 5717293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final View mOriginatingView; 5817293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private final Point mDisplaySize; 5915a6c89f46420371115b1648bd2f3925f4bcf7edAbodunrinwa Toki private final int mBottomAllowance; 60fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 61fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki private final Runnable mMovingOff = new Runnable() { 62fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki public void run() { 63d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki if (isViewStillActive()) { 64d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki mFloatingToolbarVisibilityHelper.setMoving(false); 65d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); 66d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki } 67fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 68fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki }; 69fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 709e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki private final Runnable mHideOff = new Runnable() { 71fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki public void run() { 72d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki if (isViewStillActive()) { 73d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki mFloatingToolbarVisibilityHelper.setHideRequested(false); 74d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); 75d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki } 76fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 77fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki }; 78fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 7917293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private FloatingToolbar mFloatingToolbar; 8017293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki @NonNull private FloatingToolbarVisibilityHelper mFloatingToolbarVisibilityHelper; 81838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 82838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public FloatingActionMode( 8317293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki Context context, ActionMode.Callback2 callback, 8417293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki View originatingView, FloatingToolbar floatingToolbar) { 85fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mContext = Preconditions.checkNotNull(context); 86fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mCallback = Preconditions.checkNotNull(callback); 87838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri mMenu = new MenuBuilder(context).setDefaultShowAsAction( 88838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri MenuItem.SHOW_AS_ACTION_IF_ROOM); 890d7d4ef56083543d58ef5835ec594865a547347cClara Bayarri setType(ActionMode.TYPE_FLOATING); 90ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri mMenu.setCallback(new MenuBuilder.Callback() { 91ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri @Override 92ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri public void onMenuModeChange(MenuBuilder menu) {} 93ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri 94ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri @Override 95ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 96ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri return mCallback.onActionItemClicked(FloatingActionMode.this, item); 97ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri } 98ea2d64492399f336c996a1af511c7acd2ad0192cClara Bayarri }); 990d7d4ef56083543d58ef5835ec594865a547347cClara Bayarri mContentRect = new Rect(); 100bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mContentRectOnScreen = new Rect(); 101bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mPreviousContentRectOnScreen = new Rect(); 102bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mViewPositionOnScreen = new int[2]; 103bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mPreviousViewPositionOnScreen = new int[2]; 104bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mRootViewPositionOnScreen = new int[2]; 105bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mViewRectOnScreen = new Rect(); 106bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mPreviousViewRectOnScreen = new Rect(); 107a8151e4ef7987faa7d0ee31bc3013a05e5b76a05Abodunrinwa Toki mScreenRect = new Rect(); 108fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mOriginatingView = Preconditions.checkNotNull(originatingView); 109bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mOriginatingView.getLocationOnScreen(mViewPositionOnScreen); 11015a6c89f46420371115b1648bd2f3925f4bcf7edAbodunrinwa Toki // Allow the content rect to overshoot a little bit beyond the 11115a6c89f46420371115b1648bd2f3925f4bcf7edAbodunrinwa Toki // bottom view bound if necessary. 11215a6c89f46420371115b1648bd2f3925f4bcf7edAbodunrinwa Toki mBottomAllowance = context.getResources() 11315a6c89f46420371115b1648bd2f3925f4bcf7edAbodunrinwa Toki .getDimensionPixelSize(R.dimen.content_rect_bottom_clip_allowance); 11449f1a76a4412ef4e36f1f647fa7ec182e6cf9b58Abodunrinwa Toki mDisplaySize = new Point(); 11517293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki setFloatingToolbar(Preconditions.checkNotNull(floatingToolbar)); 1160d7d4ef56083543d58ef5835ec594865a547347cClara Bayarri } 1170d7d4ef56083543d58ef5835ec594865a547347cClara Bayarri 11817293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki private void setFloatingToolbar(FloatingToolbar floatingToolbar) { 119838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri mFloatingToolbar = floatingToolbar 120838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri .setMenu(mMenu) 12117293cc8a214e3ad1e86dd0a4999fa86063bf70fAbodunrinwa Toki .setOnMenuItemClickListener(item -> mMenu.performItemAction(item, 0)); 122fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mFloatingToolbarVisibilityHelper = new FloatingToolbarVisibilityHelper(mFloatingToolbar); 123f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mFloatingToolbarVisibilityHelper.activate(); 124838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 125838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 126838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 127838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void setTitle(CharSequence title) {} 128838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 129838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 130838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void setTitle(int resId) {} 131838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 132838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 133838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void setSubtitle(CharSequence subtitle) {} 134838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 135838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 136838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void setSubtitle(int resId) {} 137838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 138838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 139838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void setCustomView(View view) {} 140838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 141838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 142838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void invalidate() { 143838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri mCallback.onPrepareActionMode(this, mMenu); 144f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki invalidateContentRect(); // Will re-layout and show the toolbar if necessary. 145838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 146838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 147838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 148838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void invalidateContentRect() { 149838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri mCallback.onGetContentRect(this, mOriginatingView, mContentRect); 150838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri repositionToolbar(); 151838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 152838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 153838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void updateViewLocationInWindow() { 154bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mOriginatingView.getLocationOnScreen(mViewPositionOnScreen); 155bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mOriginatingView.getRootView().getLocationOnScreen(mRootViewPositionOnScreen); 156bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mOriginatingView.getGlobalVisibleRect(mViewRectOnScreen); 157bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mViewRectOnScreen.offset(mRootViewPositionOnScreen[0], mRootViewPositionOnScreen[1]); 158c107b0ecdcd4e2f89ae4bec818c3a94f45c3c15eAbodunrinwa Toki 159bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa if (!Arrays.equals(mViewPositionOnScreen, mPreviousViewPositionOnScreen) 160bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa || !mViewRectOnScreen.equals(mPreviousViewRectOnScreen)) { 161c107b0ecdcd4e2f89ae4bec818c3a94f45c3c15eAbodunrinwa Toki repositionToolbar(); 162bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mPreviousViewPositionOnScreen[0] = mViewPositionOnScreen[0]; 163bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mPreviousViewPositionOnScreen[1] = mViewPositionOnScreen[1]; 164bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mPreviousViewRectOnScreen.set(mViewRectOnScreen); 165c107b0ecdcd4e2f89ae4bec818c3a94f45c3c15eAbodunrinwa Toki } 166838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 167838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 168838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri private void repositionToolbar() { 169bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mContentRectOnScreen.set(mContentRect); 1706183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen 1716183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen // Offset the content rect into screen coordinates, taking into account any transformations 1726183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen // that may be applied to the originating view or its ancestors. 1736183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen final ViewParent parent = mOriginatingView.getParent(); 1746183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen if (parent instanceof ViewGroup) { 1756183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen ((ViewGroup) parent).getChildVisibleRect( 1764e7a1208eaa81f684485ee23ba681dab6419973fAbodunrinwa Toki mOriginatingView, mContentRectOnScreen, 1774e7a1208eaa81f684485ee23ba681dab6419973fAbodunrinwa Toki null /* offset */, true /* forceParentCheck */); 1786183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen mContentRectOnScreen.offset(mRootViewPositionOnScreen[0], mRootViewPositionOnScreen[1]); 1796183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen } else { 1806183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen mContentRectOnScreen.offset(mViewPositionOnScreen[0], mViewPositionOnScreen[1]); 1816183b722de89d69ce16890db809a14ac03ab89feJustin Klaassen } 182a8151e4ef7987faa7d0ee31bc3013a05e5b76a05Abodunrinwa Toki 183a8151e4ef7987faa7d0ee31bc3013a05e5b76a05Abodunrinwa Toki if (isContentRectWithinBounds()) { 184a8151e4ef7987faa7d0ee31bc3013a05e5b76a05Abodunrinwa Toki mFloatingToolbarVisibilityHelper.setOutOfBounds(false); 185f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki // Make sure that content rect is not out of the view's visible bounds. 186bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mContentRectOnScreen.set( 187bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa Math.max(mContentRectOnScreen.left, mViewRectOnScreen.left), 188bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa Math.max(mContentRectOnScreen.top, mViewRectOnScreen.top), 189bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa Math.min(mContentRectOnScreen.right, mViewRectOnScreen.right), 190bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa Math.min(mContentRectOnScreen.bottom, 191bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mViewRectOnScreen.bottom + mBottomAllowance)); 192bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa 193bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa if (!mContentRectOnScreen.equals(mPreviousContentRectOnScreen)) { 194f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki // Content rect is moving. 195f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mOriginatingView.removeCallbacks(mMovingOff); 196f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mFloatingToolbarVisibilityHelper.setMoving(true); 197f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY); 198f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki 199bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mFloatingToolbar.setContentRect(mContentRectOnScreen); 200f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mFloatingToolbar.updateLayout(); 201f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki } 202a8151e4ef7987faa7d0ee31bc3013a05e5b76a05Abodunrinwa Toki } else { 203a8151e4ef7987faa7d0ee31bc3013a05e5b76a05Abodunrinwa Toki mFloatingToolbarVisibilityHelper.setOutOfBounds(true); 204bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mContentRectOnScreen.setEmpty(); 205a8151e4ef7987faa7d0ee31bc3013a05e5b76a05Abodunrinwa Toki } 206b9acbe40d298612a2ab6bfb15842e63ff8f09af5Abodunrinwa Toki mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); 207a8151e4ef7987faa7d0ee31bc3013a05e5b76a05Abodunrinwa Toki 208bafc908304d49e8f7f7c5e52772c75da66e4daa3Yohei Yukawa mPreviousContentRectOnScreen.set(mContentRectOnScreen); 209838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 210838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 211f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki private boolean isContentRectWithinBounds() { 21249f1a76a4412ef4e36f1f647fa7ec182e6cf9b58Abodunrinwa Toki mContext.getSystemService(WindowManager.class) 21349f1a76a4412ef4e36f1f647fa7ec182e6cf9b58Abodunrinwa Toki .getDefaultDisplay().getRealSize(mDisplaySize); 21449f1a76a4412ef4e36f1f647fa7ec182e6cf9b58Abodunrinwa Toki mScreenRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); 215f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki 216f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri return intersectsClosed(mContentRectOnScreen, mScreenRect) 217f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri && intersectsClosed(mContentRectOnScreen, mViewRectOnScreen); 218f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri } 219f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri 220f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri /* 221f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri * Same as Rect.intersects, but includes cases where the rectangles touch. 222f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri */ 223f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri private static boolean intersectsClosed(Rect a, Rect b) { 224f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri return a.left <= b.right && b.left <= a.right 225f95ed10d9da55c25013200fb35af63f0dac65cb4Clara Bayarri && a.top <= b.bottom && b.top <= a.bottom; 226fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 227fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 228fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki @Override 2299e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki public void hide(long duration) { 2309e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki if (duration == ActionMode.DEFAULT_HIDE_DURATION) { 2319e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki duration = ViewConfiguration.getDefaultActionModeHideDuration(); 2329e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki } 2339e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki duration = Math.min(MAX_HIDE_DURATION, duration); 2349e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki mOriginatingView.removeCallbacks(mHideOff); 2359e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki if (duration <= 0) { 2369e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki mHideOff.run(); 237fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } else { 2389e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki mFloatingToolbarVisibilityHelper.setHideRequested(true); 239f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); 2409e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki mOriginatingView.postDelayed(mHideOff, duration); 241fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 242fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 243fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 244838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 245972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki public void onWindowFocusChanged(boolean hasWindowFocus) { 246972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki mFloatingToolbarVisibilityHelper.setWindowFocused(hasWindowFocus); 247972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); 248972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki } 249972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki 250972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki @Override 251838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public void finish() { 252fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki reset(); 253838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri mCallback.onDestroyActionMode(this); 254838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 255838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 256838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 257838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public Menu getMenu() { 258838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri return mMenu; 259838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 260838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 261838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 262838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public CharSequence getTitle() { 263838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri return null; 264838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 265838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 266838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 267838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public CharSequence getSubtitle() { 268838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri return null; 269838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 270838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 271838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 272838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public View getCustomView() { 273838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri return null; 274838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 275838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 276838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri @Override 277838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri public MenuInflater getMenuInflater() { 278838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri return new MenuInflater(mContext); 279838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri } 280838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri 281fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki private void reset() { 282972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki mFloatingToolbar.dismiss(); 283f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mFloatingToolbarVisibilityHelper.deactivate(); 284fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mOriginatingView.removeCallbacks(mMovingOff); 2859e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki mOriginatingView.removeCallbacks(mHideOff); 286fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 287fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 288d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki private boolean isViewStillActive() { 289d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki return mOriginatingView.getWindowVisibility() == View.VISIBLE 290d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki && mOriginatingView.isShown(); 291d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki } 292d1eb19c65e89a67cfc63ed5496825b79a3bfe1edAbodunrinwa Toki 293fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki /** 294f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki * A helper for showing/hiding the floating toolbar depending on certain states. 295fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki */ 296fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki private static final class FloatingToolbarVisibilityHelper { 297fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 298fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki private final FloatingToolbar mToolbar; 299fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 3009e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki private boolean mHideRequested; 301fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki private boolean mMoving; 302fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki private boolean mOutOfBounds; 303972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki private boolean mWindowFocused = true; 304fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 305f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki private boolean mActive; 306f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki 307fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki public FloatingToolbarVisibilityHelper(FloatingToolbar toolbar) { 308fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mToolbar = Preconditions.checkNotNull(toolbar); 309fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 310fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 311f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki public void activate() { 312f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mHideRequested = false; 313f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mMoving = false; 314f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mOutOfBounds = false; 315972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki mWindowFocused = true; 316f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki 317f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mActive = true; 318f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki } 319f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki 320f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki public void deactivate() { 321f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mActive = false; 322f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki mToolbar.dismiss(); 323f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki } 324f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki 3259e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki public void setHideRequested(boolean hide) { 3269e211282d3ee54c9840947951593554c3bd5a77cAbodunrinwa Toki mHideRequested = hide; 327fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 328fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 329fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki public void setMoving(boolean moving) { 330fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mMoving = moving; 331fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 332fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 333fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki public void setOutOfBounds(boolean outOfBounds) { 334fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mOutOfBounds = outOfBounds; 335fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 336fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki 337972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki public void setWindowFocused(boolean windowFocused) { 338972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki mWindowFocused = windowFocused; 339972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki } 340972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki 341f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki public void updateToolbarVisibility() { 342f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki if (!mActive) { 343f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki return; 344f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki } 345f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki 346972ab4f8588c365cf9c06e1f22b30a96fb0a06fcAbodunrinwa Toki if (mHideRequested || mMoving || mOutOfBounds || !mWindowFocused) { 347fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mToolbar.hide(); 348f444b5c3ae46f8790c8f2a8481fb688b00a42d3bAbodunrinwa Toki } else { 349fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki mToolbar.show(); 350fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 351fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 352fd3a3a1163c5096821cef351309fcdd9a4f48002Abodunrinwa Toki } 353838e36cda7af884233c06c5b2b5e43ffbed4715bClara Bayarri} 354