GithubHelp home page GithubHelp logo

saket / cascade Goto Github PK

View Code? Open in Web Editor NEW
2.0K 33.0 63.0 3.85 MB

Nested popup menus with smooth height animations for Android

Home Page: https://saket.github.io/cascade

License: Apache License 2.0

Kotlin 100.00%
popup menu android jetpack-compose

cascade's Introduction

cascade

demo

cascade builds nested popup menus with smooth height animations. It is designed to be a drop-in replacement for both PopupMenu and DropdownMenu, 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:2.3.0"
implementation "me.saket.cascade:cascade-compose:2.3.0"

See project website for full documentation.

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.

cascade's People

Contributors

goooler avatar kasem-sm avatar kizitonwose avatar msfjarvis avatar paolovalerdi avatar saket avatar waseefakhtar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cascade's Issues

App Crash when clicking on menu item

App crash when I clicked on a menu item with children.
Device Android 11

Crash Log:
java.lang.IllegalArgumentException: Cannot perform operation for Unspecified type.
at androidx.compose.ui.unit.TextUnitKt.checkArithmetic--R2X_6o(TextUnit.kt:344)
at me.saket.cascade.CascadeColumnScope$DefaultImpls.DropdownMenuHeader(Cascade.kt:458)
at me.saket.cascade.CascadeKt$CascadeColumnScope$1.DropdownMenuHeader(Cascade.kt:393)
at me.saket.cascade.CascadeColumnScope$DropdownMenuItem$1.invoke(Cascade.kt:305)
at me.saket.cascade.CascadeColumnScope$DropdownMenuItem$1.invoke(Cascade.kt:305)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at me.saket.cascade.CascadeKt$CascadeDropdownMenuContent$2$2.invoke(Cascade.kt:259)
at me.saket.cascade.CascadeKt$CascadeDropdownMenuContent$2$2.invoke(Cascade.kt:250)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:135)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$5$1$4.invoke(AnimatedContent.kt:658)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$5$1$4.invoke(AnimatedContent.kt:648)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.animation.AnimatedVisibilityKt.AnimatedEnterExitImpl(AnimatedVisibility.kt:939)
at androidx.compose.animation.AnimatedVisibilityKt.AnimatedVisibility(AnimatedVisibility.kt:607)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$5$1.invoke(AnimatedContent.kt:638)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$5$1.invoke(AnimatedContent.kt:625)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.animation.AnimatedContentKt.AnimatedContent(AnimatedContent.kt:671)
at androidx.compose.animation.AnimatedContentKt.AnimatedContent(AnimatedContent.kt:131)
at me.saket.cascade.CascadeKt$CascadeDropdownMenuContent$2.invoke(Cascade.kt:246)
at me.saket.cascade.CascadeKt$CascadeDropdownMenuContent$2.invoke(Cascade.kt:233)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:162)
at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2465)
at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2733)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3364)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3342)
at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3342)
at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3307)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:772)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1047)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:124)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:541)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:510)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
2023-02-17 13:49:48.070 18917-18917 AndroidRuntime com.phunware.modules.mapping.sample E at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1054)
at android.view.Choreographer.doCallbacks(Choreographer.java:878)
at android.view.Choreographer.doFrame(Choreographer.java:807)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1041)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:368)
at android.app.ActivityThread.main(ActivityThread.java:7710)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:954)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@61d3318, androidx.compose.ui.platform.MotionDurationScaleImpl@c904171, StandaloneCoroutine{Cancelling}@bc27b56, AndroidUiDispatcher@de6e7d7]

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.

Allow setting of max width

I'd love if I could set the max width of the PopupMenu to something dynamic so I can accommodate slightly larger strings of text while using icons.

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

The default color of the CascadeDropdownMenu is not the same as DropdownMenu

Before:
image

after:
image

Showing a default DropdownMenu vs CascadeDropdownMenu

studio64_ydSz9zlk9O.mp4

I am also not sure how not to change the default color with CascadeDropdownMenu

