Balloon icon indicating copy to clipboard operation
Balloon copied to clipboard

[Crash] The width of the balloon must bigger than zero.

Open zenyagami opened this issue 7 months ago • 9 comments

Please complete the following information:

  • Library Version: latest 1.6.12
  • Affected Device(s) Several with android 12+

Describe the Bug: I can't reproduce the issue, however I can see a crash, it was not before,

Fatal Exception: java.lang.IllegalArgumentException: The width of the balloon must bigger than zero.
       at com.skydoves.balloon.Balloon$Builder.setMeasuredWidth(Balloon.kt:2439)
       at com.skydoves.balloon.Balloon.updateSizeOfBalloonCard(Balloon.kt:1698)
       at com.skydoves.balloon.compose.BalloonComposeView.updateSizeOfBalloonCard-ozmzZPI$balloon_compose_release(BalloonComposeView.kt:315)
       at com.skydoves.balloon.compose.BalloonKt$Balloon$6.invoke$lambda$3$lambda$2(Balloon.kt:165)
       at androidx.compose.ui.layout.OnGloballyPositionedNode.onGloballyPositioned(OnGloballyPositionedModifier.kt:75)
       at androidx.compose.ui.node.LayoutNode.dispatchOnPositionedCallbacks$ui_release(LayoutNode.kt:1176)
       at androidx.compose.ui.node.OnPositionedDispatcher.dispatchHierarchy(OnPositionedDispatcher.kt:76)
       at androidx.compose.ui.node.OnPositionedDispatcher.dispatchHierarchy(OnPositionedDispatcher.kt:79)
       at androidx.compose.ui.node.OnPositionedDispatcher.dispatchHierarchy(OnPositionedDispatcher.kt:79)
       at androidx.compose.ui.node.OnPositionedDispatcher.dispatch(OnPositionedDispatcher.kt:67)
       at androidx.compose.ui.node.MeasureAndLayoutDelegate.dispatchOnPositionedCallbacks(MeasureAndLayoutDelegate.kt:719)
       at androidx.compose.ui.platform.AndroidComposeView.updatePositionCacheAndDispatch(AndroidComposeView.android.kt:1721)
       at androidx.compose.ui.platform.AndroidComposeView.onLayout(AndroidComposeView.android.kt:1687)
       at android.view.View.layout(View.java:25484)
       at android.view.ViewGroup.layout(ViewGroup.java:6441)
       at androidx.compose.ui.platform.AbstractComposeView.internalOnLayout$ui_release(ComposeView.android.kt:320)
       at androidx.compose.ui.window.PopupLayout.internalOnLayout$ui_release(AndroidPopup.android.kt:608)
       at androidx.compose.ui.platform.AbstractComposeView.onLayout(ComposeView.android.kt:310)
       at android.view.View.layout(View.java:25484)
       at android.view.ViewGroup.layout(ViewGroup.java:6441)
       at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:5214)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4329)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3155)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10833)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1406)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1415)
       at android.view.Choreographer.doCallbacks(Choreographer.java:1015)
       at android.view.Choreographer.doFrame(Choreographer.java:945)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1389)
       at android.os.Handler.handleCallback(Handler.java:1001)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loopOnce(Looper.java:268)
       at android.os.Looper.loop(Looper.java:384)
       at android.app.ActivityThread.main(ActivityThread.java:8921)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:907)
        

In crashlytics/sentry the same, I'm not sure which one is causing the conflict, But I suspect that this is the one:

@Composable
fun appDrawerBalloonFactory(): Balloon.Builder {
    val context = LocalContext.current

    return rememberBalloonBuilder {
        setArrowSize(14)
        setArrowOrientationRules(ArrowOrientationRules.ALIGN_ANCHOR)
        setArrowOrientation(ArrowOrientation.BOTTOM)
        setArrowPosition(0.15f)
        setWidth(BalloonSizeSpec.WRAP)
        setPadding(12)
        setCornerRadius(4f)
        setTextSize(17f)
        setBackgroundColor(context.getPrimaryContainerColor())
        setBalloonAnimation(BalloonAnimation.CIRCULAR)
        setPreferenceName(BalloonFactory.PREFERENCE_NAME_BALLOON_APP_DRAWER)
        setShowCounts(1)
        setBalloonHighlightAnimation(BalloonHighlightAnimation.SHAKE)
    }
}

