skydoves/Balloon là dự án Kotlin với 4.0k sao trong nhóm Mobile. :balloon: Modernized and sophisticated tooltips, fully customizable with an arrow and animations for Compose and Kotlin Multiplatform.
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
:balloon: Modernized and sophisticated tooltips for Compose Multiplatform, fully customizable with an arrow and animations.
Who's using Balloon?
👉 Check out who's using Balloon
Balloon hits +800,000 downloads every month around the globe! :balloon:
What's new in 2.0.0
Balloon 2.0.0 is a full rewrite on Compose Multiplatform. One artifact now runs on Android,
iOS, Desktop (JVM), and Web (Wasm), and everything is drawn by Compose instead of a
PopupWindow. There is no Context, no View, and no XML anywhere in the API.
If you are coming from 1.x, read the Migration guide from 1.x to 2.0.0.
The View based implementation is still available at version 1.7.6, documented under
Balloon 1.x (View).
💝 Sponsors
Including in your project
Gradle
Add the dependency below to your module's build.gradle.kts file.
A balloon is made of two things: a style that describes how it looks, and a state that
decides when it shows.
val style = rememberBalloonBuilder {
setArrowSize(10.dp)
setArrowPosition(0.5f)
setWidthRatio(0.7f)
setPadding(12.dp)
setCornerRadius(8.dp)
setBackgroundColor(Color(0xFF785EF0))
setBalloonAnimation(BalloonAnimation.ELASTIC)
}
val balloonState = rememberBalloonState(style)
Then attach it to an anchor. There are two ways to do that.
Balloon composable
Wrap the anchor with the Balloon composable. The balloon body goes in balloonContent, and
the anchor goes in the trailing lambda.
Balloon(
state = balloonState,
balloonContent = {
Text(
text = "Now you can edit your profile!",
color = Color.White,
)
},
) {
Button(onClick = { balloonState.showAlignTop() }) {
Text(text = "Edit profile")
}
}
Modifier.balloon
If you would rather decorate an existing composable than wrap it, use Modifier.balloon. It
needs a BalloonHost somewhere above it, which is what actually renders the popup and the
overlay scrim.
BalloonHost {
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
Button(
modifier = Modifier.balloon(balloonState) {
Text(text = "Now you can edit your profile!", color = Color.White)
},
onClick = { balloonState.showAlignTop() },
) {
Text(text = "Edit profile")
}
}
}
Wrap your screen in BalloonHost once and every Modifier.balloon below it works. Forgetting
it throws an exception that says so, instead of silently rendering nothing.
Showing and dismissing
BalloonState is the single place that controls visibility.
balloonState.showAlignTop() // above the anchor
balloonState.showAlignBottom() // below the anchor
balloonState.showAlignStart() // leading side
balloonState.showAlignEnd() // trailing side
balloonState.showAsDropDown() // below, leading edges aligned
balloonState.showAtCenter(BalloonCenterAlign.TOP)
balloonState.show(BalloonAlign.BOTTOM, xOffset = 8.dp, yOffset = 4.dp)
balloonState.toggle()
balloonState.dismiss()
balloonState.update(BalloonAlign.TOP) // move without replaying the animation
balloonState.dismissWithDelay(scope, 1_500L)
balloonState.isVisible // observable in composition
Every show has a suspend twin that returns once the balloon is dismissed, which makes
sequences easy to write.
The arrow edge is derived from the alignment you show with, so it always points back at the
anchor without you naming it. When the requested side has no room and the opposite side does,
the balloon flips over and the arrow follows it. A final clamp keeps the balloon inside the
window.
To pin the arrow to a specific edge regardless of placement:
setIsVisibleArrow(true)
setArrowSize(10.dp) // square
setArrowSize(width = 16.dp, height = 8.dp) // base and protrusion
setArrowPosition(0.62f) // 0f..1f along the edge
setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
setArrowColor(Color.White)
ALIGN_BALLOON reads arrowPosition as a fraction of the balloon, and ALIGN_ANCHOR reads it
as a fraction of the anchor, so the arrow keeps pointing at the same spot on the anchor wherever
the balloon lands. Under ALIGN_ANCHOR the arrow is kept
arrowSize * arrowAlignAnchorPaddingRatio + arrowAlignAnchorPadding clear of the balloon's ends.
Size and spacing
setWidth(200.dp) // fixed
setWidthRatio(0.6f) // fraction of the window
setMinWidth(120.dp)
setMaxWidth(320.dp)
setMinWidthRatio(0.3f)
setMaxWidthRatio(0.9f)
setHeight(120.dp)
setSize(width = 200.dp, height = 120.dp)
setPadding(12.dp)
setPadding(start = 8.dp, top = 4.dp, end = 8.dp, bottom = 4.dp)
setPaddingHorizontal(16.dp)
setPaddingVertical(8.dp)
setMargin(12.dp)
setMarginHorizontal(16.dp)
setElevation(2.dp)
Width and height specs size the whole popup box, which is the visible card plus the margins and
the elevation inset. Set setElevation(0.dp) and no margin if you want the card itself to be
exactly the size you asked for.
A balloon with an overlay must sit under a BalloonHost, because a popup cannot cover the
system bars. The scrim fills the host's own bounds, so put BalloonHost at the root of an
edge-to-edge window with Modifier.fillMaxSize() if you want it to dim the whole screen.
NONE, HEARTBEAT, SHAKE, BREATH, and ROTATE. ROTATE takes its parameters from
setBalloonRotationAnimation(BalloonRotateAnimation(turns = 2, speedMillis = 1200)).
Listeners
Listeners are properties on the state rather than builder options, because BalloonStyle is
value equal data and lambdas would break that.
balloonState.onBalloonClick = { /* the body was tapped */ }
balloonState.onOverlayClick = { /* the scrim was tapped */ }
balloonState.onDismiss = { /* the balloon closed */ }
For a full reference of every option, see the documentation.
Getting Started
Showing a Balloon
Arrow
Size and Spacing
Customization
Overlay
Animation
Listeners
Migration from 1.x
Balloon 1.x (View)
Find this library useful? :heart:
Support it by joining stargazers for this repository. :star:
Also, follow me on GitHub for my next creations! 🤩
License
Designed and developed by 2019 skydoves (Jaewoong Eum)
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.
skydoves/Balloon thuộc nhóm Mobile trên TopGit, cùng 13 topic GitHub. Trang Trending và Topics liệt kê các repo cùng số sao và cùng ngôn ngữ để so sánh.
Đọc thêm về skydoves/Balloon ở đâu?
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/skydoves/Balloon là nguồn chính thức.
skydoves/Balloon có phải mã nguồn mở không?
Có — skydoves/Balloon phát hành theo license Apache-2.0, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/skydoves/Balloon.
skydoves/Balloon có trang demo không?
Dự án có trang chủ ở https://skydoves.github.io/Balloon/. Tab "Readme" ở trang này thường có ảnh chụp và hướng dẫn bắt đầu nhanh.
skydoves/Balloon dùng license gì?
skydoves/Balloon phát hành theo license Apache-2.0. Nên mở file LICENSE trên GitHub để xác nhận — license metadata đôi khi lệch với thực tế dự án.
skydoves/Balloon là gì?
skydoves/Balloon (skydoves/Balloon) là dự án Kotlin trên GitHub. Theo mô tả gốc: :balloon: Modernized and sophisticated tooltips, fully customizable with an arrow and animations for Compose and Kotlin Multiplatform.
Vì sao skydoves/Balloon được xếp vào nhóm Mobile?
TopGit xếp skydoves/Balloon vào nhóm Mobile dựa trên GitHub topics và mô tả của repo (gắn thẻ: "android", "android-library", "android-ui"). Việc phân loại dựa trên metadata thật của repo, không phải đoán theo cảm tính biên tập.
Đọc đầy đủ README ở tab phía trên.
Chưa chắc Balloon có hợp với bạn?
Để ChatGPT, Claude hoặc Perplexity tìm hiểu giúp — bấm bên dưới và xem AI nói gì về Balloon.