FloatingToolbar.java revision 7aa6d0a4b1ec7f75335348a86284d3773cc72f91
10c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki/* 20c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Copyright (C) 2015 The Android Open Source Project 30c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 40c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Licensed under the Apache License, Version 2.0 (the "License"); 50c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * you may not use this file except in compliance with the License. 60c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * You may obtain a copy of the License at 70c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 80c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * http://www.apache.org/licenses/LICENSE-2.0 90c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 100c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Unless required by applicable law or agreed to in writing, software 110c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * distributed under the License is distributed on an "AS IS" BASIS, 120c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * See the License for the specific language governing permissions and 140c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * limitations under the License. 150c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 160c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokipackage com.android.internal.widget; 180c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 190c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.animation.Animator; 200c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.animation.AnimatorListenerAdapter; 210c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.animation.AnimatorSet; 220c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.animation.ObjectAnimator; 230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.content.Context; 240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.graphics.Color; 250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.graphics.Point; 260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.graphics.Rect; 27517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.graphics.Region; 280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.graphics.drawable.ColorDrawable; 29b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Tokiimport android.text.TextUtils; 30517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.util.Size; 310c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.Gravity; 320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.LayoutInflater; 330c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.Menu; 340c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.MenuItem; 350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.View; 360c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.View.MeasureSpec; 370c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.ViewGroup; 38517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.ViewTreeObserver; 390c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.Window; 40e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Tokiimport android.view.WindowInsets; 41517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.WindowManager; 42517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.animation.Animation; 43517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.animation.AnimationSet; 44517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.animation.Transformation; 45517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.widget.AdapterView; 46517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.widget.ArrayAdapter; 470c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.widget.Button; 480c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.widget.ImageButton; 49b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Tokiimport android.widget.ImageView; 500c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.widget.LinearLayout; 51517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.widget.ListView; 520c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.widget.PopupWindow; 53517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.widget.TextView; 540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 550c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport java.util.ArrayList; 560c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport java.util.LinkedList; 570c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport java.util.List; 580c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 59517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport com.android.internal.R; 60517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport com.android.internal.util.Preconditions; 61517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 620c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki/** 630c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * A floating toolbar for showing contextual menu items. 640c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * This view shows as many menu item buttons as can fit in the horizontal toolbar and the 650c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * the remaining menu items in a vertical overflow view when the overflow button is clicked. 660c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * The horizontal toolbar morphs into the vertical overflow view. 670c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 680c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokipublic final class FloatingToolbar { 690c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 70517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki // This class is responsible for the public API of the floating toolbar. 71517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki // It delegates rendering operations to the FloatingToolbarPopup. 72517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 730c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private static final MenuItem.OnMenuItemClickListener NO_OP_MENUITEM_CLICK_LISTENER = 740c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki new MenuItem.OnMenuItemClickListener() { 750c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki @Override 760c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public boolean onMenuItemClick(MenuItem item) { 770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return false; 780c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 790c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki }; 800c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 810c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private final Context mContext; 820c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private final FloatingToolbarPopup mPopup; 830c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 840c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private final Rect mContentRect = new Rect(); 850c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 860c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private Menu mMenu; 875047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki private List<Object> mShowingMenuItems = new ArrayList<Object>(); 880c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; 890c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 900c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private int mSuggestedWidth; 91517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private boolean mWidthChanged = true; 920c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 930c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 940c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Initializes a floating toolbar. 950c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 960c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar(Context context, Window window) { 970c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mContext = Preconditions.checkNotNull(context); 98517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopup = new FloatingToolbarPopup(window.getDecorView()); 990c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1000c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1010c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1020c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Sets the menu to be shown in this floating toolbar. 1030c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the 1040c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * toolbar. 1050c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1060c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar setMenu(Menu menu) { 1070c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mMenu = Preconditions.checkNotNull(menu); 1080c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1090c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1100c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1110c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1127270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Sets the custom listener for invocation of menu items in this floating toolbar. 1130c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1140c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar setOnMenuItemClickListener( 1150c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki MenuItem.OnMenuItemClickListener menuItemClickListener) { 1160c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (menuItemClickListener != null) { 1170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mMenuItemClickListener = menuItemClickListener; 1180c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } else { 1190c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; 1200c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1210c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1220c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Sets the content rectangle. This is the area of the interesting content that this toolbar 1260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * should avoid obstructing. 1270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the 1280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * toolbar. 1290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar setContentRect(Rect rect) { 1310c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mContentRect.set(Preconditions.checkNotNull(rect)); 1320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1330c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1340c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1360c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Sets the suggested width of this floating toolbar. 1370c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * The actual width will be about this size but there are no guarantees that it will be exactly 1380c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * the suggested width. 1390c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the 1400c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * toolbar. 1410c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1420c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar setSuggestedWidth(int suggestedWidth) { 143517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki // Check if there's been a substantial width spec change. 144517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int difference = Math.abs(suggestedWidth - mSuggestedWidth); 145517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mWidthChanged = difference > (mSuggestedWidth * 0.2); 146517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1470c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mSuggestedWidth = suggestedWidth; 1480c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1490c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1500c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1510c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1520c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Shows this floating toolbar. 1530c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar show() { 1550c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu); 156517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (!isCurrentlyShowing(menuItems) || mWidthChanged) { 1570c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mPopup.dismiss(); 158517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth); 1595047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki mShowingMenuItems = getShowingMenuItemsReferences(menuItems); 1600c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 161ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mPopup.updateCoordinates(mContentRect); 1620c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (!mPopup.isShowing()) { 163ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mPopup.show(mContentRect); 1640c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 165517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mWidthChanged = false; 1660c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1670c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1680c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1690c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1700c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Updates this floating toolbar to reflect recent position and view updates. 1710c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * NOTE: This method is a no-op if the toolbar isn't showing. 1720c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1730c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar updateLayout() { 1740c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (mPopup.isShowing()) { 1750c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki // show() performs all the logic we need here. 1760c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki show(); 1770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1780c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1790c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1800c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1810c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1820c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Dismisses this floating toolbar. 1830c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1840c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public void dismiss() { 1850c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mPopup.dismiss(); 1860c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1870c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1880c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1897270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Hides this floating toolbar. This is a no-op if the toolbar is not showing. 1907270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Use {@link #isHidden()} to distinguish between a hidden and a dismissed toolbar. 1917270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 1927270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public void hide() { 1937270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mPopup.hide(); 1947270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 1957270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 1967270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 1977270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Returns {@code true} if this toolbar is currently showing. {@code false} otherwise. 1980c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1990c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public boolean isShowing() { 2000c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return mPopup.isShowing(); 2010c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2020c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2030c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 2047270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Returns {@code true} if this toolbar is currently hidden. {@code false} otherwise. 2057270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 2067270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public boolean isHidden() { 2077270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki return mPopup.isHidden(); 2087270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 2097270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 2107270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 211517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns true if this floating toolbar is currently showing the specified menu items. 2120c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 213517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private boolean isCurrentlyShowing(List<MenuItem> menuItems) { 2145047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki return mShowingMenuItems.equals(getShowingMenuItemsReferences(menuItems)); 2150c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2160c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 2180c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns the visible and enabled menu items in the specified menu. 2190c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * This method is recursive. 2200c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 2210c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private List<MenuItem> getVisibleAndEnabledMenuItems(Menu menu) { 2220c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki List<MenuItem> menuItems = new ArrayList<MenuItem>(); 2230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki for (int i = 0; (menu != null) && (i < menu.size()); i++) { 2240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki MenuItem menuItem = menu.getItem(i); 2250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (menuItem.isVisible() && menuItem.isEnabled()) { 2260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki Menu subMenu = menuItem.getSubMenu(); 2270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (subMenu != null) { 2280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki menuItems.addAll(getVisibleAndEnabledMenuItems(subMenu)); 2290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } else { 2300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki menuItems.add(menuItem); 2310c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2330c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2340c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return menuItems; 2350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2360c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2375047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki private List<Object> getShowingMenuItemsReferences(List<MenuItem> menuItems) { 2385047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki List<Object> references = new ArrayList<Object>(); 2390c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki for (MenuItem menuItem : menuItems) { 2405047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki if (isIconOnlyMenuItem(menuItem)) { 2415047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki references.add(menuItem.getIcon()); 2425047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki } else { 2435047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki references.add(menuItem.getTitle()); 2445047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki } 2450c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2465047132887112df4235beea8ff42a28f1653e202Abodunrinwa Toki return references; 2470c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2480c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2490c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2500c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 251517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * A popup window used by the floating toolbar. 252517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 253517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This class is responsible for the rendering/animation of the floating toolbar. 254517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * It can hold one of 2 panels (i.e. main panel and overflow panel) at a time. 255517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * It delegates specific panel functionality to the appropriate panel. 2560c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 257517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final class FloatingToolbarPopup { 2580c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 259517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public static final int OVERFLOW_DIRECTION_UP = 0; 260517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public static final int OVERFLOW_DIRECTION_DOWN = 1; 2610c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 262517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final View mParent; 263517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final PopupWindow mPopupWindow; 264517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewGroup mContentContainer; 265f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private final int mMarginHorizontal; 266f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private final int mMarginVertical; 2670c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 268517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Animation.AnimationListener mOnOverflowOpened = 269517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new Animation.AnimationListener() { 270517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 271517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationStart(Animation animation) {} 2720c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 273517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 274517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationEnd(Animation animation) { 275b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setOverflowPanelAsContent(); 276517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.fadeIn(true); 277517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 2780c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 279517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 280517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationRepeat(Animation animation) {} 281517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 282517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Animation.AnimationListener mOnOverflowClosed = 283517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new Animation.AnimationListener() { 284517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 285517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationStart(Animation animation) {} 2860c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 287517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 288517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationEnd(Animation animation) { 289b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setMainPanelAsContent(); 290517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel.fadeIn(true); 291517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 2920c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2930c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki @Override 294517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationRepeat(Animation animation) { 2950c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2960c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki }; 2977270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private final AnimatorSet mDismissAnimation; 2987270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private final AnimatorSet mHideAnimation; 299b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true) { 300b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki @Override 301b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki public void cancel() { 302b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (hasStarted() && !hasEnded()) { 303b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki super.cancel(); 304b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setOverflowPanelAsContent(); 305b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 306b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 307b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki }; 308b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private final AnimationSet mCloseOverflowAnimation = new AnimationSet(true) { 309b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki @Override 310b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki public void cancel() { 311b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (hasStarted() && !hasEnded()) { 312b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki super.cancel(); 313b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setMainPanelAsContent(); 314b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 315b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 316b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki }; 3170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 318517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Runnable mOpenOverflow = new Runnable() { 319517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 320517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void run() { 321517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki openOverflow(); 322517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 323517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 324517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Runnable mCloseOverflow = new Runnable() { 325517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 326517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void run() { 327517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki closeOverflow(); 328517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 329517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 330517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 331e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki private final Rect mViewPort = new Rect(); 332ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki private final Point mCoords = new Point(); 333ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 334517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Region mTouchableRegion = new Region(); 335d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = 336d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki new ViewTreeObserver.OnComputeInternalInsetsListener() { 337d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki public void onComputeInternalInsets( 338d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki ViewTreeObserver.InternalInsetsInfo info) { 339d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki info.contentInsets.setEmpty(); 340d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki info.visibleInsets.setEmpty(); 341d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki info.touchableRegion.set(mTouchableRegion); 342d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo 343d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki .TOUCHABLE_INSETS_REGION); 344d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki } 345d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki }; 346517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 3477270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private boolean mDismissed = true; // tracks whether this popup is dismissed or dismissing. 3487270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private boolean mHidden; // tracks whether this popup is hidden or hiding. 3490c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 350517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private FloatingToolbarOverflowPanel mOverflowPanel; 351517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private FloatingToolbarMainPanel mMainPanel; 352517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private int mOverflowDirection; 353517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 3540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 355517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Initializes a new floating toolbar popup. 3560c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 357517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param parent A parent view to get the {@link android.view.View#getWindowToken()} token 358517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * from. 3590c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 3600c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbarPopup(View parent) { 3610c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mParent = Preconditions.checkNotNull(parent); 3620c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mContentContainer = createContentContainer(parent.getContext()); 3630c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mPopupWindow = createPopupWindow(mContentContainer); 3647aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki mDismissAnimation = createExitAnimation( 365517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer, 3664ce050bd83b8c311d7cf7b50e0a36a28df68bc4aAbodunrinwa Toki 150, // startDelay 367517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new AnimatorListenerAdapter() { 368517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 369517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationEnd(Animator animation) { 370517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopupWindow.dismiss(); 371b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.removeAllViews(); 372517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 373517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }); 3747aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki mHideAnimation = createExitAnimation( 3757270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mContentContainer, 3764ce050bd83b8c311d7cf7b50e0a36a28df68bc4aAbodunrinwa Toki 0, // startDelay 3777270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki new AnimatorListenerAdapter() { 3787270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki @Override 3797270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public void onAnimationEnd(Animator animation) { 3807270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mPopupWindow.dismiss(); 3817270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 3827270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki }); 3836cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki mMarginHorizontal = parent.getResources() 3846cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); 3856cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki mMarginVertical = parent.getResources() 3866cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_vertical_margin); 387517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 388517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 389517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 390517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Lays out buttons for the specified menu items. 391517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 3926c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki public void layoutMenuItems( 3936c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki List<MenuItem> menuItems, 3946c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki MenuItem.OnMenuItemClickListener menuItemClickListener, 3956c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki int suggestedWidth) { 396ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki Preconditions.checkNotNull(menuItems); 397ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 398517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.removeAllViews(); 399517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mMainPanel == null) { 400517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel = new FloatingToolbarMainPanel(mParent.getContext(), mOpenOverflow); 401517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 402517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki List<MenuItem> overflowMenuItems = 403e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki mMainPanel.layoutMenuItems(menuItems, getToolbarWidth(suggestedWidth)); 404517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel.setOnMenuItemClickListener(menuItemClickListener); 405517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (!overflowMenuItems.isEmpty()) { 406517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOverflowPanel == null) { 407517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel = 408517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new FloatingToolbarOverflowPanel(mParent.getContext(), mCloseOverflow); 409517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 410517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.setMenuItems(overflowMenuItems); 411517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.setOnMenuItemClickListener(menuItemClickListener); 412517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 413517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki updatePopupSize(); 4140c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4150c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4160c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 4170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Shows this popup at the specified coordinates. 4180c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. 4190c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 420ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki public void show(Rect contentRect) { 421ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki Preconditions.checkNotNull(contentRect); 422ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 4230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (isShowing()) { 4240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return; 4250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4277270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHidden = false; 4287270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissed = false; 4290ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki cancelDismissAndHideAnimations(); 4300ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki cancelOverflowAnimations(); 431ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 432b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // Make sure a panel is set as the content. 433b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (mContentContainer.getChildCount() == 0) { 434b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setMainPanelAsContent(); 435c23ac32601af1c7a5877d99c221e7e79e0ed1c90Abodunrinwa Toki // If we're yet to show the popup, set the container visibility to zero. 436c23ac32601af1c7a5877d99c221e7e79e0ed1c90Abodunrinwa Toki // The "show" animation will make this visible. 437c23ac32601af1c7a5877d99c221e7e79e0ed1c90Abodunrinwa Toki mContentContainer.setAlpha(0); 438b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 439e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki refreshViewPort(); 440e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki updateOverflowHeight(contentRect.top - (mMarginVertical * 2) - mViewPort.top); 441ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki refreshCoordinatesAndOverflowDirection(contentRect); 442517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki preparePopupContent(); 443ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoords.x, mCoords.y); 444d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki setTouchableSurfaceInsetsComputer(); 4457270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki runShowAnimation(); 4460c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4470c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4480c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 4490c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Gets rid of this popup. If the popup isn't currently showing, this will be a no-op. 4500c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 4510c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public void dismiss() { 4520ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki if (mDismissed) { 4530c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return; 4540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4550c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4567270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHidden = false; 4577270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissed = true; 4580ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki mHideAnimation.cancel(); 4597270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki runDismissAnimation(); 4607270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki setZeroTouchableSurface(); 4617270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 4627270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 4637270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 4647270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Hides this popup. This is a no-op if this popup is not showing. 4657270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Use {@link #isHidden()} to distinguish between a hidden and a dismissed popup. 4667270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 4677270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public void hide() { 4687270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki if (!isShowing()) { 4697270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki return; 4707270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 4717270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 4727270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHidden = true; 4737270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki runHideAnimation(); 474517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki setZeroTouchableSurface(); 4750c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4760c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 4780c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns {@code true} if this popup is currently showing. {@code false} otherwise. 4790c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 4800c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public boolean isShowing() { 481c23ac32601af1c7a5877d99c221e7e79e0ed1c90Abodunrinwa Toki return !mDismissed && !mHidden; 4827270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 4837270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 4847270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 4857270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Returns {@code true} if this popup is currently hidden. {@code false} otherwise. 4867270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 4877270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public boolean isHidden() { 4887270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki return mHidden; 4890c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4900c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4910c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 4920c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Updates the coordinates of this popup. 4930c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. 4947270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * This is a no-op if this popup is not showing. 4950c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 496ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki public void updateCoordinates(Rect contentRect) { 497ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki Preconditions.checkNotNull(contentRect); 498ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 499c23ac32601af1c7a5877d99c221e7e79e0ed1c90Abodunrinwa Toki if (!isShowing() || !mPopupWindow.isShowing()) { 500517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return; 5010c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 502517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 5030ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki cancelOverflowAnimations(); 504e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki refreshViewPort(); 505ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki refreshCoordinatesAndOverflowDirection(contentRect); 506517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki preparePopupContent(); 507ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mPopupWindow.update(mCoords.x, mCoords.y, getWidth(), getHeight()); 5080c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5090c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5100c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5110c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns the width of this popup. 5120c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5130c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public int getWidth() { 514517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mPopupWindow.getWidth(); 5150c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5160c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5180c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns the height of this popup. 5190c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5200c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public int getHeight() { 521517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mPopupWindow.getHeight(); 5220c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns the context this popup is running in. 5260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public Context getContext() { 5280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return mContentContainer.getContext(); 5290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 531ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki private void refreshCoordinatesAndOverflowDirection(Rect contentRect) { 532e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki // NOTE: Ensure that mViewPort has been refreshed before this. 533e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki 534ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki int x = contentRect.centerX() - getWidth() / 2; 535ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki int y; 536e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki if (contentRect.top - getHeight() > mViewPort.top) { 537ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki y = contentRect.top - getHeight(); 538ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_UP; 539e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki } else if (contentRect.top - getToolbarHeightWithVerticalMargin() > mViewPort.top) { 540ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki y = contentRect.top - getToolbarHeightWithVerticalMargin(); 541ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN; 542ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } else { 543ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki y = contentRect.bottom; 544ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN; 545ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 546e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki 547e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki // Update x so that the toolbar isn't rendered behind the nav bar in landscape. 548e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki x = Math.max(0, Math.min(x, mViewPort.right - getWidth())); 549e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki 550ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mCoords.set(x, y); 551ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki if (mOverflowPanel != null) { 552ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mOverflowPanel.setOverflowDirection(mOverflowDirection); 553ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 554ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 555ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 556ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki private int getToolbarHeightWithVerticalMargin() { 557f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki return getEstimatedToolbarHeight(mParent.getContext()) + mMarginVertical * 2; 558f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki } 559f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki 5600c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5617270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Performs the "show" animation on the floating popup. 5627270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 5637270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private void runShowAnimation() { 5647aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki createEnterAnimation(mContentContainer).start(); 5657270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 5667270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 5677270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 5687270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Performs the "dismiss" animation on the floating popup. 5690c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5707270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private void runDismissAnimation() { 5717270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissAnimation.start(); 5720c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5730c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5740c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5757270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Performs the "hide" animation on the floating popup. 5760c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5777270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private void runHideAnimation() { 5787270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHideAnimation.start(); 5790c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5800c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5810ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki private void cancelDismissAndHideAnimations() { 5827270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissAnimation.cancel(); 5837270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHideAnimation.cancel(); 5840ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki } 5850ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki 5860ce3e08a8444c73e63a0f733357581fb4409449aAbodunrinwa Toki private void cancelOverflowAnimations() { 587b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.cancel(); 588b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.cancel(); 589517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 590517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 591517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 592517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Opens the floating toolbar overflow. 593517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This method should not be called if menu items have not been laid out with 594b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, int)}. 595517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 596517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @throws IllegalStateException if called when menu items have not been laid out. 597517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 598517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void openOverflow() { 599b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkState(mMainPanel != null); 600b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkState(mOverflowPanel != null); 601517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 602517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel.fadeOut(true); 603517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size overflowPanelSize = mOverflowPanel.measure(); 604f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki final int targetWidth = overflowPanelSize.getWidth(); 605517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int targetHeight = overflowPanelSize.getHeight(); 606517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final boolean morphUpwards = (mOverflowDirection == OVERFLOW_DIRECTION_UP); 607517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int startWidth = mContentContainer.getWidth(); 608517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int startHeight = mContentContainer.getHeight(); 609517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final float startY = mContentContainer.getY(); 6106c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki final float left = mContentContainer.getX(); 6116c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki final float right = left + mContentContainer.getWidth(); 612517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Animation widthAnimation = new Animation() { 613517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 614517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki protected void applyTransformation(float interpolatedTime, Transformation t) { 615517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 616517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth)); 617517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.width = startWidth + deltaWidth; 618517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 6196cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki if (isRTL()) { 6206c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki mContentContainer.setX(left); 6216c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki } else { 6226c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki mContentContainer.setX(right - mContentContainer.getWidth()); 6236c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki } 624517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 625517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 626517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Animation heightAnimation = new Animation() { 627517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 628517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki protected void applyTransformation(float interpolatedTime, Transformation t) { 629517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 630517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int deltaHeight = (int) (interpolatedTime * (targetHeight - startHeight)); 631517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.height = startHeight + deltaHeight; 632517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 633517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (morphUpwards) { 634517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki float y = startY - (mContentContainer.getHeight() - startHeight); 635517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setY(y); 636517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 637517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 638517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 639517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki widthAnimation.setDuration(240); 640517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki heightAnimation.setDuration(180); 641517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki heightAnimation.setStartOffset(60); 642b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.getAnimations().clear(); 643b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.setAnimationListener(mOnOverflowOpened); 644b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.addAnimation(widthAnimation); 645b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.addAnimation(heightAnimation); 646b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.startAnimation(mOpenOverflowAnimation); 647517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 648517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 649517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 650517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Opens the floating toolbar overflow. 651517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This method should not be called if menu items have not been laid out with 652517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, int)}. 653517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 654b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * @throws IllegalStateException if called when menu items have not been laid out. 655517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 656517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void closeOverflow() { 657b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkState(mMainPanel != null); 658b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkState(mOverflowPanel != null); 659517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 660517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.fadeOut(true); 661517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size mainPanelSize = mMainPanel.measure(); 662517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int targetWidth = mainPanelSize.getWidth(); 663517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int targetHeight = mainPanelSize.getHeight(); 664517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int startWidth = mContentContainer.getWidth(); 665517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int startHeight = mContentContainer.getHeight(); 666517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final float bottom = mContentContainer.getY() + mContentContainer.getHeight(); 667517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final boolean morphedUpwards = (mOverflowDirection == OVERFLOW_DIRECTION_UP); 6686c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki final float left = mContentContainer.getX(); 6696c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki final float right = left + mContentContainer.getWidth(); 670517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Animation widthAnimation = new Animation() { 671517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 672517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki protected void applyTransformation(float interpolatedTime, Transformation t) { 673517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 674517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth)); 675517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.width = startWidth + deltaWidth; 676517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 6776cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki if (isRTL()) { 6786c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki mContentContainer.setX(left); 6796c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki } else { 6806c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki mContentContainer.setX(right - mContentContainer.getWidth()); 6816c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki } 682517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 683517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 684517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Animation heightAnimation = new Animation() { 685517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 686517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki protected void applyTransformation(float interpolatedTime, Transformation t) { 687517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 688517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int deltaHeight = (int) (interpolatedTime * (targetHeight - startHeight)); 689517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.height = startHeight + deltaHeight; 690517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 691517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (morphedUpwards) { 692517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setY(bottom - mContentContainer.getHeight()); 693517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 694517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 695517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 696517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki widthAnimation.setDuration(150); 697517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki widthAnimation.setStartOffset(150); 698517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki heightAnimation.setDuration(210); 699b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.getAnimations().clear(); 700b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.setAnimationListener(mOnOverflowClosed); 701b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.addAnimation(widthAnimation); 702b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.addAnimation(heightAnimation); 703b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.startAnimation(mCloseOverflowAnimation); 704517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 705517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 706517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 707517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Prepares the content container for show and update calls. 708517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 709517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void preparePopupContent() { 710b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // Reset visibility. 711b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (mMainPanel != null) { 712b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mMainPanel.fadeIn(false); 713517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 714517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOverflowPanel != null) { 715517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.fadeIn(false); 716517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 717517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 718b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // Reset position. 719ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki if (isMainPanelContent()) { 720b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki positionMainPanel(); 721517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 722ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki if (isOverflowPanelContent()) { 723b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki positionOverflowPanel(); 724517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 725517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 726517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 727ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki private boolean isMainPanelContent() { 728ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki return mMainPanel != null 729ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki && mContentContainer.getChildAt(0) == mMainPanel.getView(); 730ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 731ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 732ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki private boolean isOverflowPanelContent() { 733ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki return mOverflowPanel != null 734ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki && mContentContainer.getChildAt(0) == mOverflowPanel.getView(); 735ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 736ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 737517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 738517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the current content to be the main view panel. 739517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 740517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void setMainPanelAsContent() { 741b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // This should never be called if the main panel has not been initialized. 742b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkNotNull(mMainPanel); 743517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.removeAllViews(); 744517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size mainPanelSize = mMainPanel.measure(); 745517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 746517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.width = mainPanelSize.getWidth(); 747517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.height = mainPanelSize.getHeight(); 748517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 749517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.addView(mMainPanel.getView()); 750b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setContentAreaAsTouchableSurface(); 751b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 752b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 753b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki /** 754b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * Sets the current content to be the overflow view panel. 755b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki */ 756b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void setOverflowPanelAsContent() { 757b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // This should never be called if the overflow panel has not been initialized. 758b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkNotNull(mOverflowPanel); 759b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.removeAllViews(); 760b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Size overflowPanelSize = mOverflowPanel.measure(); 761b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 762b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki params.width = overflowPanelSize.getWidth(); 763b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki params.height = overflowPanelSize.getHeight(); 764b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setLayoutParams(params); 765b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.addView(mOverflowPanel.getView()); 766b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setContentAreaAsTouchableSurface(); 767b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 768b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 769b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki /** 770b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * Places the main view panel at the appropriate resting coordinates. 771b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki */ 772b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void positionMainPanel() { 773b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkNotNull(mMainPanel); 7746c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki mContentContainer.setX(mMarginHorizontal); 775b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 776b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki float y = mMarginVertical; 777b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (mOverflowDirection == OVERFLOW_DIRECTION_UP) { 778b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki y = getHeight() 779b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki - (mMainPanel.getView().getMeasuredHeight() + mMarginVertical); 780b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 781b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setY(y); 782b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setContentAreaAsTouchableSurface(); 783b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 784b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 785b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki /** 786b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * Places the main view panel at the appropriate resting coordinates. 787b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki */ 788b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void positionOverflowPanel() { 789b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkNotNull(mOverflowPanel); 7906cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki float x; 7916cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki if (isRTL()) { 7926cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki x = mMarginHorizontal; 7936cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki } else { 7946cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki x = mPopupWindow.getWidth() 795b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki - (mOverflowPanel.getView().getMeasuredWidth() + mMarginHorizontal); 7966cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki } 797b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setX(x); 798b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setY(mMarginVertical); 799b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setContentAreaAsTouchableSurface(); 800517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 801517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 802ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki private void updateOverflowHeight(int height) { 803ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki if (mOverflowPanel != null) { 804ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mOverflowPanel.setSuggestedHeight(height); 805ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 806ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki // Re-measure the popup and it's contents. 807ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki boolean mainPanelContent = isMainPanelContent(); 808ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki boolean overflowPanelContent = isOverflowPanelContent(); 809ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mContentContainer.removeAllViews(); // required to update popup size. 810ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki updatePopupSize(); 811ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki // Reset the appropriate content. 812ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki if (mainPanelContent) { 813ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki setMainPanelAsContent(); 814ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 815ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki if (overflowPanelContent) { 816ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki setOverflowPanelAsContent(); 817ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 818ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 819ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 820ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 821517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void updatePopupSize() { 822517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int width = 0; 823517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int height = 0; 824517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mMainPanel != null) { 825517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size mainPanelSize = mMainPanel.measure(); 826517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki width = mainPanelSize.getWidth(); 827517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki height = mainPanelSize.getHeight(); 828517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 829517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOverflowPanel != null) { 830517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size overflowPanelSize = mOverflowPanel.measure(); 831517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki width = Math.max(width, overflowPanelSize.getWidth()); 832517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki height = Math.max(height, overflowPanelSize.getHeight()); 833517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 834f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mPopupWindow.setWidth(width + mMarginHorizontal * 2); 835f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mPopupWindow.setHeight(height + mMarginVertical * 2); 836517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 837517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 838e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki 839e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki private void refreshViewPort() { 840e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki mParent.getGlobalVisibleRect(mViewPort); 841e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki WindowInsets windowInsets = mParent.getRootWindowInsets(); 842e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki mViewPort.set( 843e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki mViewPort.left + windowInsets.getStableInsetLeft(), 844e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki mViewPort.top + windowInsets.getStableInsetTop(), 845e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki mViewPort.right - windowInsets.getStableInsetRight(), 846e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki mViewPort.bottom - windowInsets.getStableInsetBottom()); 847e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki } 848e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki 849e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki private int getToolbarWidth(int suggestedWidth) { 850e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki int width = suggestedWidth; 851e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki refreshViewPort(); 852e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki int maximumWidth = mViewPort.width() - 2 * mParent.getResources() 853e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); 854e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki if (width <= 0) { 855e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki width = mParent.getResources() 856e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_preferred_width); 857e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki } 858e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki return Math.min(width, maximumWidth); 859e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki } 860e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki 861517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 862517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the touchable region of this popup to be zero. This means that all touch events on 863517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * this popup will go through to the surface behind it. 864517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 865517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void setZeroTouchableSurface() { 866517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mTouchableRegion.setEmpty(); 867517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 868517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 869517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 870517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the touchable region of this popup to be the area occupied by its content. 871517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 872517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void setContentAreaAsTouchableSurface() { 873517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (!mPopupWindow.isShowing()) { 874517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 875517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 876517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int width = mContentContainer.getMeasuredWidth(); 877517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int height = mContentContainer.getMeasuredHeight(); 878517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mTouchableRegion.set( 879517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki (int) mContentContainer.getX(), 880517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki (int) mContentContainer.getY(), 881517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki (int) mContentContainer.getX() + width, 882517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki (int) mContentContainer.getY() + height); 883517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 884d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki 885d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki /** 886d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki * Make the touchable area of this popup be the area specified by mTouchableRegion. 887d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki * This should be called after the popup window has been dismissed (dismiss/hide) 888d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki * and is probably being re-shown with a new content root view. 889d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki */ 890d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki private void setTouchableSurfaceInsetsComputer() { 891d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki ViewTreeObserver viewTreeObserver = mPopupWindow.getContentView() 892d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki .getRootView() 893d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki .getViewTreeObserver(); 894d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki viewTreeObserver.removeOnComputeInternalInsetsListener(mInsetsComputer); 895d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki viewTreeObserver.addOnComputeInternalInsetsListener(mInsetsComputer); 896d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki } 8976cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki 8986cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki private boolean isRTL() { 8996cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki return mContentContainer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 9006cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki } 901517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 902517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 903517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 904517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * A widget that holds the primary menu items in the floating toolbar. 905517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 906517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final class FloatingToolbarMainPanel { 907517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 908517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Context mContext; 909517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewGroup mContentView; 910517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final View.OnClickListener mMenuItemButtonOnClickListener = 911517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new View.OnClickListener() { 912517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 913517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onClick(View v) { 914517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (v.getTag() instanceof MenuItem) { 915517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOnMenuItemClickListener != null) { 916517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOnMenuItemClickListener.onMenuItemClick((MenuItem) v.getTag()); 917517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 918517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 919517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 920517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 921517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewFader viewFader; 922517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Runnable mOpenOverflow; 923517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 924517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private View mOpenOverflowButton; 925517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener; 926517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 927517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 928517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Initializes a floating toolbar popup main view panel. 929517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 930517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param context 931517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param openOverflow The code that opens the toolbar popup overflow. 932517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 933517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public FloatingToolbarMainPanel(Context context, Runnable openOverflow) { 934517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContext = Preconditions.checkNotNull(context); 935517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView = new LinearLayout(context); 936517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki viewFader = new ViewFader(mContentView); 937517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOpenOverflow = Preconditions.checkNotNull(openOverflow); 938517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 939517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 9400c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 941517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Fits as many menu items in the main panel and returns a list of the menu items that 942517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * were not fit in. 943517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 944517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @return The menu items that are not included in this main panel. 9450c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 946e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki public List<MenuItem> layoutMenuItems(List<MenuItem> menuItems, int width) { 947ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki Preconditions.checkNotNull(menuItems); 948ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 949e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki // Reserve space for the "open overflow" button. 950e3eb1833503c324127c621d22cbf7ac1729dbc54Abodunrinwa Toki final int toolbarWidth = width - getEstimatedOpenOverflowButtonWidth(mContext); 951517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 952517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int availableWidth = toolbarWidth; 953517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final LinkedList<MenuItem> remainingMenuItems = new LinkedList<MenuItem>(menuItems); 954517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 955517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.removeAllViews(); 956517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 957517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki boolean isFirstItem = true; 958517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki while (!remainingMenuItems.isEmpty()) { 959517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final MenuItem menuItem = remainingMenuItems.peek(); 960b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki View menuItemButton = createMenuItemButton(mContext, menuItem); 961517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 962f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki // Adding additional start padding for the first button to even out button spacing. 963517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (isFirstItem) { 964f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuItemButton.setPaddingRelative( 965f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki (int) (1.5 * menuItemButton.getPaddingStart()), 966517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.getPaddingTop(), 967f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuItemButton.getPaddingEnd(), 968517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.getPaddingBottom()); 969517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki isFirstItem = false; 970517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 971517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 972f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki // Adding additional end padding for the last button to even out button spacing. 973517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (remainingMenuItems.size() == 1) { 974f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuItemButton.setPaddingRelative( 975f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuItemButton.getPaddingStart(), 976517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.getPaddingTop(), 977f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki (int) (1.5 * menuItemButton.getPaddingEnd()), 978517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.getPaddingBottom()); 979517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 980517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 981517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 982517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth); 983517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (menuItemButtonWidth <= availableWidth) { 984b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki setButtonTagAndClickListener(menuItemButton, menuItem); 985517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(menuItemButton); 986517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = menuItemButton.getLayoutParams(); 987517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.width = menuItemButtonWidth; 988517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.setLayoutParams(params); 989517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki availableWidth -= menuItemButtonWidth; 990517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki remainingMenuItems.pop(); 991517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } else { 992517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOpenOverflowButton == null) { 993b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki mOpenOverflowButton = LayoutInflater.from(mContext) 994517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_open_overflow_button, null); 995517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOpenOverflowButton.setOnClickListener(new View.OnClickListener() { 996517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 997517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onClick(View v) { 998517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOpenOverflowButton != null) { 999517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOpenOverflow.run(); 1000517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1001517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1002517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }); 1003517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1004517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(mOpenOverflowButton); 1005517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki break; 1006517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1007517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1008517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return remainingMenuItems; 1009517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1010517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1011517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener listener) { 1012517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOnMenuItemClickListener = listener; 10130c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 10140c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1015517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public View getView() { 1016517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mContentView; 10170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 10180c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1019517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeIn(boolean animate) { 1020517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki viewFader.fadeIn(animate); 1021517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1022517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1023517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeOut(boolean animate) { 1024517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki viewFader.fadeOut(animate); 10250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 10260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 10270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1028517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns how big this panel's view should be. 1029517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This method should only be called when the view has not been attached to a parent 1030517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * otherwise it will throw an illegal state. 1031517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1032517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public Size measure() throws IllegalStateException { 1033517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Preconditions.checkState(mContentView.getParent() == null); 1034517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 1035517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return new Size(mContentView.getMeasuredWidth(), mContentView.getMeasuredHeight()); 1036517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1037b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki 1038b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki private void setButtonTagAndClickListener(View menuItemButton, MenuItem menuItem) { 1039b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki View button = menuItemButton; 1040b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki if (isIconOnlyMenuItem(menuItem)) { 1041b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki button = menuItemButton.findViewById(R.id.floating_toolbar_menu_item_image_button); 1042b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1043b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki button.setTag(menuItem); 1044b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki button.setOnClickListener(mMenuItemButtonOnClickListener); 1045b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1046517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1047517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1048517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1049517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1050517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * A widget that holds the overflow items in the floating toolbar. 1051517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1052517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final class FloatingToolbarOverflowPanel { 1053517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1054517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final LinearLayout mContentView; 1055517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewGroup mBackButtonContainer; 1056517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final View mBackButton; 1057517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ListView mListView; 1058f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private final TextView mListViewItemWidthCalculator; 1059517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewFader mViewFader; 1060517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Runnable mCloseOverflow; 1061517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1062517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener; 1063f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private int mOverflowWidth = 0; 1064ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki private int mSuggestedHeight; 1065517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1066517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1067517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Initializes a floating toolbar popup overflow view panel. 10680c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 1069517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param context 1070517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param closeOverflow The code that closes the toolbar popup's overflow. 1071517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1072517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public FloatingToolbarOverflowPanel(Context context, Runnable closeOverflow) { 1073517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mCloseOverflow = Preconditions.checkNotNull(closeOverflow); 1074ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mSuggestedHeight = getScreenHeight(context); 1075517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1076517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView = new LinearLayout(context); 1077517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.setOrientation(LinearLayout.VERTICAL); 1078517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mViewFader = new ViewFader(mContentView); 1079517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1080517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mBackButton = LayoutInflater.from(context) 1081517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_close_overflow_button, null); 1082517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mBackButton.setOnClickListener(new View.OnClickListener() { 1083517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 1084517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onClick(View v) { 1085517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mCloseOverflow.run(); 1086517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1087517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }); 1088517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mBackButtonContainer = new LinearLayout(context); 1089517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mBackButtonContainer.addView(mBackButton); 1090517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1091f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListView = createOverflowListView(); 1092517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 1093517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 1094517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 1095517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki MenuItem menuItem = (MenuItem) mListView.getAdapter().getItem(position); 1096517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOnMenuItemClickListener != null) { 1097517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOnMenuItemClickListener.onMenuItemClick(menuItem); 1098517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1099517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1100517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }); 1101517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1102517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(mListView); 1103517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(mBackButtonContainer); 1104f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki 1105f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator = createOverflowMenuItemButton(context); 1106f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator.setLayoutParams(new ViewGroup.LayoutParams( 1107f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 1108517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1109517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1110517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1111517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the menu items to be displayed in the overflow. 11120c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1113517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setMenuItems(List<MenuItem> menuItems) { 1114517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ArrayAdapter overflowListViewAdapter = (ArrayAdapter) mListView.getAdapter(); 1115517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListViewAdapter.clear(); 1116517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListViewAdapter.addAll(menuItems); 1117517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki setListViewHeight(); 1118f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki setOverflowWidth(); 1119517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1120517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1121517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener listener) { 1122517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOnMenuItemClickListener = listener; 11230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 11240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 11250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1126517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Notifies the overflow of the current direction in which the overflow will be opened. 11270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 1128517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param overflowDirection {@link FloatingToolbarPopup#OVERFLOW_DIRECTION_UP} 1129517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * or {@link FloatingToolbarPopup#OVERFLOW_DIRECTION_DOWN}. 11300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1131517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setOverflowDirection(int overflowDirection) { 1132517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.removeView(mBackButtonContainer); 1133517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int index = (overflowDirection == FloatingToolbarPopup.OVERFLOW_DIRECTION_UP)? 1 : 0; 1134517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(mBackButtonContainer, index); 11350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 11360c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1137ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki public void setSuggestedHeight(int height) { 1138ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki mSuggestedHeight = height; 1139ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki setListViewHeight(); 1140ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 1141ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki 11420c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1143517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns the content view of the overflow. 1144517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1145517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public View getView() { 1146517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mContentView; 1147517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1148517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1149517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeIn(boolean animate) { 1150517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mViewFader.fadeIn(animate); 1151517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1152517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1153517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeOut(boolean animate) { 1154517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mViewFader.fadeOut(animate); 1155517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1156517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1157517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1158517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns how big this panel's view should be. 1159517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This method should only be called when the view has not been attached to a parent. 11600c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 1161517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @throws IllegalStateException 11620c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1163517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public Size measure() { 1164517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Preconditions.checkState(mContentView.getParent() == null); 1165517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 1166517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return new Size(mContentView.getMeasuredWidth(), mContentView.getMeasuredHeight()); 1167517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1168517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1169517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void setListViewHeight() { 1170517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int itemHeight = getEstimatedToolbarHeight(mContentView.getContext()); 1171517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int height = mListView.getAdapter().getCount() * itemHeight; 1172517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int maxHeight = mContentView.getContext().getResources(). 1173ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki getDimensionPixelSize(R.dimen.floating_toolbar_maximum_overflow_height); 1174ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki int minHeight = mContentView.getContext().getResources(). 1175517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height); 1176ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki int availableHeight = mSuggestedHeight - (mSuggestedHeight % itemHeight) 1177ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki - itemHeight; // reserve space for the back button. 1178517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mListView.getLayoutParams(); 1179ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki if (availableHeight >= minHeight) { 1180ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki params.height = Math.min(Math.min(availableHeight, maxHeight), height); 1181ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } else { 1182ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki params.height = Math.min(maxHeight, height); 1183ffebf68202311963c497f5793e17d7a075706fd6Abodunrinwa Toki } 1184517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mListView.setLayoutParams(params); 11850c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1186517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1187f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private int setOverflowWidth() { 1188f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki for (int i = 0; i < mListView.getAdapter().getCount(); i++) { 1189f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki MenuItem menuItem = (MenuItem) mListView.getAdapter().getItem(i); 1190f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki Preconditions.checkNotNull(menuItem); 1191f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator.setText(menuItem.getTitle()); 1192f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator.measure( 1193f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 1194f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mOverflowWidth = Math.max( 1195f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator.getMeasuredWidth(), mOverflowWidth); 1196f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki } 1197f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki return mOverflowWidth; 1198f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki } 1199f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki 1200f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private ListView createOverflowListView() { 1201f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki final Context context = mContentView.getContext(); 1202517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final ListView overflowListView = new ListView(context); 1203517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListView.setLayoutParams(new ViewGroup.LayoutParams( 1204517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 1205517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListView.setDivider(null); 1206517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListView.setDividerHeight(0); 1207b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki 1208b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki final int viewTypeCount = 2; 1209b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki final int stringLabelViewType = 0; 1210b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki final int iconOnlyViewType = 1; 1211517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final ArrayAdapter overflowListViewAdapter = 1212517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new ArrayAdapter<MenuItem>(context, 0) { 1213517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 1214b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki public int getViewTypeCount() { 1215b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return viewTypeCount; 1216b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1217b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki 1218b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki @Override 1219b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki public int getItemViewType(int position) { 1220b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki if (isIconOnlyMenuItem(getItem(position))) { 1221b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return iconOnlyViewType; 1222b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1223b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return stringLabelViewType; 1224b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1225b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki 1226b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki @Override 1227517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public View getView(int position, View convertView, ViewGroup parent) { 1228b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki if (getItemViewType(position) == iconOnlyViewType) { 1229b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return getIconOnlyView(position, convertView); 1230b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1231b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return getStringTitleView(position, convertView); 1232b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1233b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki 1234b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki private View getStringTitleView(int position, View convertView) { 1235517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki TextView menuButton; 1236517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (convertView != null) { 1237517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuButton = (TextView) convertView; 1238517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } else { 1239517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuButton = createOverflowMenuItemButton(context); 1240517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1241517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki MenuItem menuItem = getItem(position); 1242517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuButton.setText(menuItem.getTitle()); 1243517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuButton.setContentDescription(menuItem.getTitle()); 1244f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuButton.setMinimumWidth(mOverflowWidth); 1245517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return menuButton; 1246517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1247b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki 1248b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki private View getIconOnlyView(int position, View convertView) { 1249b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki View menuButton; 1250b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki if (convertView != null) { 1251b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki menuButton = convertView; 1252b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } else { 1253b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki menuButton = LayoutInflater.from(context).inflate( 1254b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki R.layout.floating_popup_overflow_image_list_item, null); 1255b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1256b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki MenuItem menuItem = getItem(position); 1257b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki ((ImageView) menuButton 1258b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki .findViewById(R.id.floating_toolbar_menu_item_image_button)) 1259b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki .setImageDrawable(menuItem.getIcon()); 1260b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki menuButton.setMinimumWidth(mOverflowWidth); 1261b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return menuButton; 1262b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1263517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 1264517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListView.setAdapter(overflowListViewAdapter); 1265517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return overflowListView; 1266517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1267517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1268517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1269517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1270517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1271517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * A helper for fading in or out a view. 1272517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1273517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final class ViewFader { 1274517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1275517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final int FADE_OUT_DURATION = 250; 1276517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final int FADE_IN_DURATION = 150; 1277517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1278517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final View mView; 1279517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ObjectAnimator mFadeOutAnimation; 1280517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ObjectAnimator mFadeInAnimation; 1281517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1282517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private ViewFader(View view) { 1283517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mView = Preconditions.checkNotNull(view); 1284517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mFadeOutAnimation = ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0) 1285517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .setDuration(FADE_OUT_DURATION); 1286517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mFadeInAnimation = ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1) 1287517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .setDuration(FADE_IN_DURATION); 1288517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1289517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1290517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeIn(boolean animate) { 1291b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki cancelFadeAnimations(); 1292517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (animate) { 1293517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mFadeInAnimation.start(); 1294517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } else { 1295517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mView.setAlpha(1); 1296517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1297517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1298517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1299517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeOut(boolean animate) { 1300b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki cancelFadeAnimations(); 1301517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (animate) { 1302517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mFadeOutAnimation.start(); 1303517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } else { 1304517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mView.setAlpha(0); 1305517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1306517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1307b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 1308b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void cancelFadeAnimations() { 1309b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mFadeInAnimation.cancel(); 1310b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mFadeOutAnimation.cancel(); 1311b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 1312517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1313517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1314b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki /** 1315b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki * @return {@code true} if the menu item does not not have a string title but has an icon. 1316b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki * {@code false} otherwise. 1317b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki */ 1318b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki private static boolean isIconOnlyMenuItem(MenuItem menuItem) { 1319b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki if (TextUtils.isEmpty(menuItem.getTitle()) && menuItem.getIcon() != null) { 1320b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return true; 1321b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1322b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return false; 1323b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1324517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1325517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1326517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Creates and returns a menu button for the specified menu item. 1327517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1328b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki private static View createMenuItemButton(Context context, MenuItem menuItem) { 1329b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki if (isIconOnlyMenuItem(menuItem)) { 1330b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki View imageMenuItemButton = LayoutInflater.from(context) 1331b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki .inflate(R.layout.floating_popup_menu_image_button, null); 1332b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki ((ImageButton) imageMenuItemButton 1333b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki .findViewById(R.id.floating_toolbar_menu_item_image_button)) 1334b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki .setImageDrawable(menuItem.getIcon()); 1335b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki return imageMenuItemButton; 1336b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki } 1337b21562c4655cb8dfb73819b68b7fc8eeeab40dacAbodunrinwa Toki 1338517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Button menuItemButton = (Button) LayoutInflater.from(context) 1339517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_menu_button, null); 1340517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.setText(menuItem.getTitle()); 1341517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.setContentDescription(menuItem.getTitle()); 1342517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return menuItemButton; 1343517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1344517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1345517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1346517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Creates and returns a styled floating toolbar overflow list view item. 1347517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1348517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static TextView createOverflowMenuItemButton(Context context) { 1349517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return (TextView) LayoutInflater.from(context) 1350517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_overflow_list_item, null); 1351517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1352517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1353517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static ViewGroup createContentContainer(Context context) { 1354517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return (ViewGroup) LayoutInflater.from(context) 1355517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_container, null); 1356517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1357517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1358517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static PopupWindow createPopupWindow(View content) { 1359517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup popupContentHolder = new LinearLayout(content.getContext()); 1360517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki PopupWindow popupWindow = new PopupWindow(popupContentHolder); 1361103d48ec09cbaeedf28b66425cde9198f767e0d5Abodunrinwa Toki popupWindow.setWindowLayoutType( 1362103d48ec09cbaeedf28b66425cde9198f767e0d5Abodunrinwa Toki WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL); 1363517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki popupWindow.setAnimationStyle(0); 1364517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 1365517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki content.setLayoutParams(new ViewGroup.LayoutParams( 1366517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 1367517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki popupContentHolder.addView(content); 1368517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return popupWindow; 1369517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1370517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1371517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 13727aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki * Creates an "appear" animation for the specified view. 1373517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 1374517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param view The view to animate 1375517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 13767aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki private static AnimatorSet createEnterAnimation(View view) { 13777aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki AnimatorSet animation = new AnimatorSet(); 13787aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki animation.playTogether( 13797aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(200), 13806c5ac8e9e6b4b06c460cd2231cdeb93b373efe5dAbodunrinwa Toki // Make sure that view.x is always fixed throughout the duration of this animation. 13816cb5cc19d467251d2e1e28791bf070f4ea6a2eedAbodunrinwa Toki ObjectAnimator.ofFloat(view, View.X, view.getX(), view.getX())); 13827aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki animation.setStartDelay(50); 13837aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki return animation; 1384517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1385517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1386517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 13877aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki * Creates a "disappear" animation for the specified view. 1388517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 1389517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param view The view to animate 1390cdffaa4c5af71b4bd0c99a98d411ee3883ec4733Abodunrinwa Toki * @param startDelay The start delay of the animation 1391517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param listener The animation listener 1392517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 13937aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki private static AnimatorSet createExitAnimation( 1394cdffaa4c5af71b4bd0c99a98d411ee3883ec4733Abodunrinwa Toki View view, int startDelay, Animator.AnimatorListener listener) { 13957aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki AnimatorSet animation = new AnimatorSet(); 13967aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki animation.playTogether( 13977aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(200)); 13987aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki animation.setStartDelay(startDelay); 13997aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki animation.addListener(listener); 14007aa6d0a4b1ec7f75335348a86284d3773cc72f91Abodunrinwa Toki return animation; 1401517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1402517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1403517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getEstimatedToolbarHeight(Context context) { 1404517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return context.getResources().getDimensionPixelSize(R.dimen.floating_toolbar_height); 1405517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1406517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1407517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getEstimatedOpenOverflowButtonWidth(Context context) { 1408517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return context.getResources() 1409517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_menu_button_minimum_width); 1410517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1411517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1412517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getAdjustedToolbarWidth(Context context, int width) { 1413c0fa6bd7ac8fa8f138c62d734d276e55d600bb6bAbodunrinwa Toki int maximumWidth = getScreenWidth(context) - 2 * context.getResources() 1414c0fa6bd7ac8fa8f138c62d734d276e55d600bb6bAbodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); 1415c0fa6bd7ac8fa8f138c62d734d276e55d600bb6bAbodunrinwa Toki 1416c0fa6bd7ac8fa8f138c62d734d276e55d600bb6bAbodunrinwa Toki if (width <= 0 || width > maximumWidth) { 1417c0fa6bd7ac8fa8f138c62d734d276e55d600bb6bAbodunrinwa Toki int defaultWidth = context.getResources() 1418c0fa6bd7ac8fa8f138c62d734d276e55d600bb6bAbodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_preferred_width); 1419c0fa6bd7ac8fa8f138c62d734d276e55d600bb6bAbodunrinwa Toki width = Math.min(defaultWidth, maximumWidth); 1420517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1421517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return width; 1422517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1423517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1424517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1425517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns the device's screen width. 1426517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1427517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getScreenWidth(Context context) { 1428517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return context.getResources().getDisplayMetrics().widthPixels; 1429517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1430517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1431517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1432517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns the device's screen height. 1433517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1434517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getScreenHeight(Context context) { 1435517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return context.getResources().getDisplayMetrics().heightPixels; 1436517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 14370c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki} 1438