Nested popup menus with smooth height animations

Related tags

Menu android popup menu
Overview

cascade

demo

cascade builds nested popup menus with smooth height animations. It is designed to be a drop-in replacement for PopupMenu so using it in your project is beautifully only a word away. Try out the sample app to see it in action.

implementation "me.saket.cascade:cascade:1.3.0"
- val popup = PopupMenu(context, anchor)
+ val popup = CascadePopupMenu(context, anchor)
  popup.inflate(R.menu.nicolas_cage_movies)
  popup.show()

Use as Toolbar's overflow menu

toolbar.overrideAllPopupMenus { context, anchor ->
  CascadePopupMenu(context, anchor)
}

// The lambda can be collapsed into a reference
// if you're only using the two-param constructor.
toolbar.overrideAllPopupMenus(with = ::CascadePopupMenu)

Customization

cascade is great for apps that prefer applying dynamic themes at runtime, which PopupMenu makes it extremely hard to do so. By providing a CascadePopupMenu.Styler object, you can adjust colors, spacings and text styles from Kotlin (example).

CascadePopupMenu(context, anchor, styler = CascadePopupMenu.Styler(...))

By default, cascade will pick up values from your theme in the same way as PopupMenu would.

<style name="AppTheme">
  <item name="popupMenuStyle">@style/PopupMenuStyle</item>
  <item name="colorControlNormal">@color/menu_icon_color</item>
  <item name="android:textColorPrimary">@color/menu_item_text_color</item>
  <item name="android:textColorSecondary">@color/menu_title_text_color</item>
</style>

<style name="PopupMenuStyle" parent="@style/Widget.AppCompat.PopupMenu">
  <item name="android:popupBackground">...</item>
  <item name="android:popupElevation">...</item>
</style>

Navigation

For sub-menus, cascade will automatically navigate to the parent menu when the title is clicked. For manual navigation, CascadePopupMenu#navigateBack() or CascadeBackNavigator can be used.

popup.menu.addSubMenu("Remove").also {
  it.setHeaderTitle("Are you sure?")
  it.add("Burn them all")
  it.add("Take me back").setOnMenuItemClickListener {
    popup.navigateBack()
  }
}

Custom layouts

cascade was originally inspired by Google Drive's menu that uses a variety of complex controls. For apps that want to create something similar, a batteries-included CascadePopupWindow is provided for use with custom layouts.

val popup = CascadePopupWindow(context)
popup.contentView.addView(CustomMenuView(context))  // Also see contentView.goBack().
popup.show(anchor)

License