code in question
    CascadeDropdownMenu(
        expanded = expanded,
        onDismissRequest = onDismissRequest,
        modifier = Modifier.semantics { testTagsAsResourceId = true },
    ) {

        DropdownMenuItem(
            text = { Text(text = stringResource(R.string.home_refresh)) },
            leadingIcon = { Icon(Icons.Outlined.Refresh, contentDescription = null) },
            onClick = {
                onDismissRequest()
                onClickRefresh()
            },
            modifier = Modifier.testTag("jerboa:refresh"),
        )
        DropdownMenuItem(
            text = { Text(text = stringResource(R.string.home_post_view_mode)) },
            leadingIcon = { Icon(Icons.Outlined.ViewAgenda, contentDescription = null) },
            children = {
                PostViewMode.entries.map {
                    DropdownMenuItem(
                        text = { Text(text = stringResource(it.mode)) },
                        onClick = {
                            onClickPostViewMode(it)
                            onDismissRequest()
                                  },

                        modifier =
                        if (selectedPostViewMode == it) {
                            Modifier.background(MaterialTheme.colorScheme.onBackground.copy(alpha = .1f))
                        } else {
                            Modifier
                        }.testTag("jerboa:postviewmode_${it.name}"),
                    )
                }
            },
            modifier = Modifier.testTag("jerboa:postviewmode"),
        )
        DropdownMenuItem(
            text = { Text(stringResource(R.string.home_site_info)) },
            leadingIcon = { Icon(Icons.Outlined.Info, contentDescription = null) },
            onClick = {
                onClickSiteInfo()
                onDismissRequest()
            },
        )

Old version https://github.com/MV-GH/jerboa/blob/a5d1b01a6b219ad524d5d97e897e6514058646d5/app/src/main/java/com/jerboa/ui/components/home/Home.kt#L230

Allow background dimming

PopupWindow allows dimming background, but it's a bit difficult do so and doesn't animate in sync with entry/exist transitions. Providing a first-class API for doing it would be sweet.

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

Expand to up ?

How do I make it open upwards when I click on a view at the bottom of the screen?

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

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.

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)`

is this code works in java?

Hi, i just want to use this menu on my java code

private void showMenu(View v, @MenuRes int menuRes) {
Context context = v.getContext();
popup = new PopupMenu(context, v);
popup.getMenuInflater().inflate(menuRes, popup.getMenu());

    int i = 0;
    for (String menuItemData : menuItemDataList) {
        popup.getMenu().add(Menu.NONE, i, Menu.NONE, menuItemData);
        i++;
    }
    popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem menuItem) {
            button.setText(menuItem.getTitle().toString());
            return true;
        }
    });
    popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
        @Override
        public void onDismiss(PopupMenu menu) {
            // Respond to popup being dismissed.
        }
    });
    // Show the popup menu.
    popup.show();
}

When there is insufficient space on the screen, the Popup is displayed incompletely or even becomes invisible.

When there is a button at the bottom of the screen and clicking on it triggers a Popup, the Popup is not fully displayed. In some extreme cases, the Popup is even invisible. I have confirmed that this issue is caused by setting the Popup height to WRAP_CONTENT.

Screenshot_20240103_201714

when I specified the exact height for the Popup, the issue was resolved. (I manually measured the height of each item in the RecyclerView).

   popup.width = fixedWidth
   popup.height = **measureHeightOfChildrenCompat(maxHeight)** + context.dip(4) // Doesn't work on API 21 without this.
    
   popup.showAsDropDown(anchor, 0, 0, gravity)

Screenshot_20240103_202253

Crash after updating androidx.compose.material3:material3

Hello,

I'm having a crash after updating from
androidx.compose.material3:material3:1.1.0-beta02 to
androidx.compose.material3:material3:1.2.0-alpha01.

Here the stacktrace:

FATAL EXCEPTION: main
Process: com., PID: 7951
java.lang.NoSuchMethodError: No static method AnimatedContent(Ljava/lang/Object;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Alignment;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V in class Landroidx/compose/animation/AnimatedContentKt; or its super classes (declaration of 'androidx.compose.animation.AnimatedContentKt' appears in /data/app/~~tm7XVqFdpYIrcR6EzvOK5Q==/com.-DgU4eTqRQixR6uvl0DF5YA==/base.apk)
	at me.saket.cascade.CascadeKt$CascadeDropdownMenuContent$2.invoke(Cascade.kt:246)
	at me.saket.cascade.CascadeKt$CascadeDropdownMenuContent$2.invoke(Cascade.kt:233)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.material3.SurfaceKt$Surface$1.invoke(Surface.kt:132)
	at androidx.compose.material3.SurfaceKt$Surface$1.invoke(Surface.kt:114)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.material3.SurfaceKt.Surface-T9BRK9s(Surface.kt:111)
	at me.saket.cascade.CascadeKt.CascadeDropdownMenuContent-942rkJo(Cascade.kt:229)
	at me.saket.cascade.CascadeKt.access$CascadeDropdownMenuContent-942rkJo(Cascade.kt:1)
	at me.saket.cascade.CascadeKt$PopupContent$1.invoke(Cascade.kt:205)
	at me.saket.cascade.CascadeKt$PopupContent$1.invoke(Cascade.kt:204)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at me.saket.cascade.internal.AnimateEntryExitKt.AnimateEntryExit-hGBTI10(AnimateEntryExit.kt:147)
	at me.saket.cascade.CascadeKt.PopupContent-aC-nel8(Cascade.kt:198)
	at me.saket.cascade.CascadeKt$CascadeDropdownMenu$2$2.invoke(Cascade.kt:169)
	at me.saket.cascade.CascadeKt$CascadeDropdownMenu$2$2.invoke(Cascade.kt:168)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at me.saket.cascade.internal.PositionPopupContentKt.PositionPopupContent(PositionPopupContent.kt:70)
	at me.saket.cascade.CascadeKt$CascadeDropdownMenu$2.invoke(Cascade.kt:160)
	at me.saket.cascade.CascadeKt$CascadeDropdownMenu$2.invoke(Cascade.kt:159)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.ui.window.AndroidPopup_androidKt$Popup$popupLayout$1$1$1$3.invoke(AndroidPopup.android.kt:257)
	at androidx.compose.ui.window.AndroidPopup_androidKt$Popup$popupLayout$1$1$1$3.invoke(AndroidPopup.android.kt:256)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.ui.window.AndroidPopup_androidKt$Popup$popupLayout$1$1$1.invoke(AndroidPopup.android.kt:844)
	at androidx.compose.ui.window.AndroidPopup_androidKt$Popup$popupLayout$1$1$1.invoke(AndroidPopup.android.kt:245)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.ui.window.PopupLayout.Content(AndroidPopup.android.kt:465)
	at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252)
	at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:190)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:119)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:118)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:158)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:157)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:157)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:142)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:78)
	at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3342)
	at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3274)
	at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:588)
	at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1004)
	at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4005)
	at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4005)
	at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4005)
	at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:520)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:142)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133)
	at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1121)
	at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:133)
	at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:183)
	at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.kt:314)
	at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.kt:192)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133)
	at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1196)
	at android.view.View.dispatchAttachedToWindow(View.java:20812)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3490)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2675)
	at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2179)
	at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8798)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1037)
	at android.view.Choreographer.doCallbacks(Choreographer.java:845)
	at android.view.Choreographer.doFrame(Choreographer.java:780)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7870)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

Any idea how to fix it?
I want to keep this upgraded version of material3 as it fixed other issues.

Thanks!

Interested in adding a centered animated popup menu?

I made centered popup menu variation of of the CascadeDropdownMenu. Are you interested in having this added to this library?

cot8LTIDkF.mp4
Source Code
@Composable
fun CascadeCenteredDropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    fixedWidth: Dp = LocalConfiguration.current.screenWidthDp.dp * POPUP_MENU_WIDTH_RATIO,
    shadowElevation: Dp = 3.dp,
    properties: PopupProperties = PopupProperties(focusable = true),
    state: CascadeState = rememberCascadeState(),
    content: @Composable CascadeColumnScope.() -> Unit,
) {
    val expandedStates = remember { MutableTransitionState(false) }
    expandedStates.targetState = expanded

    if (expandedStates.currentState || expandedStates.targetState) {
        val transformOriginState = remember { mutableStateOf(TransformOrigin.Center) }

        // A full sized popup is shown so that content can render fake shadows
        // that do not suffer from https://issuetracker.google.com/issues/236109671.

        Popup(
            alignment = Alignment.Center,
            onDismissRequest = onDismissRequest,
            properties = properties.copy(usePlatformDefaultWidth = false),
        ) {
            Box(
                Modifier
                    .fillMaxSize()
                    .then(properties.dismissOnClickOutside) {
                        clickableWithoutRipple(onClick = onDismissRequest)
                    },
                Alignment.Center,
            ) {
                PopupContent(
                    modifier = Modifier
                        // Prevent clicks from leaking behind. Otherwise, they'll get picked up as outside
                        // clicks to dismiss the popup. This must be set _before_ the downstream modifiers to
                        // avoid overriding any clickable modifiers registered by the developer.
                        .clickableWithoutRipple {}
                        .padding(vertical = LARGE_PADDING)
                        .then(modifier),
                    state = state,
                    fixedWidth = fixedWidth,
                    expandedStates = expandedStates,
                    transformOriginState = transformOriginState,
                    shadowElevation = shadowElevation,
                    tonalElevation = 3.dp,
                    content = content,
                )
            }
        }
    }
}

If not, could you allow making PopupContent not internal so I can depend on the upstream?

@saket

Shadow elevation should not be limited if a project's minSdk is 31 or above

cascade copies material3's behavior of limiting elevation to 8dp. This was done to workaround a bug on systems older than API level 31 where any content under drop shadows weren't visible to screen readers (source).

shadowElevation = shadowElevation.coerceAtMost(8.dp),

This is unfortunate because larger shadows look definitely a lot nicer. cascade should read the project's minSdk and allow elevations > 8.dp on API level 31 and above.

Popup isnt visible on second screen on dual screen phones

I received a report from a user that when we made the switch to this library that the popups on one screen don't appear anymore.

When the app is opening on one screen everything is fine, just the other screen the popups/dialogs don't appear at all.

I had the device + Android version but I can't find the report back again. I'll update this issue when I do.

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!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.