Calling

      items.forEach {
                when (it) {
                    BottomBarItems.AppDrawer -> {
                        Balloon(
                            modifier = Modifier,
                            builder = appDrawerBalloonFactory(),
                            balloonContent = {
                                Text(
                                    text = stringResource(id = R.string.tool_tip_app_drawer),
                                    modifier = Modifier,
                                    style = MaterialTheme.typography.titleMedium,
                                    color = MaterialTheme.colorScheme.onPrimaryContainer
                                )
                            }
                        ) {
                            NavIcon(
                                icon = ImageVector.vectorResource(id = R.drawable.ic_apps),
                                onItemClick = onAppDrawerClicked
                            )
                            it.showAlignTop()
                        }
                    }

Add a clear description about the problem.

Expected Behavior: to not crash.

A clear description of what you expected to happen. I can't reproduce, since it seems that happens randomly but I can see several users with this issue tho,

zenyagami avatar Jul 05 '25 13:07 zenyagami

I checked new crashes and in Sentry, it happened in user orientation change

zenyagami avatar Jul 10 '25 09:07 zenyagami

Hi @zenyagami, I'm sorry for the late response. Have you already set the .setLifecycleOwner(lifecycleOwner) on your Balloon.Builder() when you create your own balloon?

skydoves avatar Aug 10 '25 07:08 skydoves

no I did not use .setLifecycleOwner(lifecycleOwner) , is this also needed for the Compose version @skydoves ? Thanks

zenyagami avatar Aug 10 '25 09:08 zenyagami

@zenyagami It automatically sets the lifecycle owner by using findViewTreeLifecycleOwner but there's any some reasons it doesn't find any bound lifecycle owner, so it would be great to set it explicitly as possible if you can. For example, it can really reproduced easily while the configuration changes happen but your balloon doesn't dismissed already.

skydoves avatar Aug 10 '25 10:08 skydoves

I tried to reproduce but I can't :/ , the logs I got it from sentry so it might happens that the app quickly changes configuration or it was in background and then back in configration change , but sadly I could not reproduce yet ,

zenyagami avatar Aug 10 '25 11:08 zenyagami

is this solved by any means, i even set lifecycleowners but it still crashes giving the same crash logs

walaankit avatar Aug 25 '25 07:08 walaankit

@walaankit not for me :/

zenyagami avatar Aug 25 '25 08:08 zenyagami

is there any update on this issue we are facing the same issue

Fatal Exception: java.lang.IllegalArgumentException: The width of the balloon must bigger than zero.
      at com.skydoves.balloon.Balloon$Builder.setMeasuredWidth(Balloon.java:2397)
      at com.skydoves.balloon.Balloon.updateSizeOfBalloonCard(Balloon.kt:1688)
      at com.skydoves.balloon.compose.BalloonComposeView.updateSizeOfBalloonCard-ozmzZPI$balloon_compose_release(BalloonComposeView.java:315)
      at com.skydoves.balloon.compose.BalloonKt$Balloon$4.invoke$lambda$1$lambda$0(Balloon.kt:144)
      at androidx.compose.ui.layout.OnGloballyPositionedNode.onGloballyPositioned(OnGloballyPositionedModifier.kt:75)
      at androidx.compose.ui.node.LayoutNode.dispatchOnPositionedCallbacks$ui_release(LayoutNode.java:1176)
      at androidx.compose.ui.node.OnPositionedDispatcher.dispatchHierarchy(OnPositionedDispatcher.kt:76)
      at androidx.compose.ui.node.OnPositionedDispatcher.dispatchHierarchy(OnPositionedDispatcher.kt:79)
      at androidx.compose.ui.node.OnPositionedDispatcher.dispatchHierarchy(OnPositionedDispatcher.kt:79)
      at androidx.compose.ui.node.OnPositionedDispatcher.dispatch(OnPositionedDispatcher.kt:67)
      at androidx.compose.ui.node.MeasureAndLayoutDelegate.dispatchOnPositionedCallbacks(MeasureAndLayoutDelegate.kt:719)
      at androidx.compose.ui.platform.AndroidComposeView.updatePositionCacheAndDispatch(AndroidComposeView.android.kt:1721)
      at androidx.compose.ui.platform.AndroidComposeView.onLayout(AndroidComposeView.android.kt:1687)
      at android.view.View.layout(View.java:24461)
      at android.view.ViewGroup.layout(ViewGroup.java:7412)
      at androidx.compose.ui.platform.AbstractComposeView.internalOnLayout$ui_release(ComposeView.android.kt:320)
      at androidx.compose.ui.window.PopupLayout.internalOnLayout$ui_release(AndroidPopup.android.kt:608)
      at androidx.compose.ui.platform.AbstractComposeView.onLayout(ComposeView.android.kt:310)
      at android.view.View.layout(View.java:24461)
      at android.view.ViewGroup.layout(ViewGroup.java:7412)
      at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:4614)
      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4036)
      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2924)
      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10513)
      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1108)
      at android.view.Choreographer.doCallbacks(Choreographer.java:866)
      at android.view.Choreographer.doFrame(Choreographer.java:797)
      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1092)
      at android.os.Handler.handleCallback(Handler.java:938)
      at android.os.Handler.dispatchMessage(Handler.java:99)
      at android.os.Looper.loopOnce(Looper.java:226)
      at android.os.Looper.loop(Looper.java:313)
      at android.app.ActivityThread.main(ActivityThread.java:8751)
      at java.lang.reflect.Method.invoke(Method.java)
      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

sureshmaidaragi1919 avatar Sep 11 '25 06:09 sureshmaidaragi1919

@sureshmaidaragi1919 I can't reproduce it yet but it happens on my crash logs I tried to set minimum size, wait until the screen is ready and nothing, still getting this crash @skydoves any suggestion?

zenyagami avatar Sep 11 '25 08:09 zenyagami

Hey @zenyagami, a new version 1.7.0 has been released, and now this issue should be resolved. If you still face the same issue, please reopen this one. Thank you!

skydoves avatar Dec 21 '25 06:12 skydoves