Copyright 2020 Saket Narayan.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Adding support for grouped menus

    Adding support for grouped menus

    Implementing #1

    Demo:

    TODO:

    1. setGroupVisible currently hides the group but does not adjust the menu height.
    2. Adding support for setGroupCheckable.
    3. setGroupEnabled is functional but the group state stays the same. (Perhaps we could add color states for disabled items)

    Also, it'd be nice to add icons for the sample grouped menu items. I can add them if there's an icon set you've already used for the other items that I can have access to.

    opened by waseefakhtar 9
  • Use cascade as toolbar's overflow menu

    Use cascade as toolbar's overflow menu

    Having dynamic content in toolbar ifRoom might be tedious to deal with but would be a great addition. I don't how toolbar and menu operates in stock Android to achieve this.

    opened by opatry 5
  • Arrows briefly left hanging on transition to a smaller menu

    Arrows briefly left hanging on transition to a smaller menu

    Hi! Just a small UI issue my teammate @burntcookie90 and I were discussing is that during menu transitions sometimes the arrow icon is briefly left hanging. I didn't notice it at all for a while, but then one of our team members pointed it out and now its hard to unsee!

    We noticed it in a POC we were doing, but it can actually be seen slightly in the demo gif:

    demo

    Relevant frames (sorry for uneven height):

    Screen Shot 2021-01-27 at 12 45 25 PMScreen Shot 2021-01-27 at 12 45 33 PMScreen Shot 2021-01-27 at 12 45 43 PMScreen Shot 2021-01-27 at 12 45 51 PMScreen Shot 2021-01-27 at 12 45 59 PMScreen Shot 2021-01-27 at 12 46 07 PMScreen Shot 2021-01-27 at 12 46 15 PMScreen Shot 2021-01-27 at 12 46 23 PMScreen Shot 2021-01-27 at 12 46 30 PM

    Seems to happen when navigating to a shorter menu and the arrows are below the incoming menu items.

    Thanks for the great library!

    opened by cmt218 4
  • App Crashing when click to open the popup

    App Crashing when click to open the popup

    App Crashing when click to open the popup Android 5.1

    Here are logs: `

    10-27 14:15:18.168 19215-19215/com.myprohelper.staging E/AndroidRuntime: FATAL EXCEPTION: main Process: com.myprohelper.staging, PID: 19215 java.lang.ClassCastException: android.view.ViewRootImpl cannot be cast to android.view.View at me.saket.cascade.CascadePopupWindow.runWithMargins(CascadePopupWindow.kt:103) at me.saket.cascade.CascadePopupWindow.showAsDropDown(CascadePopupWindow.kt:89) at me.saket.cascade.CascadePopupMenu.show(CascadePopupMenu.kt:73) at com.myprohelper.ui.base.tableview.TableViewListener.onRowHeaderClicked(TableViewListener.kt:49) at com.evrencoskun.tableview.listener.itemclick.RowHeaderRecyclerViewItemClickListener.clickAction(RowHeaderRecyclerViewItemClickListener.java:59) at com.evrencoskun.tableview.listener.itemclick.AbstractItemClickListener$1.onSingleTapConfirmed(AbstractItemClickListener.java:65) at android.view.GestureDetector$GestureHandler.handleMessage(GestureDetector.java:295) at android.os.Handler.dispatchMessage(Handler.java:111) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:6102) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)`

    opened by Mohamadkotb 3
  • Support menu appearing from bottom of screen

    Support menu appearing from bottom of screen

    Great looking library, can see it being desirable to have these menus popup from the bottom of the screen, nearer the users normal reach.

    Currently with the sample app if you move the toolbar to the bottom the menu appears but only showing the first item.

    image

    opened by ac87 2
  • Feature/menu groups support

    Feature/menu groups support

    This PR addresses the issue #1 .

    addToGroup() example:

    Screenshot_1602413595

    removeFromGroup() example:

    Screenshot_1602413616

    Note: The setGroupVisible() method is not implemented as it sets the visibility of MenuItems without removing the space. One possible workaround would be to call removeFromGroup() method when the user calls setGroupVisible(false) and addToGroup() method when the user calls setGroupVisible(false). To be able to implement this, though, we should memorize the MenuItems added locally before removing them in order to recreate them when setGroupVisible(false) is called. Consequently, this would be a duplicate implementation of the existing addToGroup() and removeFromGroup() methods.
    opened by ilkeraslan 2
  • Enhancement Request: Option to hide menu rather than navigating back

    Enhancement Request: Option to hide menu rather than navigating back

    I noticed that it currently navigates back from a submenu when clicked on an item. What about adding an option to hide the menu altogether rather than navigating back?

    Demo:

    opened by waseefakhtar 1
  • Crashing on clicking menu

    Crashing on clicking menu

    Device: Xiaomi Redmi Note 4 Android Version: API 24

    I installed sample application on my device. Clicked on menu icon and it crashed.

    Here are logs

    java.lang.NoSuchMethodError: No virtual method getFont(I)Landroid/graphics/Typeface; in class Landroid/content/res/Resources; or its super classes (declaration of 'android.content.res.Resources' appears in /system/framework/framework.jar)
    	at me.saket.cascade.sample.MainActivity$cascadeMenuStyler$3.invoke(MainActivity.kt:103)
    	at me.saket.cascade.sample.MainActivity$cascadeMenuStyler$3.invoke(MainActivity.kt:27)
    	at me.saket.cascade.CascadeMenuAdapter.onBindViewHolder(CascadeMenuAdapter.kt:70)
    	at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
    	at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
    	at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
    	at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
    	at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
    	at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
    	at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
    	at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
    	at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
    	at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
    	at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
    	at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3540)
    	at android.view.View.measure(View.java:19762)
    	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6122)
    	at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    	at android.view.View.measure(View.java:19762)
    	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6122)
    	at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    	at android.view.View.measure(View.java:19762)
    	at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2315)
    	at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1402)
    	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1651)
    	at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1290)
    	at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6399)
    	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:873)
    	at android.view.Choreographer.doCallbacks(Choreographer.java:685)
    	at android.view.Choreographer.doFrame(Choreographer.java:621)
    	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:859)
    	at android.os.Handler.handleCallback(Handler.java:754)
    	at android.os.Handler.dispatchMessage(Handler.java:95)
    	at android.os.Looper.loop(Looper.java:165)
    	at android.app.ActivityThread.main(ActivityThread.java:6375)
    	at java.lang.reflect.Method.invoke(Native Method)
    	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802)
    

    I hope this information would be helpful for you.

    opened by PatilShreyas 1
  • Animate ViewFlipper changes using ViewPropertyAnimator

    Animate ViewFlipper changes using ViewPropertyAnimator

    Fixes #4 Download APK: WeTransfer / Google Drive

    I still don't understand why are the animations choppy on some devices with android.view.animation.Animation, but it's probably safe to assume that the old animation APIs were always bad. I'm thankful they're not used anymore.

    opened by saket 0
  • Need to provide `consumerProguardFile` or declare reflection keeps in README

    Need to provide `consumerProguardFile` or declare reflection keeps in README

    For: https://github.com/saket/cascade/blob/80fcf2dab77b0413b3bb420600b5fb947080417b/cascade/src/main/java/me/saket/cascade/toolbar.kt#L122

    &

    https://github.com/saket/cascade/blob/80fcf2dab77b0413b3bb420600b5fb947080417b/cascade/src/main/java/me/saket/cascade/toolbar.kt#L134

    opened by drakeet 1
  • Add option to show at anchor location.

    Add option to show at anchor location.

    Hello @saket, first of all great library.

    This is my take on "fixing" #21 and #26 This PR is for you to have a look at a potential solution. Showing at location is trying always fit the popup in the current window.

    https://user-images.githubusercontent.com/2619500/178484524-8d657634-2378-42cc-9284-b4cb117f0e1c.mp4

    opened by geftimov 4
  • Make fixedWidth a function.

    Make fixedWidth a function.

    The width of the popup is currently fixed and while this is fine in a single-language project, translations often lead to truncated texts in the popup.

    The change in the PR simply makes the fixedWidth property a function and provides the menu as a parameter so users get the chance to calculate the width before the popup is shown.

    Currently, for my use case, I loop through the menu items and find the item with the largest width.

    Note that in cases where I inflate the menu on cascade myself before calling show() then I can already do this calculation before creating cascade even though that would mean inflating a dummy menu outside since fixedWidth is a constructor parameter so I can't use the menu inside cascade. However, since I also use cascade to override the toolbar's popup menu, grabbing the inflated menu before it is shown becomes a problem because all the work is done in the toolbar.kt

    Granted, this would be considered a breaking change but it is one that is quite easy to fix, and users who do not set a custom value for this parameter do not even need to do anything.

    opened by kizitonwose 0
  • Android 5 issues

    Android 5 issues

    Hi @saket I hope you're doing well. Thanks for that great library.

    I notice some issues in android 5

    • Can't do any action while the popup menu is opened
    • The popup looks very strange when clicking on the bottom of the screen
    • When open the keyboard the popup menu is jumped to the top of the screen Please, check the attached images

    received_441420143687499 received_411103146927199 received_978552435973192 received_197330485325167

    opened by MohamedHarmoush 1
  • Gravity doesn't appear to work?

    Gravity doesn't appear to work?

    I am using Cascade as a means to show a menu in a scrolling list that takes up the entire vertical space of the device. For items at the very end, I'd prefer if the menu anchors at the bottom and and then draws upward rather than achor at the top of the view, draw downward, and then get cutoff by the screen.

    I've tried setting Cascade to use various Gravities, but changing the value seems to have no effect.

    image

    opened by Kev1000000 5
