Balloon
:balloon: Modernized and sophisticated tooltips, fully customizable with an arrow and animations for Android and Jetpack Compose.
Install / Use
/learn @skydoves/BalloonREADME
Who's using Balloon?
👉 Check out who's using Balloon
Balloon hits +800,000 downloads every month around the globe! :balloon:

Balloon in Jetpack Compose
If you want to use Balloon in your Jetpack Compose project, check out the Balloon in Jetpack Compose section. You can also check out the blog post Tooltips for Jetpack Compose: Improve User Experience to the Next Level for more details.
💝 Sponsors
<a href="https://coderabbit.link/Jaewoong" target="_blank"> <img width="300" alt="coderabbit" src="https://www.coderabbit.ai/_next/image?url=https%3A%2F%2Fvictorious-bubble-f69a016683.media.strapiapp.com%2FCr_logo_dark_f656abe8e3.png&w=384&q=75" /></a>
<a href="https://getstream.io/chat/sdk/android/?utm_source=github&utm_medium=referral&utm_content=&utm_campaign=Jaewoong_github_2025" target="_blank"> <img width="260" alt="stream" src="https://github.com/user-attachments/assets/87a69228-4fef-4f48-ad98-1e2c606c5b7e" /></a>
Including in your project
Gradle
Add the dependency below to your module's build.gradle file:
dependencies {
implementation("com.github.skydoves:balloon:1.7.5")
}
How to Use
Balloon supports both Kotlin and Java projects, so you can reference it by your language.
Create Balloon with Kotlin
We can create an instance of the Balloon with the Balloon.Builder class.
val balloon = Balloon.Builder(context)
.setWidthRatio(1.0f)
.setHeight(BalloonSizeSpec.WRAP)
.setText("Edit your profile here!")
.setTextColorResource(R.color.white_87)
.setTextSize(15f)
.setIconDrawableResource(R.drawable.ic_edit)
.setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
.setArrowSize(10)
.setArrowPosition(0.5f)
.setPadding(12)
.setCornerRadius(8f)
.setBackgroundColorResource(R.color.skyBlue)
.setBalloonAnimation(BalloonAnimation.ELASTIC)
.setLifecycleOwner(lifecycle)
.build()
Create Balloon with Kotlin DSL
We can also create an instance of the Balloon with the Kotlin DSL.
<details> <summary>Keep reading for more details</summary>You can create an instance of the Balloon with createBalloon as the example below:
val balloon = createBalloon(context) {
setWidthRatio(1.0f)
setHeight(BalloonSizeSpec.WRAP)
setText("Edit your profile here!")
setTextColorResource(R.color.white_87)
setTextSize(15f)
setIconDrawableResource(R.drawable.ic_edit)
setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
setArrowSize(10)
setArrowPosition(0.5f)
setPadding(12)
setCornerRadius(8f)
setBackgroundColorResource(R.color.skyBlue)
setBalloonAnimation(BalloonAnimation.ELASTIC)
setLifecycleOwner(lifecycle)
build()
}
</details>
Create Balloon with Java
You can create an instance of the Balloon with Java by using the Balloon.Builder class.
You can create an instance of the Balloon as the following example below:
Balloon balloon = new Balloon.Builder(context)
.setArrowSize(10)
.setArrowOrientation(ArrowOrientation.TOP)
.setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
.setArrowPosition(0.5f)
.setWidth(BalloonSizeSpec.WRAP)
.setHeight(65)
.setTextSize(15f)
.setCornerRadius(4f)
.setAlpha(0.9f)
.setText("You can access your profile from now on.")
.setTextColor(ContextCompat.getColor(context, R.color.white_93))
.setTextIsHtml(true)
.setIconDrawable(ContextCompat.getDrawable(context, R.drawable.ic_profile))
.setBackgroundColor(ContextCompat.getColor(context, R.color.colorPrimary))
.setOnBalloonClickListener(onBalloonClickListener)
.setBalloonAnimation(BalloonAnimation.FADE)
.setLifecycleOwner(lifecycleOwner)
.build();
</details>
Show up Balloon
We can show up the Balloon using the functions below. If we use showAlign__ method, we can show up the Balloon based on alignments (top, bottom, right, left). Also, we can adjust specific positions of the Balloon by using x-Offset and y-Offset parameters. <br>
balloon.showAlignTop(anchor: View) // shows the balloon on an anchor view as the top alignment.
balloon.showAlignTop(anchor: View, xOff: Int, yOff: Int) // shows top alignment with x-off and y-off.
balloon.showAlignBottom(anchor: View) // shows the balloon on an anchor view as the bottom alignment.
balloon.showAlignBottom(anchor: View, xOff: Int, yOff: Int) // shows bottom alignment with x-off and y-off.
balloon.showAlignEnd(anchor: View) // shows the balloon on an anchor view as the end alignment.
balloon.showAlignEnd(anchor: View, xOff: Int, yOff: Int) // shows end alignment with x-off and y-off.
balloon.showAlignStart(anchor: View) // shows the balloon on an anchor view as the start alignment.
balloon.showAlignStart(anchor: View, xOff: Int, yOff: Int) // shows start alignment with x-off and y-off.
balloon.showAsDropDown(anchor: View) // shows the balloon as a dropdown without any alignments.
balloon.showAsDropDown(anchor: View, xOff: Int, yOff: Int) // shows no alignments with x-off and y-off.
balloon.showAtCenter(anchor: View, xOff: Int, yOff: Int, centerAlign: BalloonCenterAlign.TOP)
// shows the balloon over the anchor view (overlap) as the center aligns.
Also, We can show up the Balloon with Kotlin extensions.
myButton.showAlignTop(balloon)
Dismiss Balloon
We can dismiss the Balloon by using the Balloon.dismiss() method.
balloon.dismiss()
balloon.dismissWithDelay(1000L) // dismisses 1000 milliseconds later when the popup is shown
We can dismiss automatically with a delay after the Balloon is shown using the setAutoDismissDuration method.
Balloon.Builder(context)
// dismisses automatically 1000 milliseconds later when the popup is shown.
.setAutoDismissDuration(1000L)
...
Show up Balloon Sequentially
We can show up a couple of Balloons sequentially with the relayShow__ and await__ methods.
customListBalloon
.relayShowAlignBottom(customProfileBalloon, circleImageView) // relay to customListBalloon
.relayShowAlignTop(customTagBalloon, bottomNavigationView, 130, 0) // relay to customProfileBalloon
// show sequentially customListBalloon-customProfileBalloon-customTagBalloon
customListBalloon.showAlignBottom(anchorView)
coroutineScope.launch {
customListBalloon.awaitAlignBottom(anchorView)
customProfileBalloon.awaitAlignBottom(circleImageView, 0, 0)
customTagBalloon.awaitAlignTop(bottomNavigationView, 130, 0)
}
Note: The
relayShow__andawait__methods overwrite thesetOnDismissListenerinternally, so you can't use thesetOnDismissListenerat the same time.
Parallel Displaying
We can show multiple balloons at the same time with sequential behavior.
lifecycleScope.launch {
// shows balloons at the same time
awaitBalloons {
// dismissing of any balloon dismisses all of them. Default behaviour
dismissSequentially = false
textView.alignTop(balloonAlignTop)
textView.alignStart(balloonAlignStart)
textView.alignEnd(balloonAlignEnd)
textView.alignBottom(balloonAlignBottom)
}
// s
