2.0.1
Balloon 2.0.1 is a patch release on top of the 2.0 Compose Multiplatform rewrite.
-
The balloon no longer jumps to the top-left corner when its anchor scrolls off-screen (#1022, #1024). Anchor bounds were captured with
boundsInWindow(), which clips: an anchor scrolled out of aModifier.verticalScrollcolumn collapses toRect.Zero, so the balloon was placed against the window origin instead of its anchor, and the off-screen dismissal never fired.The anchor rect now comes from the anchor's own four corners, so a balloon stays glued to its anchor for the whole scroll. A balloon is dismissed once its anchor is genuinely out of view — including an anchor clipped away by a scrolling container while still inside the window, which was never detected before. An anchor that has not appeared yet does not count, so a balloon shown while its anchor is still animating in waits for it.
Compose Multiplatform:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("com.github.skydoves:balloon:2.0.1")
}
}
}
Android only:
dependencies {
implementation("com.github.skydoves:balloon:2.0.1")
}
Full Changelog: https://github.com/skydoves/Balloon/compare/2.0.0...2.0.1
2.0.0
Balloon 2.0.0 is a full rewrite on Compose Multiplatform. One artifact now runs on Android, iOS, Desktop and Web, and the API is composables and state instead of Context, View and XML.
If you need the View implementation, it stays available at 1.7.6 and is documented separately. Nothing about 1.x is going away.
| Target | Artifact |
|---|---|
| Android | balloon-android |
| Desktop (JVM) | balloon-desktop |
| iOS (arm64) | balloon-iosarm64 |
| iOS (simulator, arm64) | balloon-iossimulatorarm64 |
| iOS (x64) | balloon-iosx64 |
| Web (Wasm) | balloon-wasm-js |
Gradle picks the right one. Depend on com.github.skydoves:balloon and nothing else.
Compose Multiplatform:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("com.github.skydoves:balloon:2.0.0")
}
}
}
Android only:
dependencies {
implementation("com.github.skydoves:balloon:2.0.0")
}
balloon-compose is gone. It is folded into balloon.
val style = rememberBalloonBuilder {
setArrowSize(10.dp)
setPadding(12.dp)
setCornerRadius(8.dp)
setBackgroundColor(Color(0xFF785EF0))
setBalloonAnimation(BalloonAnimation.ELASTIC)
}
val balloonState = rememberBalloonState(style)
Balloon(
state = balloonState,
balloonContent = { Text(text = "Now you can edit your profile!", color = Color.White) },
) {
Button(onClick = { balloonState.showAlignTop() }) {
Text(text = "Edit profile")
}
}
Wrap your screen in BalloonHost { ... } once, at the root, and every balloon inside it works.
| 1.7.6 | 2.0.0 | |
|---|---|---|
| Artifacts | balloon, balloon-compose |
balloon |
| Platforms | Android | Android, iOS, Desktop (JVM), Web (Wasm) |
| Rendering | PopupWindow plus Android views |
Compose Popup and a Compose Shape |
| Package | com.skydoves.balloon, com.skydoves.balloon.compose |
com.skydoves.balloon |
| Content | setText, TextForm, IconForm, setLayout |
a @Composable slot |
| Anchoring | you pass a View to every show call |
BalloonState knows its own anchor |
| Lifecycle | setLifecycleOwner, manual disposal |
composition disposal |
There is no Context, no View, no Drawable, no Typeface and no XML anywhere in the API.
- Two ways to attach a balloon. Wrap an anchor with
Balloon(...), or decorate one in place withModifier.balloon(...). - A composable body. The balloon content is a slot, so you build it like any other UI. Interactive children work: a tap a child consumes never reaches the balloon's own handler.
- Coroutine friendly. Every
showhas asuspendtwin.awaitAlignBottom()returns when the balloon closes, so a sequence of tips reads as straight line code. - Restyle in place.
rememberBalloonStatere-applies the style on every recomposition, so an animated style updates a balloon that is already showing without hiding it. derive.base.derive { setBackgroundColor(Color.Red) }makes a variant of an existing style using the same builder block.- Placement that flips. When the requested side has no room and the opposite side has some, the balloon moves and the arrow follows it.
- A baseline profile ships in the Android artifact.
Every 1.x builder setter that has a multiplatform meaning is present, with the same name and the same defaults, so most builder blocks port across unchanged.
These behave differently from 1.7.6 on purpose. Each was found by rendering both implementations and diffing the result pixel by pixel.
- A hidden arrow takes no space.
setIsVisibleArrow(false)puts the body flush against the anchor. 1.x left anarrowHeight - 1pxgap. - The arrow points at the anchor by default. In 1.x
arrowOrientationdefaulted toBOTTOM, soshowAlignStart()on a default builder left the arrow pointing down. - Balloons flip instead of clamping. 1.x only flipped vertically, and horizontally it slid the balloon along the window edge until it overlapped its own anchor.
setBalloonStrokedraws the thickness you asked for, around the arrow too.- No drop shadow.
elevationreserves its space and drives the width math, but the shadow is not drawn: Compose can only cast a shadow from a convex outline, and a balloon with an arrow notch is not convex. UseModifier.shadow(...)inside the slot if you need one. BalloonOverlayShape.CircleandRoundRecttakeDp, where 1.x took raw pixels. Convert deliberately.- The arrow never enters a rounded corner. Its base is clamped
cornerRadius + arrowWidth / 2in from each end. setAutoDismissDuration(0L)means "never". 1.x used-1Las the disabled sentinel and treated0Las "dismiss immediately".BalloonHighlightAnimation.ROTATEanimates out of the box. In 1.x it did nothing without an explicitsetBalloonRotationAnimation.
Everything else matches to the pixel.
Mostly Android only surface with no multiplatform equivalent:
setText,TextForm,IconForm,setLayout, and everything taking a resource id. Use the composable slot.setOnBalloonTouchListenerandsetOnBalloonOutsideTouchListener.MotionEventis Android only. UseModifier.pointerInputinside the slot.setPreferenceName,setShowCounts,runIfReachedShowCounts. No multiplatform key value store is assumed. Gateshow()with your own storage.setLifecycleOwner,setDismissWhenLifecycleOnPause,setLifecycleObserver. Composition disposal dismisses the balloon.setIsStatusBarVisible,setIsAttachedInDecor,setIsClippingEnabled,setRtlSupports.PopupWindowspecific, or handled byLocalLayoutDirection.
Listeners moved from the builder onto the state: balloonState.onBalloonClick, onDismiss and onOverlayClick.
The migration guide maps every 1.x setter to its 2.0.0 counterpart, including the ones that were dropped and what to use instead.
- Overview and quick start
- Getting started
- Showing a balloon
- Arrow, Size and spacing, Customization
- Overlay, Animation, Listeners
- Balloon 1.x (View) for the 1.7.6 API
The View implementation is unchanged and still published. Keep using it with:
implementation("com.github.skydoves:balloon:1.7.6")
implementation("com.github.skydoves:balloon-compose:1.7.6")
2.0.0 does not replace it in place. It is a different API under the same coordinates, so pin the version you want.
1.7.6
- Update androidxMacroBenchmark to v1.5.0-alpha04 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/954
- Update dependency androidx.activity:activity-compose to v1.13.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/955
- Update dependency androidx.compose:compose-bom to v2026.03.00 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/956
- Update Gradle to v9.4.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/957
- Handle demo activity insets for edge-to-edge system bars by @chinmaydash007 in https://github.com/skydoves/Balloon/pull/958
- Update androidxMacroBenchmark to v1.5.0-alpha05 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/959
- Update dependency androidx.compose:compose-bom to v2026.03.01 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/960
- Update dokka to v2.2.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/961
- Update dependency androidx.annotation:annotation to v1.10.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/962
- Update agp to v9.1.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/964
- Use findContext for looking up app context by @skydoves in https://github.com/skydoves/Balloon/pull/965
- Set the min height size by @skydoves in https://github.com/skydoves/Balloon/pull/966
- The balloon renders in a PopupWindow for the compatibilities by @skydoves in https://github.com/skydoves/Balloon/pull/967
- @chinmaydash007 made their first contribution in https://github.com/skydoves/Balloon/pull/958
Full Changelog: https://github.com/skydoves/Balloon/compare/1.7.5...1.7.6
1.7.5
- Update agp to v9.1.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/948
- Update Gradle to v9.4.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/949
- Apply effectiveMaxWidth for the size compatibilities by @skydoves in https://github.com/skydoves/Balloon/pull/950
- Add snapshot workflows by @skydoves in https://github.com/skydoves/Balloon/pull/951
Full Changelog: https://github.com/skydoves/Balloon/compare/1.7.4...1.7.5
1.7.4
- Update Gradle to v9.3.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/926
- Update dependency com.vanniktech.maven.publish to v0.36.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/927
- Update dependency androidx.compose:compose-bom to v2026 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/924
- Update dependency org.robolectric:robolectric to v4.16.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/928
- Update actions/setup-java action to v5.2.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/929
- Update actions/checkout action to v6.0.2 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/930
- Update dependency io.mockk:mockk to v1.14.9 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/931
- Update dependency io.mockk:mockk-android to v1.14.9 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/932
- Update dependency androidx.compose:compose-bom to v2026.01.01 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/933
- Update Gradle to v9.3.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/934
- Update dependency androidx.activity:activity-compose to v1.12.3 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/935
- Migrate to AGP 9 by @skydoves in https://github.com/skydoves/Balloon/pull/936
- Update androidxMacroBenchmark to v1.5.0-alpha03 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/938
- Update dependency androidx.activity:activity-compose to v1.12.4 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/939
- Update dependency androidx.compose:compose-bom to v2026.02.00 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/940
- Update agp to v9.0.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/941
- Update dependency androidx.compose:compose-bom to v2026.02.01 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/942
- Remove limits of the width ratio by @skydoves in https://github.com/skydoves/Balloon/pull/944
- Narrow consumer ProGuard rules to only reflection-dependent classes by @skydoves in https://github.com/skydoves/Balloon/pull/945
- Add missing balloon.builder size measurements by @skydoves in https://github.com/skydoves/Balloon/pull/946
- Bump Kotlin to 2.3.10 by @skydoves in https://github.com/skydoves/Balloon/pull/947
Full Changelog: https://github.com/skydoves/Balloon/compare/1.7.3...1.7.4
1.7.3
- Add anchorParent and prevent measure for Constraints.Infinity by @skydoves in https://github.com/skydoves/Balloon/pull/921
- Calculate transition x, y values for the showAsDropDown by @skydoves in https://github.com/skydoves/Balloon/pull/922
- Use ViewGroup.MarginLayoutParams instead of FrameLayout by @skydoves in https://github.com/skydoves/Balloon/pull/923
Full Changelog: https://github.com/skydoves/Balloon/compare/1.7.2...1.7.3
1.7.2
- Add isClippingEnabled property by @skydoves in https://github.com/skydoves/Balloon/pull/916
- Add BalloonState.update() function to remeasure the layout contents by @skydoves in https://github.com/skydoves/Balloon/pull/917
Full Changelog: https://github.com/skydoves/Balloon/compare/1.7.1...1.7.2
1.7.1
- Configure mk docs by @skydoves in https://github.com/skydoves/Balloon/pull/905
- Add unit tests and ui tests for balloon and balloon-compose by @skydoves in https://github.com/skydoves/Balloon/pull/906
- Update dependency com.google.truth:truth to v1.4.5 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/907
- Update dependency androidx.test.espresso:espresso-core to v3.7.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/908
- Update dependency androidx.test.ext:junit to v1.3.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/909
- Update dependency io.mockk:mockk to v1.14.7 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/910
- Update dependency io.mockk:mockk-android to v1.14.7 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/911
- Update dependency org.robolectric:robolectric to v4.16 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/912
- Balloon Compose: fix fixed-width tooltip content clamped to anchor constraints by @gamer3dx in https://github.com/skydoves/Balloon/pull/913
- @gamer3dx made their first contribution in https://github.com/skydoves/Balloon/pull/913
Full Changelog: https://github.com/skydoves/Balloon/compare/1.7.0...1.7.1
1.7.0
Release Notes for Balloon 1.7.0.
- Introduce Modifier.balloon() and BalloonState for Jetpack Compose (#904)
- New modifier-based API for attaching balloon tooltips to composables
- rememberBalloonState() for managing balloon state
- Deprecates the Balloon() composable and BalloonWindow interface
- Support individual properties for BalloonOverlayRoundRect (#903)
- Allows setting individual corner radii for overlay round rectangles
- Implement effective arrow sizes (#900)
- Better arrow size calculations for improved positioning
Now, the Balloon composable function will be deprecated. Migration guides from Balloon composable to Modifier.balloon():
Before (Deprecated)
var balloonWindow: BalloonWindow? by remember { mutableStateOf(null) }
Balloon(
builder = builder,
onBalloonWindowInitialized = { balloonWindow = it },
onComposedAnchor = { balloonWindow?.showAlignTop() },
balloonContent = {
Text(text = "Tooltip content")
},
) {
Button(onClick = { balloonWindow?.showAlignTop() }) {
Text(text = "Show Balloon")
}
}
After (New API)
val balloonState = rememberBalloonState(builder)
LaunchedEffect(Unit) {
balloonState.showAlignTop()
}
Button(
modifier = Modifier.balloon(balloonState) {
Text(text = "Tooltip content")
},
onClick = { balloonState.showAlignTop() },
) {
Text(text = "Show Balloon")
}
- Disable focus to prevent focus highlight on D-pad navigation (#902)
- Apply stroke/border in non-clipped mode as well (#901)
- Migrate to Subcompose layout to measure layout sizes (#898)
- Fixes black screen issue during SplashScreen (#786)
- Correct measuring logic with adjusted padding sequences (#897)
- Use EXACTLY mode for fixed heights, AT_MOST for wrap content (#896)
- Fixes nested layout measurement issues
- Fix: Clear any theme-applied background tint (#893)
The following APIs are now deprecated in favor of the new Modifier.balloon() API:
- Balloon() composable - Use Modifier.balloon() with rememberBalloonState()
- BalloonWindow interface - Use BalloonState
- rememberBalloonWindow() - Use rememberBalloonState()
- awaitBalloonWindows() and AwaitBalloonWindowsDsl
1.6.13
- Update dependency androidx.compose:compose-bom to v2025.01.01 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/778
- Update dependency androidx.fragment:fragment-ktx to v1.8.6 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/783
- Update dependency androidx.compose:compose-bom to v2025.02.00 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/784
- Update agp to v8.8.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/785
- Update dependency gradle to v8.13 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/788
- Update agp to v8.8.2 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/789
- Update dependency androidx.activity:activity-compose to v1.10.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/790
- Update dependency androidx.constraintlayout:constraintlayout-compose to v1.1.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/791
- Update agp to v8.9.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/793
- Update dependency com.vanniktech.maven.publish to v0.31.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/794
- Update dependency androidx.compose:compose-bom to v2025.03.00 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/795
- Update dependency com.github.skydoves:compose-stable-marker to v1.0.6 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/796
- Update agp to v8.9.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/797
- Update androidxMacroBenchmark to v1.3.4 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/798
- Update dependency androidx.compose:compose-bom to v2025.03.01 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/799
- Update actions/setup-java action to v4.7.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/801
- Update dependency androidx.compose:compose-bom to v2025.04.00 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/802
- Docs: fix typos by @tobioyelekan in https://github.com/skydoves/Balloon/pull/803
- Update agp to v8.9.2 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/804
- Update dependency androidx.compose:compose-bom to v2025.04.01 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/805
- Update dependency gradle to v8.14 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/806
- Update agp to v8.10.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/809
- Update dependency androidx.compose:compose-bom to v2025.05.00 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/810
- Update dependency androidx.lifecycle:lifecycle-runtime-ktx to v2.9.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/811
- Update dependency com.vanniktech.maven.publish to v0.32.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/812
- Update dependency androidx.compose:compose-bom to v2025.05.01 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/814
- Update dependency androidx.fragment:fragment-ktx to v1.8.7 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/815
- Update dependency gradle to v8.14.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/816
- Update agp to v8.10.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/817
- Added BalloonOverlayPadding data class for customizable overlay paddings and done some minor refactoring. by @hemantj99 in https://github.com/skydoves/Balloon/pull/813
- Update dependency androidx.appcompat:appcompat to v1.7.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/818
- Update dependency androidx.fragment:fragment-ktx to v1.8.8 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/819
- Update dependency androidx.lifecycle:lifecycle-runtime-ktx to v2.9.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/820
- Update dependency androidx.compose:compose-bom to v2025.06.00 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/821
- Update dependency gradle to v8.14.2 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/822
- Update dependency androidx.compose:compose-bom to v2025.06.01 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/823
- Update dependency com.vanniktech.maven.publish to v0.33.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/825
- Update agp to v8.11.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/826
- Update dependency gradle to v8.14.3 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/827
- Update agp to v8.11.1 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/830
- Update dependency com.vanniktech.maven.publish to v0.34.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/831
- Update dependency androidx.compose:compose-bom to v2025.07.00 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/833
- Update dependency androidx.lifecycle:lifecycle-runtime-ktx to v2.9.2 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/834
- Update agp to v8.12.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/835
- Update androidxMacroBenchmark to v1.4.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/836
- Update dependency androidx.test:runner to v1.7.0 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/837
- Update dependency gradle to v9 by @renovate[bot] in https://github.com/skydoves/Balloon/pull/838
- Stroke balloon by @tobioyelekan in https://github.com/skydoves/Balloon/pull/829
- Enable isClipArrowEnabled by default by setting setBalloonStroke by @skydoves in https://github.com/skydoves/Balloon/pull/839
- Rollback adding the padding values for the elevation by @skydoves in https://github.com/skydoves/Balloon/pull/840
- @tobioyelekan made their first contribution in https://github.com/skydoves/Balloon/pull/803
- @hemantj99 made their first contribution in https://github.com/skydoves/Balloon/pull/813
Full Changelog: https://github.com/skydoves/Balloon/compare/1.6.12...1.6.13