Releases(2.0.0-beta1)
  • 2.0.0-beta1(May 4, 2022)

    cascade is getting ready for Compose UI. As usual, it is offering a a drop-in replacement for Material Design's DropdownMenu() composable with support for nested menus.

    - DropdownMenu(
    + CascadeDropdownMenu(
       expanded = expanded,
       onDismissRequest = { expanded = false }
     )
    
    implementation "me.saket.cascade:cascade-compose:2.0.0-beta1"
    implementation "androidx.compose.material3:material3:..." // https://developer.android.com/jetpack/androidx/releases/compose-material3
    

    Sample code

    var expanded by rememberSaveable { mutableStateOf(false) }
    
    CascadeDropdownMenu(
      expanded = expanded,
      onDismissRequest = { expanded = false }
    ) {
      DropdownMenuItem(
        text = { Text("Horizon") },
        children = {
          DropdownMenuItem(
            text = { Text("Zero Dawn") },
            onClick = { … }
          )
          DropdownMenuItem(
            text = { Text("Forbidden West") },
            onClick = { … }
          )
        }
      )
    }
    
    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Feb 1, 2021)

    New features

    • Support for group dividers (thanks @waseefakhtar!).
    • Internal paddings in the popup's background are trimmed automatically if they were picked up from the app's (XML) theme. cascade assumes that they were supplied by appcompat or MaterialComponents. If paddings are really desired, a custom CascadePopupMenu.Styler.background will have to be provided with paddings.

    cascade_popup_paddings

    • Injectable back navigator:
    // A "back" navigator can be used for setting up a menu's navigation before an instance of
    // CascadePopupMenu can be created. This is especially useful for overriding Toolbar's popup 
    // menus where a CascadePopupMenu can only be created AFTER a menu item is clicked 
    // (to maintain backwards compatibility with PopupMenu).
    val navigator = CascadeBackNavigator()
    toolbar.menu.addSubMenu("Are you sure?").apply {
      add("Cancel").setOnMenuItemClickListener {
        backNavigator.navigateBack()
      }
    }
    
    toolbar.overrideOverflowMenu { context, anchor ->
      CascadePopupMenu(context, anchor, backNavigator = navigator)
    }
    
    • Experimental API to ~steal~ override all popup menus of a Toolbar with cascade. This will override both overflow menu and sub menus for action items.
    toolbar.overrideAllPopupMenus(with = ::CascadePopupMenu)
    

    Fixes

    • Prevent keyboard from getting recreated when cascade is shown.
    • Disable drag-to-show gesture when overflow menu is overridden.
    • Fix incorrect left spacing of menu items with MaterialComponents theme.
    • #23: Handle touch and key events on API 22 (thanks @kizitonwose!).
    Source code(tar.gz)
    Source code(zip)
    cascade_v1.3.0_sample.apk(4.13 MB)
  • 1.2.0(Nov 25, 2020)

    • Fixes a critical bug that was causing cascade to crash on API 21 devices.
    • Works around a bug with PopupWindow, where the internal paddings set by the default popup background aren’t reset even if the background is changed (https://github.com/saket/cascade/commit/79ace480f33bc7cd2726db5022c099deeb54d9c4).
    Source code(tar.gz)
    Source code(zip)
    cascade_v1.2.0_sample.apk(2.46 MB)
  • 1.1.0(Oct 16, 2020)

Owner
Saket Narayan
Maker of shiny things at @square @cashapp and an Android GDE
Saket Narayan
You can create awesome menus with bottom sheet experience in a few lines

You can create awesome menus with bottom sheet experience in a few lines

Mazen Rashed 19 Nov 1, 2022
:fire: The powerful and easiest way to implement modern material popup menu.

PowerMenu ?? The powerful and easiest way to implement modern material popup menu. PowerMenu can be fully customized and used for popup dialogs. Downl

Jaewoong Eum 1k Dec 29, 2022
Android-NewPopupMenu 3.9 0.0 Java is an android library to create popup menu with GoogleMusic app-like style.

Android-NewPopupMenu Android-NewPopupMenu is an android library to create popup menu with GoogleMusic app-like style. Requirements Tested with APIv4 H

u1aryz 159 Nov 21, 2022
imitate Tumblr's menu, dragging animations look like a snake

android-snake-menu imitate Tumblr's menu, dragging animations look like a snake unexpected episode I found another repository some time ago which impl

stone 586 Nov 10, 2022
Animations for Android L drawer, back, dismiss and check icons

Material Menu Morphing Android menu, back, dismiss and check buttons Have full control of the animation: Including in your project compile 'com.balysv

Balys Valentukevicius 2.5k Dec 30, 2022
A customizable and easy to use BottomBar navigation view with sleek animations, with support for ViewPager, ViewPager2, NavController, and badges.

AnimatedBottomBar A customizable and easy to use bottom bar view with sleek animations. Examples Playground app Download the playground app from Googl

Joery 1.2k Dec 30, 2022
πŸ’§ A customizable jetpack compose dropdown menu with cascade and animations

Dropdown ?? A customizable jetpack compose dropdown menu with cascade and animations. Who's using Dropdown? ?? Check out who's using Dropdown Include

Ranbir Singh 192 Jan 4, 2023
Android RecyclerView Adapter with nested items & expand/contract functionality

AccordionRecycler Android RecyclerView Adapter with nested items & expand/contract functionality With AccordionRecycler you can easily create awesome

Fanis Veizis 17 Aug 18, 2022
Expandable Recyclerview makes it easy to integrate nested recycler view...πŸ”¨ πŸ“

SSExpandableRecyclerView Expandable Recyclerview make it easy to integrate nested recyclerview Features Simple and easy to use ( no complex adapter re

Simform Solutions 52 Nov 1, 2022
Mobile App that shows Random Products in a Nested Recyclerview for Android [Kotlin] Developer Role at Edvora

EdvoraAndroidTest An simple Android App for Edvora Android Assessment. It consum

Joel Kanyi 6 Jul 12, 2022
:balloon: A lightweight popup like tooltips, fully customizable with an arrow and animations.

Balloon ?? A lightweight popup like tooltips, fully customizable with arrow and animations. Including in your project Gradle Add below codes to your r

Jaewoong Eum 2.8k Jan 5, 2023
:balloon: A lightweight popup like tooltips, fully customizable with an arrow and animations.

Balloon ?? A lightweight popup like tooltips, fully customizable with arrow and animations. Including in your project Gradle Add below codes to your r

Jaewoong Eum 2.9k Jan 9, 2023
:balloon: A lightweight popup like tooltips, fully customizable with an arrow and animations.

Balloon ?? A lightweight popup like tooltips, fully customizable with arrow and animations. Including in your project Gradle Add below codes to your r

Jaewoong Eum 1.8k Apr 27, 2021
Balloon 🎈 A lightweight popup like tooltips, fully customizable with arrow and animations.

Balloon ?? A lightweight popup like tooltips, fully customizable with arrow and animations.

Jaewoong Eum 2.8k Jan 2, 2023
PowerSpinner - πŸŒ€ A lightweight dropdown popup spinner, fully customizable with an arrow and animations for Android.

PowerSpinner - ?? A lightweight dropdown popup spinner, fully customizable with an arrow and animations for Android.

Jaewoong Eum 881 Dec 30, 2022
An Android library that allows you to easily create applications with slide-in menus. You may use it in your Android apps provided that you cite this project and include the license in your app. Thanks!

SlidingMenu (Play Store Demo) SlidingMenu is an Open Source Android library that allows developers to easily create applications with sliding menus li

Jeremy Feinstein 11.1k Dec 27, 2022
An Android library that allows you to easily create applications with slide-in menus. You may use it in your Android apps provided that you cite this project and include the license in your app. Thanks!

SlidingMenu (Play Store Demo) SlidingMenu is an Open Source Android library that allows developers to easily create applications with sliding menus li

Jeremy Feinstein 11.1k Dec 21, 2022
You can create awesome menus with bottom sheet experience in a few lines

You can create awesome menus with bottom sheet experience in a few lines

Mazen Rashed 19 Nov 1, 2022