FloatingToolbar.java revision d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1
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; 29517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.util.Size; 300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.Gravity; 310c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.LayoutInflater; 320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.Menu; 330c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.MenuItem; 340c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.View; 350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.View.MeasureSpec; 360c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.ViewGroup; 37517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.ViewTreeObserver; 380c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.view.Window; 39517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.WindowManager; 40517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.animation.Animation; 41517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.animation.AnimationSet; 42517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.view.animation.Transformation; 43517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.widget.AdapterView; 44517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.widget.ArrayAdapter; 450c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.widget.Button; 460c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.widget.ImageButton; 470c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.widget.LinearLayout; 48517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.widget.ListView; 490c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport android.widget.PopupWindow; 50517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport android.widget.TextView; 510c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 520c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport java.util.ArrayList; 530c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport java.util.LinkedList; 540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokiimport java.util.List; 550c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 56517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport com.android.internal.R; 57517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Tokiimport com.android.internal.util.Preconditions; 58517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 590c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki/** 600c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * A floating toolbar for showing contextual menu items. 610c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * This view shows as many menu item buttons as can fit in the horizontal toolbar and the 620c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * the remaining menu items in a vertical overflow view when the overflow button is clicked. 630c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * The horizontal toolbar morphs into the vertical overflow view. 640c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 650c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Tokipublic final class FloatingToolbar { 660c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 67517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki // This class is responsible for the public API of the floating toolbar. 68517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki // It delegates rendering operations to the FloatingToolbarPopup. 69517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 700c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private static final MenuItem.OnMenuItemClickListener NO_OP_MENUITEM_CLICK_LISTENER = 710c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki new MenuItem.OnMenuItemClickListener() { 720c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki @Override 730c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public boolean onMenuItemClick(MenuItem item) { 740c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return false; 750c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 760c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki }; 770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 780c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private final Context mContext; 790c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private final FloatingToolbarPopup mPopup; 800c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 810c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private final Rect mContentRect = new Rect(); 820c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private final Point mCoordinates = new Point(); 830c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 840c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private Menu mMenu; 850c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private List<CharSequence> mShowingTitles = new ArrayList<CharSequence>(); 860c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; 870c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 880c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private int mSuggestedWidth; 89517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private boolean mWidthChanged = true; 90517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private int mOverflowDirection; 910c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 920c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 930c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Initializes a floating toolbar. 940c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 950c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar(Context context, Window window) { 960c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mContext = Preconditions.checkNotNull(context); 97517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopup = new FloatingToolbarPopup(window.getDecorView()); 980c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 990c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1000c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1010c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Sets the menu to be shown in this floating toolbar. 1020c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the 1030c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * toolbar. 1040c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1050c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar setMenu(Menu menu) { 1060c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mMenu = Preconditions.checkNotNull(menu); 1070c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1080c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1090c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1100c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1117270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Sets the custom listener for invocation of menu items in this floating toolbar. 1120c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1130c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar setOnMenuItemClickListener( 1140c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki MenuItem.OnMenuItemClickListener menuItemClickListener) { 1150c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (menuItemClickListener != null) { 1160c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mMenuItemClickListener = menuItemClickListener; 1170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } else { 1180c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; 1190c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1200c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1210c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1220c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Sets the content rectangle. This is the area of the interesting content that this toolbar 1250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * should avoid obstructing. 1260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the 1270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * toolbar. 1280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar setContentRect(Rect rect) { 1300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mContentRect.set(Preconditions.checkNotNull(rect)); 1310c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1330c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1340c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Sets the suggested width of this floating toolbar. 1360c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * The actual width will be about this size but there are no guarantees that it will be exactly 1370c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * the suggested width. 1380c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the 1390c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * toolbar. 1400c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1410c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar setSuggestedWidth(int suggestedWidth) { 142517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki // Check if there's been a substantial width spec change. 143517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int difference = Math.abs(suggestedWidth - mSuggestedWidth); 144517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mWidthChanged = difference > (mSuggestedWidth * 0.2); 145517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1460c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mSuggestedWidth = suggestedWidth; 1470c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1480c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1490c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1500c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1510c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Shows this floating toolbar. 1520c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1530c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar show() { 1540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu); 155517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (!isCurrentlyShowing(menuItems) || mWidthChanged) { 1560c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mPopup.dismiss(); 157517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth); 1580c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mShowingTitles = getMenuItemTitles(menuItems); 1590c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1600c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki refreshCoordinates(); 161517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopup.setOverflowDirection(mOverflowDirection); 1620c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mPopup.updateCoordinates(mCoordinates.x, mCoordinates.y); 1630c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (!mPopup.isShowing()) { 1640c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mPopup.show(mCoordinates.x, mCoordinates.y); 1650c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 166517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mWidthChanged = false; 1670c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1680c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1690c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1700c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1710c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Updates this floating toolbar to reflect recent position and view updates. 1720c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * NOTE: This method is a no-op if the toolbar isn't showing. 1730c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1740c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbar updateLayout() { 1750c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (mPopup.isShowing()) { 1760c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki // show() performs all the logic we need here. 1770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki show(); 1780c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1790c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return this; 1800c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1810c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1820c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1830c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Dismisses this floating toolbar. 1840c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1850c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public void dismiss() { 1860c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mPopup.dismiss(); 1870c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1880c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 1890c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1907270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Hides this floating toolbar. This is a no-op if the toolbar is not showing. 1917270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Use {@link #isHidden()} to distinguish between a hidden and a dismissed toolbar. 1927270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 1937270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public void hide() { 1947270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mPopup.hide(); 1957270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 1967270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 1977270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 1987270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Returns {@code true} if this toolbar is currently showing. {@code false} otherwise. 1990c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 2000c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public boolean isShowing() { 2010c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return mPopup.isShowing(); 2020c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2030c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2040c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 2057270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Returns {@code true} if this toolbar is currently hidden. {@code false} otherwise. 2067270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 2077270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public boolean isHidden() { 2087270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki return mPopup.isHidden(); 2097270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 2107270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 2117270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 2120c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Refreshes {@link #mCoordinates} with values based on {@link #mContentRect}. 2130c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 2140c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private void refreshCoordinates() { 215517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int x = mContentRect.centerX() - mPopup.getWidth() / 2; 2160c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki int y; 217517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mContentRect.top > mPopup.getHeight()) { 218517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki y = mContentRect.top - mPopup.getHeight(); 219517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_UP; 220f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki } else if (mContentRect.top > mPopup.getToolbarHeightWithVerticalMargin()) { 221f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki y = mContentRect.top - mPopup.getToolbarHeightWithVerticalMargin(); 222517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN; 2230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } else { 2240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki y = mContentRect.bottom; 225517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN; 2260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mCoordinates.set(x, y); 2280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 231517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns true if this floating toolbar is currently showing the specified menu items. 2320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 233517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private boolean isCurrentlyShowing(List<MenuItem> menuItems) { 234517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mShowingTitles.equals(getMenuItemTitles(menuItems)); 2350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2360c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2370c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 2380c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns the visible and enabled menu items in the specified menu. 2390c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * This method is recursive. 2400c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 2410c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private List<MenuItem> getVisibleAndEnabledMenuItems(Menu menu) { 2420c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki List<MenuItem> menuItems = new ArrayList<MenuItem>(); 2430c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki for (int i = 0; (menu != null) && (i < menu.size()); i++) { 2440c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki MenuItem menuItem = menu.getItem(i); 2450c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (menuItem.isVisible() && menuItem.isEnabled()) { 2460c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki Menu subMenu = menuItem.getSubMenu(); 2470c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (subMenu != null) { 2480c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki menuItems.addAll(getVisibleAndEnabledMenuItems(subMenu)); 2490c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } else { 2500c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki menuItems.add(menuItem); 2510c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2520c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2530c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return menuItems; 2550c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2560c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2570c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki private List<CharSequence> getMenuItemTitles(List<MenuItem> menuItems) { 2580c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki List<CharSequence> titles = new ArrayList<CharSequence>(); 2590c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki for (MenuItem menuItem : menuItems) { 2600c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki titles.add(menuItem.getTitle()); 2610c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2620c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return titles; 2630c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 2640c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2650c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 2660c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 267517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * A popup window used by the floating toolbar. 268517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 269517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This class is responsible for the rendering/animation of the floating toolbar. 270517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * It can hold one of 2 panels (i.e. main panel and overflow panel) at a time. 271517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * It delegates specific panel functionality to the appropriate panel. 2720c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 273517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final class FloatingToolbarPopup { 2740c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 275517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public static final int OVERFLOW_DIRECTION_UP = 0; 276517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public static final int OVERFLOW_DIRECTION_DOWN = 1; 2770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 278517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final View mParent; 279517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final PopupWindow mPopupWindow; 280517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewGroup mContentContainer; 281f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private final int mMarginHorizontal; 282f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private final int mMarginVertical; 2830c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 284517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Animation.AnimationListener mOnOverflowOpened = 285517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new Animation.AnimationListener() { 286517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 287517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationStart(Animation animation) {} 2880c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 289517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 290517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationEnd(Animation animation) { 291b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setOverflowPanelAsContent(); 292517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.fadeIn(true); 293517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 2940c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 295517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 296517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationRepeat(Animation animation) {} 297517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 298517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Animation.AnimationListener mOnOverflowClosed = 299517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new Animation.AnimationListener() { 300517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 301517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationStart(Animation animation) {} 3020c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 303517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 304517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationEnd(Animation animation) { 305b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setMainPanelAsContent(); 306517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel.fadeIn(true); 307517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 3080c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 3090c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki @Override 310517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationRepeat(Animation animation) { 3110c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 3120c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki }; 3137270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private final AnimatorSet mShowAnimation; 3147270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private final AnimatorSet mDismissAnimation; 3157270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private final AnimatorSet mHideAnimation; 316b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true) { 317b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki @Override 318b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki public void cancel() { 319b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (hasStarted() && !hasEnded()) { 320b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki super.cancel(); 321b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setOverflowPanelAsContent(); 322b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 323b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 324b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki }; 325b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private final AnimationSet mCloseOverflowAnimation = new AnimationSet(true) { 326b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki @Override 327b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki public void cancel() { 328b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (hasStarted() && !hasEnded()) { 329b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki super.cancel(); 330b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setMainPanelAsContent(); 331b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 332b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 333b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki }; 3340c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 335517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Runnable mOpenOverflow = new Runnable() { 336517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 337517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void run() { 338517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki openOverflow(); 339517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 340517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 341517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Runnable mCloseOverflow = new Runnable() { 342517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 343517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void run() { 344517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki closeOverflow(); 345517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 346517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 347517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 348517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Region mTouchableRegion = new Region(); 349d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = 350d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki new ViewTreeObserver.OnComputeInternalInsetsListener() { 351d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki public void onComputeInternalInsets( 352d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki ViewTreeObserver.InternalInsetsInfo info) { 353d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki info.contentInsets.setEmpty(); 354d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki info.visibleInsets.setEmpty(); 355d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki info.touchableRegion.set(mTouchableRegion); 356d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo 357d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki .TOUCHABLE_INSETS_REGION); 358d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki } 359d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki }; 360517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 3617270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private boolean mDismissed = true; // tracks whether this popup is dismissed or dismissing. 3627270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private boolean mHidden; // tracks whether this popup is hidden or hiding. 3630c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 364517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private FloatingToolbarOverflowPanel mOverflowPanel; 365517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private FloatingToolbarMainPanel mMainPanel; 366517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private int mOverflowDirection; 367517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 3680c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 369517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Initializes a new floating toolbar popup. 3700c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 371517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param parent A parent view to get the {@link android.view.View#getWindowToken()} token 372517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * from. 3730c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 3740c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public FloatingToolbarPopup(View parent) { 3750c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mParent = Preconditions.checkNotNull(parent); 3760c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mContentContainer = createContentContainer(parent.getContext()); 3770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki mPopupWindow = createPopupWindow(mContentContainer); 3787270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mShowAnimation = createGrowFadeInFromBottom(mContentContainer); 3797270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissAnimation = createShrinkFadeOutFromBottomAnimation( 380517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer, 381517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new AnimatorListenerAdapter() { 382517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 383517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onAnimationEnd(Animator animation) { 384517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopupWindow.dismiss(); 385b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.removeAllViews(); 386517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 387517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }); 3887270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHideAnimation = createShrinkFadeOutFromBottomAnimation( 3897270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mContentContainer, 3907270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki new AnimatorListenerAdapter() { 3917270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki @Override 3927270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public void onAnimationEnd(Animator animation) { 3937270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mPopupWindow.dismiss(); 3947270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 3957270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki }); 396f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mMarginHorizontal = parent.getResources() 397f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); 398f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mMarginVertical = parent.getResources() 399f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_vertical_margin); 400517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 401517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 402517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 403517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Lays out buttons for the specified menu items. 404517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 405517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void layoutMenuItems(List<MenuItem> menuItems, 406517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki MenuItem.OnMenuItemClickListener menuItemClickListener, int suggestedWidth) { 407517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.removeAllViews(); 408517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mMainPanel == null) { 409517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel = new FloatingToolbarMainPanel(mParent.getContext(), mOpenOverflow); 410517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 411517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki List<MenuItem> overflowMenuItems = 412517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel.layoutMenuItems(menuItems, suggestedWidth); 413517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel.setOnMenuItemClickListener(menuItemClickListener); 414517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (!overflowMenuItems.isEmpty()) { 415517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOverflowPanel == null) { 416517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel = 417517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new FloatingToolbarOverflowPanel(mParent.getContext(), mCloseOverflow); 418517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 419517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.setMenuItems(overflowMenuItems); 420517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.setOnMenuItemClickListener(menuItemClickListener); 421517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 422517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki updatePopupSize(); 4230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4240c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 4260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Shows this popup at the specified coordinates. 4270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. 4280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 4290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public void show(int x, int y) { 4300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (isShowing()) { 4310c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return; 4320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4330c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4347270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHidden = false; 4357270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissed = false; 436b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki cancelAllAnimations(); 437b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // Make sure a panel is set as the content. 438b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (mContentContainer.getChildCount() == 0) { 439b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setMainPanelAsContent(); 440b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 441517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki preparePopupContent(); 442b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // If we're yet to show the popup, set the container visibility to zero. 443b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // The "show" animation will make this visible. 444b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setAlpha(0); 445517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, x, y); 446d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki setTouchableSurfaceInsetsComputer(); 4477270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki runShowAnimation(); 4480c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4490c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4500c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 4510c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Gets rid of this popup. If the popup isn't currently showing, this will be a no-op. 4520c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 4530c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public void dismiss() { 4540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki if (!isShowing()) { 4550c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return; 4560c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4570c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4587270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHidden = false; 4597270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissed = true; 4607270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki runDismissAnimation(); 4617270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki setZeroTouchableSurface(); 4627270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 4637270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 4647270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 4657270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Hides this popup. This is a no-op if this popup is not showing. 4667270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Use {@link #isHidden()} to distinguish between a hidden and a dismissed popup. 4677270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 4687270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public void hide() { 4697270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki if (!isShowing()) { 4707270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki return; 4717270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 4727270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 4737270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHidden = true; 4747270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki runHideAnimation(); 475517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki setZeroTouchableSurface(); 4760c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4780c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 4790c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns {@code true} if this popup is currently showing. {@code false} otherwise. 4800c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 4810c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public boolean isShowing() { 4827270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki return mPopupWindow.isShowing() && !mDismissed && !mHidden; 4837270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 4847270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 4857270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 4867270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Returns {@code true} if this popup is currently hidden. {@code false} otherwise. 4877270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 4887270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki public boolean isHidden() { 4897270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki return mHidden; 4900c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 4910c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 4920c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 4930c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Updates the coordinates of this popup. 4940c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. 4957270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * This is a no-op if this popup is not showing. 4960c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 4970c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public void updateCoordinates(int x, int y) { 4987270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki if (!isShowing()) { 499517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return; 5000c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 501517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 502b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki cancelAllAnimations(); 503517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki preparePopupContent(); 504517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mPopupWindow.update(x, y, getWidth(), getHeight()); 5050c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5060c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5070c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 508517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the direction in which the overflow will open. i.e. up or down. 509517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 510517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param overflowDirection Either {@link #OVERFLOW_DIRECTION_UP} 511517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * or {@link #OVERFLOW_DIRECTION_DOWN}. 5120c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 513517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setOverflowDirection(int overflowDirection) { 514517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowDirection = overflowDirection; 515517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOverflowPanel != null) { 516517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.setOverflowDirection(mOverflowDirection); 517517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 5180c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5190c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5200c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5210c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns the width of this popup. 5220c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5230c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public int getWidth() { 524517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mPopupWindow.getWidth(); 5250c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5260c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5270c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns the height of this popup. 5290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public int getHeight() { 531517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mPopupWindow.getHeight(); 5320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5330c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5340c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * Returns the context this popup is running in. 5360c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5370c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki public Context getContext() { 5380c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki return mContentContainer.getContext(); 5390c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5400c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 541f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki int getToolbarHeightWithVerticalMargin() { 542f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki return getEstimatedToolbarHeight(mParent.getContext()) + mMarginVertical * 2; 543f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki } 544f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki 5450c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5467270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Performs the "show" animation on the floating popup. 5477270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki */ 5487270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private void runShowAnimation() { 5497270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mShowAnimation.start(); 5507270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki } 5517270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki 5527270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki /** 5537270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Performs the "dismiss" animation on the floating popup. 5540c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5557270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private void runDismissAnimation() { 5567270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissAnimation.start(); 5570c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5580c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 5590c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 5607270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki * Performs the "hide" animation on the floating popup. 5610c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 5627270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki private void runHideAnimation() { 5637270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHideAnimation.start(); 5640c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 5650c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 566b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void cancelAllAnimations() { 567b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mShowAnimation.cancel(); 5687270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mDismissAnimation.cancel(); 5697270d07aab00c30c7f339963d3e9312456a2462eAbodunrinwa Toki mHideAnimation.cancel(); 570b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.cancel(); 571b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.cancel(); 572517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 573517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 574517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 575517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Opens the floating toolbar overflow. 576517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This method should not be called if menu items have not been laid out with 577b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, int)}. 578517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 579517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @throws IllegalStateException if called when menu items have not been laid out. 580517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 581517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void openOverflow() { 582b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkState(mMainPanel != null); 583b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkState(mOverflowPanel != null); 584517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 585517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mMainPanel.fadeOut(true); 586517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size overflowPanelSize = mOverflowPanel.measure(); 587f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki final int targetWidth = overflowPanelSize.getWidth(); 588517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int targetHeight = overflowPanelSize.getHeight(); 589517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final boolean morphUpwards = (mOverflowDirection == OVERFLOW_DIRECTION_UP); 590517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int startWidth = mContentContainer.getWidth(); 591517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int startHeight = mContentContainer.getHeight(); 592517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final float startY = mContentContainer.getY(); 593517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final float right = mContentContainer.getX() + mContentContainer.getWidth(); 594517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Animation widthAnimation = new Animation() { 595517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 596517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki protected void applyTransformation(float interpolatedTime, Transformation t) { 597517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 598517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth)); 599517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.width = startWidth + deltaWidth; 600517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 601517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setX(right - mContentContainer.getWidth()); 602517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 603517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 604517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Animation heightAnimation = new Animation() { 605517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 606517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki protected void applyTransformation(float interpolatedTime, Transformation t) { 607517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 608517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int deltaHeight = (int) (interpolatedTime * (targetHeight - startHeight)); 609517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.height = startHeight + deltaHeight; 610517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 611517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (morphUpwards) { 612517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki float y = startY - (mContentContainer.getHeight() - startHeight); 613517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setY(y); 614517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 615517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 616517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 617517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki widthAnimation.setDuration(240); 618517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki heightAnimation.setDuration(180); 619517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki heightAnimation.setStartOffset(60); 620b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.getAnimations().clear(); 621b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.setAnimationListener(mOnOverflowOpened); 622b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.addAnimation(widthAnimation); 623b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mOpenOverflowAnimation.addAnimation(heightAnimation); 624b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.startAnimation(mOpenOverflowAnimation); 625517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 626517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 627517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 628517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Opens the floating toolbar overflow. 629517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This method should not be called if menu items have not been laid out with 630517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, int)}. 631517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 632b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * @throws IllegalStateException if called when menu items have not been laid out. 633517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 634517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void closeOverflow() { 635b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkState(mMainPanel != null); 636b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkState(mOverflowPanel != null); 637517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 638517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.fadeOut(true); 639517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size mainPanelSize = mMainPanel.measure(); 640517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int targetWidth = mainPanelSize.getWidth(); 641517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int targetHeight = mainPanelSize.getHeight(); 642517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int startWidth = mContentContainer.getWidth(); 643517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int startHeight = mContentContainer.getHeight(); 644517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final float right = mContentContainer.getX() + mContentContainer.getWidth(); 645517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final float bottom = mContentContainer.getY() + mContentContainer.getHeight(); 646517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final boolean morphedUpwards = (mOverflowDirection == OVERFLOW_DIRECTION_UP); 647517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Animation widthAnimation = new Animation() { 648517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 649517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki protected void applyTransformation(float interpolatedTime, Transformation t) { 650517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 651517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth)); 652517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.width = startWidth + deltaWidth; 653517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 654517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setX(right - mContentContainer.getWidth()); 655517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 656517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 657517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Animation heightAnimation = new Animation() { 658517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 659517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki protected void applyTransformation(float interpolatedTime, Transformation t) { 660517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 661517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int deltaHeight = (int) (interpolatedTime * (targetHeight - startHeight)); 662517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.height = startHeight + deltaHeight; 663517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 664517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (morphedUpwards) { 665517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setY(bottom - mContentContainer.getHeight()); 666517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 667517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 668517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 669517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki widthAnimation.setDuration(150); 670517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki widthAnimation.setStartOffset(150); 671517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki heightAnimation.setDuration(210); 672b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.getAnimations().clear(); 673b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.setAnimationListener(mOnOverflowClosed); 674b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.addAnimation(widthAnimation); 675b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mCloseOverflowAnimation.addAnimation(heightAnimation); 676b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.startAnimation(mCloseOverflowAnimation); 677517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 678517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 679517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 680517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Prepares the content container for show and update calls. 681517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 682517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void preparePopupContent() { 683b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // Reset visibility. 684b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (mMainPanel != null) { 685b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mMainPanel.fadeIn(false); 686517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 687517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOverflowPanel != null) { 688517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOverflowPanel.fadeIn(false); 689517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 690517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 691b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // Reset position. 692b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (mMainPanel != null 693b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki && mContentContainer.getChildAt(0) == mMainPanel.getView()) { 694b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki positionMainPanel(); 695517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 696b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (mOverflowPanel != null 697b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki && mContentContainer.getChildAt(0) == mOverflowPanel.getView()) { 698b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki positionOverflowPanel(); 699517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 700517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 701517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 702517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 703517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the current content to be the main view panel. 704517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 705517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void setMainPanelAsContent() { 706b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // This should never be called if the main panel has not been initialized. 707b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkNotNull(mMainPanel); 708517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.removeAllViews(); 709517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size mainPanelSize = mMainPanel.measure(); 710517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 711517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.width = mainPanelSize.getWidth(); 712517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.height = mainPanelSize.getHeight(); 713517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.setLayoutParams(params); 714517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.addView(mMainPanel.getView()); 715b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setContentAreaAsTouchableSurface(); 716b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 717b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 718b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki /** 719b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * Sets the current content to be the overflow view panel. 720b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki */ 721b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void setOverflowPanelAsContent() { 722b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki // This should never be called if the overflow panel has not been initialized. 723b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkNotNull(mOverflowPanel); 724b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.removeAllViews(); 725b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Size overflowPanelSize = mOverflowPanel.measure(); 726b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); 727b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki params.width = overflowPanelSize.getWidth(); 728b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki params.height = overflowPanelSize.getHeight(); 729b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setLayoutParams(params); 730b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.addView(mOverflowPanel.getView()); 731b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setContentAreaAsTouchableSurface(); 732b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 733b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 734b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki /** 735b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * Places the main view panel at the appropriate resting coordinates. 736b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki */ 737b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void positionMainPanel() { 738b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkNotNull(mMainPanel); 739b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki float x = mPopupWindow.getWidth() 740b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki - (mMainPanel.getView().getMeasuredWidth() + mMarginHorizontal); 741b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setX(x); 742b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 743b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki float y = mMarginVertical; 744b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki if (mOverflowDirection == OVERFLOW_DIRECTION_UP) { 745b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki y = getHeight() 746b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki - (mMainPanel.getView().getMeasuredHeight() + mMarginVertical); 747b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 748b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setY(y); 749b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setContentAreaAsTouchableSurface(); 750b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 751b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 752b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki /** 753b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki * Places the main view panel at the appropriate resting coordinates. 754b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki */ 755b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void positionOverflowPanel() { 756b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki Preconditions.checkNotNull(mOverflowPanel); 757b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki float x = mPopupWindow.getWidth() 758b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki - (mOverflowPanel.getView().getMeasuredWidth() + mMarginHorizontal); 759b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setX(x); 760b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mContentContainer.setY(mMarginVertical); 761b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki setContentAreaAsTouchableSurface(); 762517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 763517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 764517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void updatePopupSize() { 765517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int width = 0; 766517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int height = 0; 767517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mMainPanel != null) { 768517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size mainPanelSize = mMainPanel.measure(); 769517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki width = mainPanelSize.getWidth(); 770517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki height = mainPanelSize.getHeight(); 771517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 772517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOverflowPanel != null) { 773517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Size overflowPanelSize = mOverflowPanel.measure(); 774517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki width = Math.max(width, overflowPanelSize.getWidth()); 775517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki height = Math.max(height, overflowPanelSize.getHeight()); 776517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 777f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mPopupWindow.setWidth(width + mMarginHorizontal * 2); 778f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mPopupWindow.setHeight(height + mMarginVertical * 2); 779517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 780517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 781517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 782517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the touchable region of this popup to be zero. This means that all touch events on 783517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * this popup will go through to the surface behind it. 784517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 785517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void setZeroTouchableSurface() { 786517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mTouchableRegion.setEmpty(); 787517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 788517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 789517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 790517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the touchable region of this popup to be the area occupied by its content. 791517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 792517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void setContentAreaAsTouchableSurface() { 793517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (!mPopupWindow.isShowing()) { 794517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentContainer.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 795517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 796517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int width = mContentContainer.getMeasuredWidth(); 797517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int height = mContentContainer.getMeasuredHeight(); 798517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mTouchableRegion.set( 799517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki (int) mContentContainer.getX(), 800517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki (int) mContentContainer.getY(), 801517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki (int) mContentContainer.getX() + width, 802517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki (int) mContentContainer.getY() + height); 803517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 804d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki 805d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki /** 806d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki * Make the touchable area of this popup be the area specified by mTouchableRegion. 807d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki * This should be called after the popup window has been dismissed (dismiss/hide) 808d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki * and is probably being re-shown with a new content root view. 809d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki */ 810d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki private void setTouchableSurfaceInsetsComputer() { 811d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki ViewTreeObserver viewTreeObserver = mPopupWindow.getContentView() 812d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki .getRootView() 813d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki .getViewTreeObserver(); 814d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki viewTreeObserver.removeOnComputeInternalInsetsListener(mInsetsComputer); 815d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki viewTreeObserver.addOnComputeInternalInsetsListener(mInsetsComputer); 816d5358ffbee845ecb2ab3e1ebdfec3823104c0dd1Abodunrinwa Toki } 817517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 818517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 819517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 820517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * A widget that holds the primary menu items in the floating toolbar. 821517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 822517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final class FloatingToolbarMainPanel { 823517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 824517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Context mContext; 825517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewGroup mContentView; 826517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final View.OnClickListener mMenuItemButtonOnClickListener = 827517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new View.OnClickListener() { 828517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 829517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onClick(View v) { 830517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (v.getTag() instanceof MenuItem) { 831517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOnMenuItemClickListener != null) { 832517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOnMenuItemClickListener.onMenuItemClick((MenuItem) v.getTag()); 833517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 834517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 835517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 836517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 837517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewFader viewFader; 838517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Runnable mOpenOverflow; 839517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 840517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private View mOpenOverflowButton; 841517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener; 842517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 843517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 844517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Initializes a floating toolbar popup main view panel. 845517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 846517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param context 847517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param openOverflow The code that opens the toolbar popup overflow. 848517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 849517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public FloatingToolbarMainPanel(Context context, Runnable openOverflow) { 850517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContext = Preconditions.checkNotNull(context); 851517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView = new LinearLayout(context); 852517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki viewFader = new ViewFader(mContentView); 853517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOpenOverflow = Preconditions.checkNotNull(openOverflow); 854517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 855517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 8560c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 857517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Fits as many menu items in the main panel and returns a list of the menu items that 858517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * were not fit in. 859517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 860517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @return The menu items that are not included in this main panel. 8610c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 862517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public List<MenuItem> layoutMenuItems(List<MenuItem> menuItems, int suggestedWidth) { 863517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final int toolbarWidth = getAdjustedToolbarWidth(mContext, suggestedWidth) 864517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki // Reserve space for the "open overflow" button. 865517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki - getEstimatedOpenOverflowButtonWidth(mContext); 866517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 867517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int availableWidth = toolbarWidth; 868517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final LinkedList<MenuItem> remainingMenuItems = new LinkedList<MenuItem>(menuItems); 869517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 870517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.removeAllViews(); 871517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 872517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki boolean isFirstItem = true; 873517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki while (!remainingMenuItems.isEmpty()) { 874517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final MenuItem menuItem = remainingMenuItems.peek(); 875517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Button menuItemButton = createMenuItemButton(mContext, menuItem); 876517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 877f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki // Adding additional start padding for the first button to even out button spacing. 878517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (isFirstItem) { 879f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuItemButton.setPaddingRelative( 880f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki (int) (1.5 * menuItemButton.getPaddingStart()), 881517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.getPaddingTop(), 882f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuItemButton.getPaddingEnd(), 883517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.getPaddingBottom()); 884517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki isFirstItem = false; 885517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 886517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 887f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki // Adding additional end padding for the last button to even out button spacing. 888517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (remainingMenuItems.size() == 1) { 889f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuItemButton.setPaddingRelative( 890f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuItemButton.getPaddingStart(), 891517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.getPaddingTop(), 892f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki (int) (1.5 * menuItemButton.getPaddingEnd()), 893517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.getPaddingBottom()); 894517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 895517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 896517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 897517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth); 898517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (menuItemButtonWidth <= availableWidth) { 899517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.setTag(menuItem); 900517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.setOnClickListener(mMenuItemButtonOnClickListener); 901517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(menuItemButton); 902517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = menuItemButton.getLayoutParams(); 903517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.width = menuItemButtonWidth; 904517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.setLayoutParams(params); 905517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki availableWidth -= menuItemButtonWidth; 906517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki remainingMenuItems.pop(); 907517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } else { 908517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOpenOverflowButton == null) { 909517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOpenOverflowButton = (ImageButton) LayoutInflater.from(mContext) 910517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_open_overflow_button, null); 911517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOpenOverflowButton.setOnClickListener(new View.OnClickListener() { 912517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 913517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onClick(View v) { 914517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOpenOverflowButton != null) { 915517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOpenOverflow.run(); 916517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 917517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 918517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }); 919517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 920517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(mOpenOverflowButton); 921517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki break; 922517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 923517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 924517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return remainingMenuItems; 925517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 926517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 927517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener listener) { 928517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOnMenuItemClickListener = listener; 9290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 9300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 931517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public View getView() { 932517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mContentView; 9330c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 9340c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 935517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeIn(boolean animate) { 936517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki viewFader.fadeIn(animate); 937517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 938517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 939517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeOut(boolean animate) { 940517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki viewFader.fadeOut(animate); 9410c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 9420c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 9430c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 944517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns how big this panel's view should be. 945517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This method should only be called when the view has not been attached to a parent 946517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * otherwise it will throw an illegal state. 947517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 948517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public Size measure() throws IllegalStateException { 949517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Preconditions.checkState(mContentView.getParent() == null); 950517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 951517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return new Size(mContentView.getMeasuredWidth(), mContentView.getMeasuredHeight()); 952517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 953517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 954517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 955517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 956517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 957517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * A widget that holds the overflow items in the floating toolbar. 958517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 959517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final class FloatingToolbarOverflowPanel { 960517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 961517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final LinearLayout mContentView; 962517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewGroup mBackButtonContainer; 963517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final View mBackButton; 964517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ListView mListView; 965f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private final TextView mListViewItemWidthCalculator; 966517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ViewFader mViewFader; 967517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final Runnable mCloseOverflow; 968517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 969517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener; 970f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private int mOverflowWidth = 0; 971517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 972517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 973517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Initializes a floating toolbar popup overflow view panel. 9740c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 975517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param context 976517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param closeOverflow The code that closes the toolbar popup's overflow. 977517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 978517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public FloatingToolbarOverflowPanel(Context context, Runnable closeOverflow) { 979517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mCloseOverflow = Preconditions.checkNotNull(closeOverflow); 980517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 981517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView = new LinearLayout(context); 982517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.setOrientation(LinearLayout.VERTICAL); 983517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mViewFader = new ViewFader(mContentView); 984517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 985517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mBackButton = LayoutInflater.from(context) 986517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_close_overflow_button, null); 987517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mBackButton.setOnClickListener(new View.OnClickListener() { 988517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 989517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onClick(View v) { 990517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mCloseOverflow.run(); 991517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 992517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }); 993517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mBackButtonContainer = new LinearLayout(context); 994517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mBackButtonContainer.addView(mBackButton); 995517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 996f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListView = createOverflowListView(); 997517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 998517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 999517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 1000517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki MenuItem menuItem = (MenuItem) mListView.getAdapter().getItem(position); 1001517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (mOnMenuItemClickListener != null) { 1002517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOnMenuItemClickListener.onMenuItemClick(menuItem); 1003517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1004517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1005517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }); 1006517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1007517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(mListView); 1008517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(mBackButtonContainer); 1009f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki 1010f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator = createOverflowMenuItemButton(context); 1011f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator.setLayoutParams(new ViewGroup.LayoutParams( 1012f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 1013517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1014517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1015517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1016517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Sets the menu items to be displayed in the overflow. 10170c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1018517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setMenuItems(List<MenuItem> menuItems) { 1019517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ArrayAdapter overflowListViewAdapter = (ArrayAdapter) mListView.getAdapter(); 1020517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListViewAdapter.clear(); 1021517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListViewAdapter.addAll(menuItems); 1022517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki setListViewHeight(); 1023f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki setOverflowWidth(); 1024517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1025517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1026517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener listener) { 1027517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mOnMenuItemClickListener = listener; 10280c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 10290c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 10300c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1031517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Notifies the overflow of the current direction in which the overflow will be opened. 10320c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 1033517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param overflowDirection {@link FloatingToolbarPopup#OVERFLOW_DIRECTION_UP} 1034517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * or {@link FloatingToolbarPopup#OVERFLOW_DIRECTION_DOWN}. 10350c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1036517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void setOverflowDirection(int overflowDirection) { 1037517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.removeView(mBackButtonContainer); 1038517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int index = (overflowDirection == FloatingToolbarPopup.OVERFLOW_DIRECTION_UP)? 1 : 0; 1039517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.addView(mBackButtonContainer, index); 10400c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 10410c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki 10420c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki /** 1043517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns the content view of the overflow. 1044517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1045517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public View getView() { 1046517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return mContentView; 1047517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1048517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1049517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeIn(boolean animate) { 1050517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mViewFader.fadeIn(animate); 1051517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1052517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1053517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeOut(boolean animate) { 1054517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mViewFader.fadeOut(animate); 1055517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1056517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1057517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1058517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns how big this panel's view should be. 1059517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * This method should only be called when the view has not been attached to a parent. 10600c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki * 1061517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @throws IllegalStateException 10620c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki */ 1063517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public Size measure() { 1064517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Preconditions.checkState(mContentView.getParent() == null); 1065517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mContentView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 1066517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return new Size(mContentView.getMeasuredWidth(), mContentView.getMeasuredHeight()); 1067517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1068517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1069517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private void setListViewHeight() { 1070517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int itemHeight = getEstimatedToolbarHeight(mContentView.getContext()); 1071517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int height = mListView.getAdapter().getCount() * itemHeight; 1072517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki int maxHeight = mContentView.getContext().getResources(). 1073517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height); 1074517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams params = mListView.getLayoutParams(); 1075517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki params.height = Math.min(height, maxHeight); 1076517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mListView.setLayoutParams(params); 10770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 1078517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1079f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private int setOverflowWidth() { 1080f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki for (int i = 0; i < mListView.getAdapter().getCount(); i++) { 1081f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki MenuItem menuItem = (MenuItem) mListView.getAdapter().getItem(i); 1082f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki Preconditions.checkNotNull(menuItem); 1083f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator.setText(menuItem.getTitle()); 1084f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator.measure( 1085f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 1086f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mOverflowWidth = Math.max( 1087f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki mListViewItemWidthCalculator.getMeasuredWidth(), mOverflowWidth); 1088f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki } 1089f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki return mOverflowWidth; 1090f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki } 1091f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki 1092f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki private ListView createOverflowListView() { 1093f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki final Context context = mContentView.getContext(); 1094517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final ListView overflowListView = new ListView(context); 1095517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListView.setLayoutParams(new ViewGroup.LayoutParams( 1096517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 1097517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListView.setDivider(null); 1098517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListView.setDividerHeight(0); 1099517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki final ArrayAdapter overflowListViewAdapter = 1100517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki new ArrayAdapter<MenuItem>(context, 0) { 1101517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki @Override 1102517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public View getView(int position, View convertView, ViewGroup parent) { 1103517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki TextView menuButton; 1104517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (convertView != null) { 1105517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuButton = (TextView) convertView; 1106517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } else { 1107517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuButton = createOverflowMenuItemButton(context); 1108517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1109517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki MenuItem menuItem = getItem(position); 1110517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuButton.setText(menuItem.getTitle()); 1111517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuButton.setContentDescription(menuItem.getTitle()); 1112f8e14fd89b63c91ff441765827dda672c67fa1dbAbodunrinwa Toki menuButton.setMinimumWidth(mOverflowWidth); 1113517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return menuButton; 1114517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1115517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki }; 1116517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki overflowListView.setAdapter(overflowListViewAdapter); 1117517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return overflowListView; 1118517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1119517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1120517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1121517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1122517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1123517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * A helper for fading in or out a view. 1124517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1125517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final class ViewFader { 1126517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1127517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final int FADE_OUT_DURATION = 250; 1128517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static final int FADE_IN_DURATION = 150; 1129517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1130517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final View mView; 1131517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ObjectAnimator mFadeOutAnimation; 1132517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private final ObjectAnimator mFadeInAnimation; 1133517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1134517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private ViewFader(View view) { 1135517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mView = Preconditions.checkNotNull(view); 1136517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mFadeOutAnimation = ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0) 1137517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .setDuration(FADE_OUT_DURATION); 1138517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mFadeInAnimation = ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1) 1139517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .setDuration(FADE_IN_DURATION); 1140517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1141517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1142517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeIn(boolean animate) { 1143b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki cancelFadeAnimations(); 1144517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (animate) { 1145517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mFadeInAnimation.start(); 1146517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } else { 1147517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mView.setAlpha(1); 1148517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1149517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1150517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1151517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki public void fadeOut(boolean animate) { 1152b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki cancelFadeAnimations(); 1153517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (animate) { 1154517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mFadeOutAnimation.start(); 1155517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } else { 1156517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki mView.setAlpha(0); 1157517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1158517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1159b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki 1160b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki private void cancelFadeAnimations() { 1161b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mFadeInAnimation.cancel(); 1162b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki mFadeOutAnimation.cancel(); 1163b90443724a5aa563cb81d6e7512329a66e80fa2cAbodunrinwa Toki } 1164517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1165517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1166517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1167517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1168517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Creates and returns a menu button for the specified menu item. 1169517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1170517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static Button createMenuItemButton(Context context, MenuItem menuItem) { 1171517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki Button menuItemButton = (Button) LayoutInflater.from(context) 1172517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_menu_button, null); 1173517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.setText(menuItem.getTitle()); 1174517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki menuItemButton.setContentDescription(menuItem.getTitle()); 1175517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return menuItemButton; 1176517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1177517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1178517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1179517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Creates and returns a styled floating toolbar overflow list view item. 1180517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1181517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static TextView createOverflowMenuItemButton(Context context) { 1182517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return (TextView) LayoutInflater.from(context) 1183517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_overflow_list_item, null); 1184517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1185517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1186517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static ViewGroup createContentContainer(Context context) { 1187517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return (ViewGroup) LayoutInflater.from(context) 1188517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .inflate(R.layout.floating_popup_container, null); 1189517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1190517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1191517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static PopupWindow createPopupWindow(View content) { 1192517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup popupContentHolder = new LinearLayout(content.getContext()); 1193517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki PopupWindow popupWindow = new PopupWindow(popupContentHolder); 1194103d48ec09cbaeedf28b66425cde9198f767e0d5Abodunrinwa Toki popupWindow.setWindowLayoutType( 1195103d48ec09cbaeedf28b66425cde9198f767e0d5Abodunrinwa Toki WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL); 1196517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki popupWindow.setAnimationStyle(0); 1197517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 1198517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki content.setLayoutParams(new ViewGroup.LayoutParams( 1199517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 1200517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki popupContentHolder.addView(content); 1201517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return popupWindow; 1202517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1203517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1204517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1205517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Creates a "grow and fade in from the bottom" animation for the specified view. 1206517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 1207517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param view The view to animate 1208517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1209517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static AnimatorSet createGrowFadeInFromBottom(View view) { 1210517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki AnimatorSet growFadeInFromBottomAnimation = new AnimatorSet(); 1211517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki growFadeInFromBottomAnimation.playTogether( 1212517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ObjectAnimator.ofFloat(view, View.SCALE_X, 0.5f, 1).setDuration(125), 1213517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.5f, 1).setDuration(125), 1214517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(75)); 1215517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki growFadeInFromBottomAnimation.setStartDelay(50); 1216517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return growFadeInFromBottomAnimation; 1217517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1218517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1219517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1220517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Creates a "shrink and fade out from bottom" animation for the specified view. 1221517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 1222517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param view The view to animate 1223517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param listener The animation listener 1224517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1225517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static AnimatorSet createShrinkFadeOutFromBottomAnimation( 1226517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki View view, Animator.AnimatorListener listener) { 1227517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki AnimatorSet shrinkFadeOutFromBottomAnimation = new AnimatorSet(); 1228517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki shrinkFadeOutFromBottomAnimation.playTogether( 1229517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ObjectAnimator.ofFloat(view, View.SCALE_Y, 1, 0.5f).setDuration(125), 1230517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(75)); 1231517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki shrinkFadeOutFromBottomAnimation.setStartDelay(150); 1232517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki shrinkFadeOutFromBottomAnimation.addListener(listener); 1233517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return shrinkFadeOutFromBottomAnimation; 1234517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1235517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1236517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getEstimatedToolbarHeight(Context context) { 1237517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return context.getResources().getDimensionPixelSize(R.dimen.floating_toolbar_height); 1238517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1239517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1240517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getEstimatedOpenOverflowButtonWidth(Context context) { 1241517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return context.getResources() 1242517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_menu_button_minimum_width); 1243517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1244517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1245517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getAdjustedToolbarWidth(Context context, int width) { 1246517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki if (width <= 0 || width > getScreenWidth(context)) { 1247517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki width = context.getResources() 1248517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki .getDimensionPixelSize(R.dimen.floating_toolbar_default_width); 1249517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1250517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return width; 1251517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1252517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1253517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1254517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns the device's screen width. 1255517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1256517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getScreenWidth(Context context) { 1257517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return context.getResources().getDisplayMetrics().widthPixels; 1258517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1259517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1260517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1261517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns the device's screen height. 1262517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1263517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int getScreenHeight(Context context) { 1264517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return context.getResources().getDisplayMetrics().heightPixels; 1265517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki } 1266517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki 1267517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki /** 1268517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * Returns value, restricted to the range min->max (inclusive). 1269517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * If maximum is less than minimum, the result is undefined. 1270517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * 1271517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param value The value to clamp. 1272517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param minimum The minimum value in the range. 1273517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki * @param maximum The maximum value in the range. Must not be less than minimum. 1274517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki */ 1275517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki private static int clamp(int value, int minimum, int maximum) { 1276517adad1c44b40fddba84c067c987d6db3fc5840Abodunrinwa Toki return Math.max(minimum, Math.min(value, maximum)); 12770c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki } 12780c7ed2886e6d17cacc9c0eeb2b7036923ef9a6e0Abodunrinwa Toki} 1279