A lightweight tooltip popup for Android.
This posting is about how to implement a lightweight popup like tooltips, fully customizable with arrow and animations using Balloon library. The library provides kotlin dsl, many kinds of showing functions based on aligning, showing sequentially functions, arrow, text compositions, lazy initialization, preferences, and some functions for avoiding memory leak.
The balloon is one of the most popular libraries I have ever published.
The balloon is downloaded from more than 27,000 projects every month over the world. Thank you for your guy's interests :)
- 03.26 2022–200,000 downloads by month
And let’s start!
Including in your project
Firstly you should add a dependency code to your module’s build.gradle file.
dependencies {
implementation "com.github.skydoves:balloon:1.4.7"
}
The version could be different from the latest version.
If you want to use the latest version, you can check it here.
How to use
Here is a basic example of implementing balloon popup with icon and text using Balloon.Builder
class based on Java.
This is how to create aBalloon
instance using kotlin dsl.
There are more functions related to width, height, padding, icon, an arrow (position, size, drawable, orientation), background, radius, text color, icon, listeners, etc.
Show and dismiss
The balloon provides many kinds of the show and the dismiss functions.
Or we can show balloon popup using kotlin extension like below.
myButtom.showAlignTop(balloon)
We can dismiss simply usingdismiss
method.
balloon.dismiss()
balloon.dismissWithDelay(1000L) // dismisses 1000 milliseconds later when the popup is shown
We can dismiss automatically some milliseconds later when the popup is shown usingsetAutoDismissDuration
method on Balloon.Builder
.
Balloon.Builder(baseContext)
// dismisses automatically 1000 milliseconds later when the popup is shown.
.setAutoDismissDuration(1000L)
...
Show sequentially
Sometimes we want to show up the balloon sequentially for providing tooltips to users. We can suppose the below circumstances.
Balloon A Show -> (Balloon A onDismiss) -> Balloon B Show ->
(Balloon B Dismiss) -> Balloon C Show -> (Balloon C Dismiss) -> next step.
We can show balloon popup sequentially using relayShow
method.
The relayShow
method makes that setOnDismissListener
of the first balloon is reset to show the next balloon and returns an instance of the next balloon.
Arrow Composition
We can customize the arrow on the balloon popup. We can customize the visibility, size, position based on ratio, orientation and drawable.
.setArrowVisible(true) // sets the visibility of the arrow.
.setArrowSize(10) // sets the arrow size.
.setArrowPosition(0.8f) // sets the arrow position using the popup size's ratio (0 ~ 1.0)
.setArrowOrientation(ArrowOrientation.TOP) // sets the arrow orientation. top, bottom, left, right
.setArrowDrawable(ContextCompat.getDrawable(baseContext, R.drawable.arrow)) // sets the arrow drawable.
Below previews are implemented using setArrowOrientation
and setArrowPosition
methods.setArrowPosition
measures the balloon popup size and sets the arrow's position using the ratio value.
Text Composition
We can customize the text on the balloon popup. We can set the text string message, size, typeface, color.
.setText("You can edit your profile now!")
.setTextSize(15f)
.setTextTypeface(Typeface.BOLD)
.setTextColor(ContextCompat.getColor(baseContext, R.color.white_87))
Listeners
We can listen to the balloon popup is clicked, dismissed or touched outside using listeners.
We can simplify it using kotlin lambda.
.setOnBalloonClickListener { Toast.makeText(baseContext, "clicked", Toast.LENGTH_SHORT).show() }
.setOnBalloonDismissListener { Toast.makeText(baseContext, "dismissed", Toast.LENGTH_SHORT).show() }
.setOnBalloonOutsideTouchListener { Toast.makeText(baseContext, "touched outside", Toast.LENGTH_SHORT).show() }
Customized layout
We can fully customize the balloon layout using the below method.
.setLayout(R.layout.my_ballon_layout)
Firstly create an xml layout file like layout_custom_profile
on your taste.
And next, we can get the inflated custom layout using getContentView
method.
val button: Button =
balloon.getContentView().findViewById(R.id.button_edit)
button.setOnClickListener {
Toast.makeText(baseContext, "Edit", Toast.LENGTH_SHORT).show()
balloon.dismiss()
}
Avoid Memory leak
Dialog, PopupWindow and etc.. have memory leak issue if not dismissed before activity or fragment are destroyed. But Lifecycles are now integrated with the Support Library since Architecture Components 1.0 Stable released.
So we can solve the memory leak issue so easily.
Just use setLifecycleOwner
method. Then dismiss
method will be called automatically before activity or fragment would be destroyed.
.setLifecycleOwner(lifecycleOwner)
Lazy initialization
We can initialize the balloon property lazily using balloon
keyword and Balloon.Factory
abstract class. The balloon
extension keyword can be used on Activity
and Fragment
.
BeforeCustomActivity.kt
class CustomActivity : AppCompatActivity() {
private val profileBalloon by lazy { BalloonUtils.getProfileBalloon(context = this, lifecycleOwner = this) } // ...
}
AfterCustomActivity.kt
class CustomActivity : AppCompatActivity() {
private val profileBalloon by balloon(ProfileBalloonFactory::class) // ...
}
We should create a class which extends Balloon.Factory
.
An implementation class of the factory must have a default(non-argument) constructor.
That’s all!
If you want to get more information about the balloon library, you can check below the GitHub link. Thank you so much :)