Coder Social home page Coder Social logo

skydoves / balloon Goto Github PK

View Code? Open in Web Editor NEW
3.6K 28.0 285.0 2.65 MB

:balloon: Modernized and sophisticated tooltips, fully customizable with an arrow and animations for Android.

Home Page: https://skydoves.github.io/libraries/balloon/html/balloon/com.skydoves.balloon/index.html

License: Apache License 2.0

Kotlin 100.00%
kotlin android android-library popup animation dsl balloon tooltip tooltips android-ui

balloon's Introduction

Balloon


๐ŸŽˆ Modernized and sophisticated tooltips, fully customizable with an arrow and animations on Android.


Google Twitter LinkedIn
License API Build Status Medium Profile Dokka


Who's using Balloon?

๐Ÿ‘‰ Check out who's using Balloon

Balloon hits +500,000 downloads every month around the globe! ๐ŸŽˆ

globe

Balloon in Jetpack Compose

If you want to use Balloon in your Jetpack Compose project, check out the Balloon in Jetpack Compose guidelines. You can also check out the blog post Tooltips for Jetpack Compose: Improve User Experience to the Next Level for more details.

Including in your project

Maven Central

Gradle

Add the dependency below to your module's build.gradle file:

dependencies {
    implementation("com.github.skydoves:balloon:1.6.4")
}

SNAPSHOT

Balloon

See how to import the snapshot

Including the SNAPSHOT

Snapshots of the current development version of Balloon are available, which track the latest versions.

To import snapshot versions on your project, add the code snippet below on your gradle file.

repositories {
   maven(url = "https://oss.sonatype.org/content/repositories/snapshots/")
}

Next, add the below dependency to your module's build.gradle file.

dependencies {
    implementation("com.github.skydoves:balloon:1.6.5-SNAPSHOT")
}

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.

Keep reading for more details

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()
}

Create Balloon with Java

You can create an instance of the Balloon with Java by using the Balloon.Builder class.

Keep reading for more details

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();

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.

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 delay after the Balloon is showing up with 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__ and await__ methods overwrite the setOnDismissListener internally, so you can't use the setOnDismissListener at the same time.

Parallel Displaying

We can show multiple balloons at the same with sequential behaviour.

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)
  }

  // shows another group after dismissing the previous group.
  awaitBalloons {
    dismissSequentially = true // balloons dismissed individually

    imageView.alignTop(balloonAlignTop)
    imageView.alignStart(balloonAlignStart)
    imageView.alignEnd(balloonAlignEnd)
    imageView.alignBottom(balloonAlignBottom)
  }
}

Note: The methods inside awaitBalloons are atCenter, asDropdown, alignTop and etc. Don't confuse with show__ and await__ methods.

Width and height

We can adjust specific width and height sizes of Balloon with the below builder methods. If we don't set any specific sizes of the width and height of the Balloon, the size of the Balloon will be decided by the content.

Specific size

We can set specific sizes of the Balloon regardless size of the contents.

balloon.setWidth(220) // sets 220dp width size.
balloon.setHeight(160) // sets 160dp height size.

Wrap Content Sizes

We can set dynamic sizes of Balloon, which depends on sizes of the internal content.

balloon.setWidth(BalloonSizeSpec.WRAP) // sets width size depending on the content's size.
balloon.setHeight(BalloonSizeSpec.WRAP) // sets height size depending on the content's size.

Depending on Screen Size

Also, we can set the width size depending on the ratio of the screen's size (horizontal).

balloon.setWidthRatio(0.5f) // sets width as 50% of the horizontal screen's size.

Padding

Balloon wraps contents. We can adjust the content size of the Balloon by adding paddings on the content like.

balloon.setPadding(6) // sets 6dp padding to all directions (left-top-right-bottom)
balloon.setPaddingLeft(8) // sets 8dp padding to content's left.
balloon.setPaddingTop(12) // sets 12dp padding to content's top.

Margin

If the location of the balloon according to the anchor would be located at the boundaries on the screen,
the balloon will be stick to the end of the screen. In this case, we can give horizontal margins to the balloon.

.setMargin(12) // sets the margin on the balloon all directions.
.setMarginLeft(14) // sets the left margin on the balloon.
.setMarginRight(14) // sets the right margin on the balloon.

Arrow Composition

We can customize the arrow on the Balloon with various methods. For more details, check out the Balloon.Builder.

.setIsVisibleArrow(true) // sets the visibility of the arrow.
.setArrowSize(10) // sets the arrow size.
.setArrowSize(BalloonSizeSpec.WRAP) // sets arrow size depending on the original resources' 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(context, R.drawable.arrow)) // sets the arrow drawable.

ArrowPositionRules

We can decide the position of the arrow depending on the aligning rules with the ArrowPositionRules.

// Align the arrow position depending on an anchor.
// if `arrowPosition` is 0.5, the arrow will be located in the middle of an anchor.
.setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR) // default

// Align the arrow position depending on the balloon popup body.
// if `arrowPosition` is 0.5, he arrow will be located in the middle of the tooltip.
.setArrowPositionRules(ArrowPositionRules.ALIGN_BALLOON)

ArrowOrientationRules

We can decide the orientation of the arrow depending on the aligning rules with the ArrowOrientationRules.

// Align depending on the position of an anchor.
// For example, `arrowOrientation` is ArrowOrientation.TOP and 
// we want to show up the balloon under an anchor using the `Balloon.showAlignBottom`.
// However, if there is not enough free space to place the tooltip at the bottom of the anchor,
// tooltips will be placed top of the anchor and the orientation of the arrow will be `ArrowOrientation.BOTTOM`.
.setArrowOrientationRules(ArrowOrientationRules.ALIGN_ANCHOR) // default

// Align to fixed ArrowOrientation value.
.setArrowOrientationRules(ArrowOrientationRules.ALIGN_FIXED)

Below previews are shows examples of setArrowOrientation and setArrowPosition methods.
The setArrowPosition measures the Balloon's size and sets the arrow's position with the ratio value.

Orientation: BOTTOM
Position: 0.62
showAlignTop
Orientation: TOP
Position : 0.5
showAlignBottom
Orientation: START
Position: 0.5
showAlignStart
Orientation: END
Position: 0.5
showAlignEnd

Text Composition

We can customize the text on the Balloon.

.setText("You can edit your profile now!")
.setTextSize(15f)
.setTextTypeface(Typeface.BOLD)
.setTextColorResource(R.color.colorAccent))
.setTextGravity(Gravity.START)

If your text includes HTML tags, you can render the text by enabling HTML option with setTextIsHtml method.

.setTextIsHtml(true)

This method will parse the text with the Html.fromHtml(text) internally.

TextForm

TextForm has some attributes for TextView to customize the text of the Balloon. You can create the TextForm instance and reuse it on multiple Balloons.

val textForm = TextForm.Builder(context)
  .setText("Edit you profile here!")
  .setTextColorResource(R.color.white_87)
  .setTextSize(14f)
  .setTextTypeface(Typeface.BOLD)
  .build()

val balloon = Balloon.Builder(context)
  .setTextForm(textForm)
  ...
Create TextForm with Kotlin DSL

You can create an instance of the TextForm with Kotlin DSL as the example below:

val textForm = textForm(context) {
  setText("Edit you profile here!")
  setTextColorResource(R.color.white_87)
  setTextSize(14f)
  setTextTypeface(Typeface.BOLD)
}

val balloon = Balloon.Builder(context)
  .setTextForm(textForm)
  ...
Create TextForm with Java

You can create an instance of the TextForm with Java as the example below:

TextForm textForm = new TextForm.Builder(context)
  .setText("Edit you profile here!")
  .setTextColorResource(R.color.white_87)
  .setTextSize(14f)
  .setTextTypeface(Typeface.BOLD)
  .build();

Balloon balloon = new Balloon.Builder(context)
  .setTextForm(textForm)
  ...

Icon Composition

We can customize the icon on the balloon.

.setIconSpace(10) // sets right margin of the icon.
.setIconSize(20) // sets size of the icon.
.setIconDrawable(ContextCompat.getDrawable(context, R.drawable.ic_edit)) // sets a drawable resource.

IconForm

IconForm has some attributes for ImageView to customize the icon of the Balloon. You can create the IconForm instance and reuse it on multiple Balloons.

val iconForm = IconForm.Builder(context)
  .setDrawable(ContextCompat.getDrawable(context, R.drawable.arrow))
  .setIconColor(ContextCompat.getColor(context, R.color.skyblue))
  .setIconSize(20)
  .setIconSize(12)
  .build()

val balloon = Balloon.Builder(context)
  .setIconForm(iconForm)
  ...  
Create IconForm with Kotlin DSL

You can create an instance of the IconForm with Kotlin DSL as the example below:

val iconForm = iconForm(context) {
  setDrawable(ContextCompat.getDrawable(context, R.drawable.arrow))
  setIconColor(ContextCompat.getColor(context, R.color.skyblue))
  setIconSize(20)
  setIconSize(12)
}

val balloon = Balloon.Builder(context)
  .setIconForm(iconForm)
  ...
Create IconForm with Java

You can create an instance of the IconForm with Java as the example below:

IconForm iconForm = new IconForm.Builder(context)
  .setDrawable(ContextCompat.getDrawable(context, R.drawable.arrow))
  .setIconColor(ContextCompat.getColor(context, R.color.skyblue))
  .setIconSize(20)
  .setIconSize(12)
  .build();

Balloon balloon = new Balloon.Builder(context)
  .setIconForm(iconForm)
  ...

OnBalloonClickListener, OnBalloonDismissListener, OnBalloonOutsideTouchListener

We can listen to if the Balloon is clicked, dismissed, and touched outside with the below listeners.

.setOnBalloonClickListener { Toast.makeText(context, "clicked", Toast.LENGTH_SHORT).show() }
.setOnBalloonDismissListener { Toast.makeText(context, "dismissed", Toast.LENGTH_SHORT).show() }
.setOnBalloonOutsideTouchListener { Toast.makeText(context, "touched outside", Toast.LENGTH_SHORT).show() }
Set Listeners with Java

You can set listeners with Java as the example below:

balloon.setOnBalloonClickListener(new OnBalloonClickListener() {
  @Override
  public void onBalloonClick() {
    // doSomething;
  }
});
    
balloon.setOnBalloonDismissListener(new OnBalloonDismissListener() {
  @Override
  public void onBalloonDismiss() {
    // doSomething;
  }
});

balloon.setOnBalloonOutsideTouchListener(new OnBalloonOutsideTouchListener() {
  @Override
  public void onBalloonOutsideTouch() {
    // doSomething;
  }
});

Custom Balloon Layout

You can fully customize the layout of the Balloon with the method below:

.setLayout(R.layout.my_balloon_layout)

You can build the Balloon with your own layout as the following example:

First, create your XML layout file like layout_custom_profile on your taste and set it on the with setLayout method.

val balloon = Balloon.Builder(context)
  .setLayout(R.layout.layout_custom_profile)
  .setArrowSize(10)
  .setArrowOrientation(ArrowOrientation.TOP)
  .setArrowPosition(0.5f)
  .setWidthRatio(0.55f)
  .setHeight(250)
  .setCornerRadius(4f)
  .setBackgroundColor(ContextCompat.getColor(this, R.color.black))
  .setBalloonAnimation(BalloonAnimation.CIRCULAR)
  .setLifecycleOwner(lifecycleOwner)
  .build()

That's all. If you need to get Views or need some interactions, you can get your custom layout with the getContentView() method from your instance of the Balloon.

val button: Button = 
  balloon.getContentView().findViewById(R.id.button_edit)
button.setOnClickListener {
  Toast.makeText(context, "Edit", Toast.LENGTH_SHORT).show()
  balloon.dismiss()
}

Persistence

If you want to show up the Balloon only once or a specific number of times, you can implement it as the following example:

balloon.setPreferenceName("MyBalloon") // sets preference name of the Balloon.
balloon.setShowCounts(3) // show-up three of times the popup. the default value is 1.
balloon.runIfReachedShowCounts {
  // do something after the preference showing counts is reached the goal.
  }

Also, you can clear all persisted preferences with the method below:

balloon.clearAllPreferences()

Avoid Memory leak

Dialog, PopupWindow etc, can have memory leak issues if not dismissed before the activity or fragment is destroyed.
But Lifecycles are now integrated with the Support Library since Architecture Components 1.0 Stable was released.
So we can solve the memory leak issue very easily like the below.

Just use setLifecycleOwner method. Then the dismiss() method will be called automatically before your activity or fragment would be destroyed.

.setLifecycleOwner(lifecycleOwner)

Lazy initialization

You can initialize a property of the Balloon lazily with the balloon() extension and Balloon.Factory abstract class.
The balloon() extension keyword can be used on your Activity, Fragment, and View.

Before
CustomActivity.kt

class CustomActivity : AppCompatActivity() {
  private val profileBalloon by lazy { BalloonUtils.getProfileBalloon(context = this, lifecycleOwner = this) }

  // ...
}

After
CustomActivity.kt

class CustomActivity : AppCompatActivity() {
  private val profileBalloon by balloon<ProfileBalloonFactory>()

  // ...
}

We should create a class which extends Balloon.Factory.
An implementation class of the factory must have a default(non-argument) constructor.

ProfileBalloonFactory.kt

class ProfileBalloonFactory : Balloon.Factory() {

  override fun create(context: Context, lifecycle: LifecycleOwner): Balloon {
    return createBalloon(context) {
      setLayout(R.layout.layout_custom_profile)
      setArrowSize(10)
      setArrowOrientation(ArrowOrientation.TOP)
      setArrowPosition(0.5f)
      setWidthRatio(0.55f)
      setHeight(250)
      setCornerRadius(4f)
      setBackgroundColor(ContextCompat.getColor(context, R.color.background900))
      setBalloonAnimation(BalloonAnimation.CIRCULAR)
      setLifecycleOwner(lifecycle)
    }
  }
}

BalloonOverlay

We can show up an overlay over the whole screen except an anchor view.

balloon.setIsVisibleOverlay(true) // sets the visibility of the overlay for highlighting an anchor.
balloon.setOverlayColorResource(R.color.overlay) // background color of the overlay using a color resource.
balloon.setOverlayPadding(6f) // sets a padding value of the overlay shape internally.  
balloon.setOverlayPaddingColorResource(R.color.colorPrimary) // sets color of the overlay padding using a color resource.
balloon.setBalloonOverlayAnimation(BalloonOverlayAnimation.FADE) // default is fade.
balloon.setDismissWhenOverlayClicked(false) // disable dismissing the balloon when the overlay is clicked.

We can change the shape of the highlighting using the .setOverlayShape method.

balloon.setOverlayShape(BalloonOverlayOval) // default shape
balloon.setOverlayShape(BalloonOverlayRect)
balloon.setOverlayShape(BalloonOverlayCircle(radius = 36f))
balloon.setOverlayShape(BalloonOverlayRoundRect(12f, 12f))
OVAL CIRCLE RECT ROUNDRECT

Also, we can set the specific position of the overlay shape with the method below:

balloon.setOverlayPosition(Point(x, y)) // sets a specific position of the overlay shape.

BalloonAnimation

We can implement popup animations while showing and dismissing.

BalloonAnimation.NONE
BalloonAnimation.FADE
BalloonAnimation.OVERSHOOT
BalloonAnimation.ELASTIC
BalloonAnimation.CIRCULAR
FADE OVERSHOOT ELASTIC CIRCULAR

BalloonHighlightAnimation

We can give a repeated dynamic animations to the Balloon while it's showing up. The animation would work differently by the position of the arrow.

HEARTBEAT SHAKE BREATH ROTATE
BalloonHighlightAnimation.NONE
BalloonHighlightAnimation.HEARTBEAT
BalloonHighlightAnimation.SHAKE
BalloonHighlightAnimation.BREATH
BalloonHighlightAnimation.ROTATE

.setBalloonHighlightAnimation(BalloonHighlightAnimation.SHAKE)

We can implement the rotate animation like the example below:

.setBalloonHighlightAnimation(BalloonHighlightAnimation.ROTATE)
.setBalloonRotationAnimation(
        BalloonRotateAnimation.Builder().setLoops(2).setSpeeds(2500).setTurns(INFINITE).build())

Balloon builder methods

For more details, you can check out the documentations below:

Balloon in Jetpack Compose

Balloon allows you to display tooltips in Jetpack Compose easily.

Maven Central

Add the dependency below to your module's build.gradle file:

dependencies {
    implementation("com.github.skydoves:balloon-compose:$version")
}

Balloon Composable

You can create and display tooltips using the Balloon composable function along with the rememberBalloonBuilder, as demonstrated in the following example:

// create and remember a builder of Balloon.
val builder = rememberBalloonBuilder {
  setArrowSize(10)
  setArrowPosition(0.5f)
  setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
  setWidth(BalloonSizeSpec.WRAP)
  setHeight(BalloonSizeSpec.WRAP)
  setPadding(12)
  setMarginHorizontal(12)
  setCornerRadius(8f)
  setBackgroundColorResource(R.color.skyBlue)
  setBalloonAnimation(BalloonAnimation.ELASTIC)
}

Balloon(
  modifier = Modifier.align(Alignment.Center),
  builder = builder,
  balloonContent = {
    Text(text = "Now you can edit your profile!")
  }
) { balloonWindow ->
    Button(
      modifier = Modifier.size(120.dp, 75.dp),
      onClick = {
        balloonWindow.showAlignTop() // display your balloon.
     }
    ) {
      Text(text = "showAlignTop")
    }
}

BalloonWindow

BalloonWindow is an interface defining all executable behaviors for a balloon's window, including showing, dismissing, updating, and setting up listeners. You can obtain an instance of BalloonWindow within the content parameter of the Balloon composable function, as illustrated in the example below:

Balloon(
  ..
) { balloonWindow ->
    Button(
      modifier = Modifier.size(120.dp, 75.dp),
      onClick = {
        balloonWindow.showAtCenter() // display your balloon.
     }
    ) {
      Text(text = "showAtCenter")
    }
}

Balloon(
  builder = builder,
  balloonContent = null
) { balloonWindow ->
  ..
}

You can also acquire the BalloonWindow by utilizing the onBalloonWindowInitialized lambda parameter in the Balloon composable. This parameter will be invoked just once when the BalloonWindow is fully prepared and ready for use:

var balloonWindow: BalloonWindow? by remember { mutableStateOf(null) }

Balloon(
  builder = builder,
  onBalloonWindowInitialized = { balloonWindow = it },
  balloonContent = {
    Text(text = "Now you can edit your profile!")
  },
) {
  Button(
    modifier = Modifier.size(160.dp, 60.dp),
    onClick = { balloonWindow?.showAlignTop() },
  ) {
    Text(text = "showAlignTop")
  }
}

The onBalloonWindowInitialized lambda paramter is useful when you need to hold an instance of the BalloonWindow as a state, and utilize it out of the Balloon composable function.

Auto-Display Balloon on Layout Ready

To automatically show a Balloon when your layout is drawn, a common requirement in numerous applications, you can use the onComposedAnchor parameter within the Balloon composable function.

var balloonWindow: BalloonWindow? by remember { mutableStateOf(null) }

Balloon(
  builder = builder,
  onBalloonWindowInitialized = { balloonWindow = it },
  onComposedAnchor = { balloonWindow?.showAlignTop() },
  balloonContent = {
    Text(text = "Now you can edit your profile!")
  },
) {
  Button(
    modifier = Modifier.size(160.dp, 60.dp),
    onClick = { balloonWindow?.showAlignTop() },
  ) {
    Text(text = "showAlignTop")
  }
}

As you can see in the example above, you can use onComposedAnchor with the onBalloonWindowInitialized lambda to obtain the BalloonWindow and display your balloon sequentially after rendering your composable layout.

Compose Extensions

The balloon-compose package provides useful compose extensions, such as setting a color with androidx.compose.ui.graphics.Color like the below:

val builder = rememberBalloonBuilder {
  setText("Now you can edit your profile!")
  setArrowSize(10)
  setWidthRatio(1.0f)
  setHeight(BalloonSizeSpec.WRAP)
  setArrowOrientation(ArrowOrientation.BOTTOM)
  setArrowPosition(0.5f)
  setPadding(12)
  setMarginHorizontal(12)
  setTextSize(15f)
  setCornerRadius(8f)
  setTextColor(Color.White) // set text color with compose color.
  setBackgroundColor(Color.White) // set background color with compose color.
  setIconDrawableResource(R.drawable.ic_edit)
}

Note: If you want to use the default form of balloon (icon + text), you should pass a null value to the balloonContent parameter of your Balloon composable.

Find this library useful? โค๏ธ

Support it by joining stargazers for this repository. โญ
Also, follow me on GitHub for my next creations! ๐Ÿคฉ

License

Copyright 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.

balloon's People

Contributors

0xflotus avatar aantunovic avatar andrespaez90 avatar davidedwards avatar denis-ismailaj avatar egorikftp avatar guillemroca avatar heckfyxe avatar itsnitish22 avatar jadenkor avatar joepaul avatar jonasskold avatar kiwiandroiddev avatar kwondae avatar linjiansi avatar nkhar avatar renovate[bot] avatar rhtyme avatar rustyhamsterr avatar skydoves avatar subhrajyotisen avatar suman-somu avatar svrlopatrik avatar vagabond95 avatar vitkhudenko avatar yosef-khaled avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

balloon's Issues

Cannot align text properly

I created a balloon with a background image and using text over it. Is there any way to align the text on the background as I am not able to find any workthrough.

setArrowSize not working

I am setting arrow size using factory
Balloon.Builder(context)
.setLayout(R.layout.layout)
.setArrowSize(40)
.setArrowOrientation(ArrowOrientation.TOP)
.setArrowPosition(0.5f)
.setCornerRadius(4f)
.setBackgroundColor(ContextCompat.getColor(context, R.color.white_20))
.setDismissWhenTouchOutside(true)
.setLifecycleOwner(lifecycleOwner)
.build()

Option for changing text alignment.

The text is always centered in the Balloon without any way to change it. I think left-aligned text looks better for large chunks of text, so I'd like an option to set this.

I've tried doing this with a custom layout, but the text always gets cut off after one line (unless I explicitly set the height, which isn't feasible for me).

EDIT: nevermind, I was able to hack around it:

    TextView textView = balloon.getContentView().findViewById(R.id.balloon_text);
    textView.setGravity(Gravity.LEFT);

Material NavigationView stops working when balloon showed

Please complete the following information:

  • Library Version 1.1.2
  • Affected Devices : Alcatel 5033D v8.1.0, Huawei P20 Pro v9.0.0, Samsung A20

Describe Bug: When the balloon is showed for the first time, menu items in Navigation view stops working in meaning, instead of opening desired activities they only close NavigationView. Problem then continues no matter if balloon is showed or not, I have to restart the app to work again.

Expected Behavior: I expect NavigationView to work as before showing balloon.

My code for creating balloon is:

val statusPopup = createBalloon(this) {
            setLayout(R.layout.popup_change_annoyed_status)
            setWidth(311)
            setArrowSize(10)
            setArrowOrientation(ArrowOrientation.TOP)
            setArrowPosition(0.85f)
            setCornerRadius(5f)
            setTextTypeface(R.font.montserrat_medium)
            setBackgroundColorResource(R.color.colorSecondary)
            setBalloonAnimation(BalloonAnimation.OVERSHOOT)
            setLifecycleOwner(lifecycleOwner)
        }

In image clicke event:

if (!statusPopup.isShowing) {
                prepareBalloon(user, statusGoLayout, statusMaybeLayout, statusNoLayout)
                it.showAlignBottom(statusPopup)
            } else {
                dismissBalloon(statusPopup)
            }

dismissBalloon(balloon) function only calls balloon.dismiss()

Setting arrow LEFT messes view for custom layouts

  • Version: 1.1.5
  • Devices: API 29 Emulator and OnePlus5
  • Describe the Bug:
    If I set left arrow for custom layout content the layout is shifted to left and corners are messed up.
    The builder calls I am using
createBalloon(context) {
            setLayout(R.layout.view_sign_up_popup_password_hint)
            setArrowOrientation(ArrowOrientation.LEFT)
            setCornerRadius(4f)
            setBackgroundColorResource(R.color.background_popup_grey)
            setLifecycleOwner(lifecycle)
}

The result is:
login_popup_arrow_left
If I set Arrow to TOP
login_popup_arrow_top

  • How to reproduce: change in Balloon demo ProfileBalloonFactory change from TOP to LEFT and the same behavior is happening.
    balloon_demo_arrow_left

  • Expected behaviors:
    Setting arrow left I would expect the balloon is rendered correctly and not distorted.

Option to have arrow point at (center of) anchor view

Is your feature request related to a problem?

From what I can tell, by default the arrow of the balloon is rendered in the center of the balloon, and the balloon is center aligned with the anchor view when shown. This means that normally, the arrow points at the center of the anchor view. However, if there is not enough space to display the balloon this way (because the balloon reaches the edge of the screen), the balloon is automatically shifted, which also shifts the arrow, causing it to no longer point at the center of the anchor view. While it is possible to change where on the balloon the arrow is displayed by specifying a ratio other than the default 0.5, it is currently not possible to tell the balloon to render the arrow so that it always points at the anchor view. This results in the problem that, if the balloon is too big and the anchor view is small, the arrow does not point at the anchor view at all.

Describe the solution you'd like:

I would love to have an option to, instead of specifying a ratio of where the arrow should be, to specify that the arrow should point at the center of the anchor view (or optionally at a certain offset from the anchor view's center).

Something like

enum class ArrowPositionMode {
    ALIGN_WITH_BALLOON, // this will place the arrow in the center of the balloon, or shifted if setArrowPosition is used
    ALIGN_WITH_ANCHOR // this will place the arrow in the center of the anchor view, or shifted if setArrowPosition is used
}

Balloon.Builder(context)
    .setArrowPositionMode(ArrowPositionMode.ALIGN_WITH_ANCHOR)

Describe alternatives you've considered:

I tried to dynamically compute the arrow ratio when showing the balloon based on where the anchor view is, but for that I'd first have to create the balloon to measure its width, calculate what the arrow position should be, then destroy the balloon again and create a new one with the calculated arrow position (because the arrow position cannot be changed once the balloon is created).

There is no way to set OnBalloonOutsideTouchListener (Java). No dismiss on outside click.

  • Library version 1.0.0
  • All devices
  • Java 1.8

Describe the Bug:
There is an interface called OnBalloonOutsideTouchListener in this library. There is no listener or callback setter function for this to be set in the Balloon class. What is the purpose of this interface?
I am looking for a way to make the popup dismiss when there is a click outside of the popup. Similar to I have found no way enable this in the library.
This would be similar functionality to doing: DialogFragment.getDialog().setCanceledOnTouchOutside(true);

Expected Behavior:
I would expect the Balloon class to have a setOnBalloonOutsideTouchListener(OnBalloonOutsideTouchListener listener) and setOnBalloonOutsideTouchListener(OnBalloonOutsideTouchListener listener) functions to enable the listener to be get and set.
If this feature is not supported, then I would expect this class to be removed.

Height not correct when inflating custom layout

Please complete the following information:

  • Library Version [e.g. v1.1.7]

Describe the Bug:

After inflating a custom layout with several text fields the height is not correctly set.

      val balloon = createBalloon(context) {
            setLayout(R.layout.onboarding_tour_dialog)
      }

      val contentView = balloon.getContentView()
      // set the correct text
   

      balloon.showAlignTop(targetView)
     

image

Expected Behavior:

The height is correctly calculated.

image

Tooltips don't disappear when leaving fragment

Please complete the following information:

  • Library Version 1.1.2
  • Affected Device(s) Emulator

Describe the Bug:

Settings:

setArrowSize(10)
//        setWidthRatio(1.0f)
setHeight(65)
setPadding(0)
setDismissWhenTouchOutside(true)
setPaddingLeft(10)
setPaddingRight(10)
//        setArrowPosition(.5f)
setSpace(10)
setCornerRadius(10f)
setAlpha(1f)
setTextColorResource(R.color.white)
setBackgroundColorResource(R.color.colorAccent)
setOnBalloonClickListener {
    onClick?.invoke()
}
setBalloonAnimation(BalloonAnimation.ELASTIC)
setLifecycleOwner(lifecycleOwner)

When I leave the fragment (e.g. to navigate to a new fragment). The tooltips stay on the screen.

Expected Behavior:

The tooltips disappear when navigating away (backwards or forwards) from fragment.

Balloon crashes, Resources$NotFoundException and InvocationTargetException

  • Library Version: v1.1.7
  • Affected Device(s): Nexus 5X, Sony Xperia Z5

I have a viewPager with 4 pages. It's MVVM architecture and I call balloons from fragments. I created balloons showing playlist/folderlist etc is empty. (I took them in timer to wait 500 msec but it's irrelevant now I think, the problem is the same without timer too).

Automatic dismissing is not working if I'm swiping fast between the 4 pages

balloon_bug2

So I'm swiping from playlist to player page and right after the ballons popup I'm swiping back.

Because of that, I created manual dismissing when the fragment is gone:

override fun setMenuVisibility(menuVisible: Boolean) {
        menuVisibilityPlayer = menuVisible

        if (menuVisibilityPlayer && this::binding.isInitialized) {
            createBalloons()
        }else {
            dismissBalloons()
        }
        super.setMenuVisibility(menuVisible)
    }
    fun dismissBalloons(){
        if (timerBalloon != null){timerBalloon!!.cancel()}
        if (timerBalloon2 != null){timerBalloon2!!.cancel()}

        if (inPlayerEmptyFoldersListBalloonFactory != null) {
            if (inPlayerEmptyFoldersListBalloonFactory!!.isShowing) {
                inPlayerEmptyFoldersListBalloonFactory!!.dismiss()
            }
        }
        if (inPlayerEmptySelectedFoldersListBalloonFactory != null) {
            if (inPlayerEmptySelectedFoldersListBalloonFactory!!.isShowing) {
                inPlayerEmptySelectedFoldersListBalloonFactory!!.dismiss()
            }
        } ...

It's seems it's working but very rarely it crashes (I saw on my phone (Xperia Z5) about 2-3 times until a lot of test, but on emulators don't have problems)
I thougth it was fixed with your 1.1.7 version, because I couldn't reproducate it.
But after I made my release, I got crashes in chrashlytics from a Nexus 5x. It comes from my dismissBalloons method:
image

Thank you for helping!

Balloon crashes on showing, BadTokenException

We are using the newest Balloon version 1.1.5 in our app.

I just saw a crash in crashlytics and cannot reproduce it on my own, but it occurred 9 times until now.

Android-Versions: no specific version

Stacktrace:
Fatal Exception: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:1122)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:450)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:95)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:1621)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1456)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1412)
at com.skydoves.balloon.Balloon$showAlignBottom$$inlined$show$2.run(Balloon.java:970)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8016)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
at com.android.internal.os.Device.fp(Device.java)

Could you at least catch this exception, so it won't crash the app? Thank you very much!

Balloon width no longer shrinks to fit text.

On versions prior to 1.17, if we didn't set a specific width or width ratio, the Balloon's width would match the text contained inside it. As of 1.17, not specifying a width or width ratio sets the Balloon's width to about 90% of the screen.

I'd like it to work like a Toast, where I don't have to specify the width beforehand.

Screenshot_1589730637

`setSpace` seems not to work?

Please complete the following information:

  • Library Version 1.1.2
  • Affected Device(s) Emulator

Describe the Bug:

I want to add some space between the arrow and the view it points too. It seems that I should use setSpace for this. But any value I enter here has no effect. Not sure if this is the correct setting. Note: Using in a RecyclerView

setTextResource(text)
setPaddingLeft(10)
setPaddingRight(10)
setTextColorResource(white)
setArrowSize(10)
setHeight(65)
setDismissWhenTouchOutside(true)
setBackgroundColorResource(colorAccent)
setCornerRadius(15f)
setSpace(100)
setAlpha(1f)
setDismissWhenShowAgain(true)
setOnBalloonClickListener {
    onClick?.invoke()
}
setBalloonAnimation(ELASTIC)
setLifecycleOwner(lifecycleOwner)

Expected Behavior:

I can set the space.

Text/images still cut off on sides

Hi,

I'm sorry, but for me the latest 1.1.7 Version did not solve the problem. I got the latest version from jcenter, where the "private fun getMeasureTextWidth(measuredWidth: Int): Int" has the parameter already (I double checked in the downloaded dependency).
I am still experiencing the image and text being cut off on my Samsung tablet (see my latest comment in issue #42 ).

Thank you

LifecycleOwner and Activity

This is more like a quick question.

To use .setLifecycleOwner(this), i have to use AppCompatActivity, which i don't want to because it causes a ton of issue with themes, so i have to stick to Activity.

My question, is it sufficient to call .dismiss() on onStop, to avoid memory leak?

Support for setting TypeFace type

Currently the setTextTypeface method takes a Int variable. This limits the situations where one wants to use a custom TypeFace object when using a custom font.
Can it be possible to add support for custom TypeFace objects, perhaps a setTextTypeface object which takes TypeFace parameter?

Preference name not working correctly

Please complete the following information:

  • Library Version -> v1.0.7

Preference name not working correctly due to the fact that is being retrieved from sharedPreferences with the following prefix SHOWED_UP, but when checking the actual sharedPreferences value, is actually saved with a double prefix like -> SHOWED_UP_SHOWED_UP<PREF_NAME>.

the arrow does not follow the image

Please complete the following information:

  • Library Version [e.g. v1.1.5]
  • Affected Device(s) [e.g. Samsung Galaxy s10 with Android 9.0]
    all devices
    Describe the Bug:
    When the image for which the tooltip is attached , is moved . the ballon arrow do not follow the image.
    For example: on the toolbar with chrome cast icon and without chrome cast icon , my image moves left to chrome cast icon or towards end of the toolbar. The arrow of the balloon meaning the ballon do not take position with respect to image.
    my settings in the factory are
    setArrowSize(10)
    setArrowPosition(0.83f)
    setArrowVisible(true)
    setWidthRatio(0.90f)
    setCornerRadius(8f)
    setTextForm(textForm)
    setArrowOrientation(ArrowOrientation.TOP)
    setBackgroundColorResource(R.color.accent)
    isRtlSupport(true)

Expected Behavior:
I would expect the ballon should move according to the position of the
clip of TT
clip2

assigned image.
A clear description of what you expected to happen.

balloon height -- limited functionality and documentation

Please complete the following information:

  • Library Version: 1.1.2
  • Affected Device(s) emulator

Describe the Bug:

Apart from setHeight(), there does not seem to be any control over height. The balloon does not seem to properly wrap my content -- whether I use just text or set my own custom layout.

I do not see much documentation concerning height.

Do I need to guess the proper height and then set it using setHeight() anytime I have more than one line of text?

Expected Behavior:

If I do not set height manually, e.g. setHeight(), I am hoping the balloon will wrap the content, setting the correct height for me. Otherwise, even if I calculate and set a correct height for each of my balloons, it will still be wrong whenever the user has a different font display size than what I am expecting, or a different language.

Tooltip not centered

Please complete the following information:

  • Library Version 1.1.2
  • Affected Device(s) Emulator

Describe the Bug:

packageEdit.setOnClickListener {
    packageTitle.showBalloon(this)
}

packageTitle is the label where it should appear centered.
Settings:

setArrowSize(10)
//        setWidthRatio(1.0f)
setHeight(65)
setPadding(0)
setDismissWhenTouchOutside(true)
setPaddingLeft(10)
setPaddingRight(10)
//        setArrowPosition(.5f)
setSpace(10)
setCornerRadius(10f)
setAlpha(1f)
setTextColorResource(R.color.white)
setBackgroundColorResource(R.color.colorAccent)
setOnBalloonClickListener {
    onClick?.invoke()
}
setBalloonAnimation(BalloonAnimation.ELASTIC)
setLifecycleOwner(lifecycleOwner)

Happens when using in RecyclerView. Position seems to be random, on other cells it appears at different non-centered positions. I haven't tested without RecyclerView.

Screen Shot 2020-03-24 at 15 53 33

Expected Behavior:

The tooltip appears centered horizontally over the text label.

Support padding instead of height/width dp

Is your feature request related to a problem?

For a balloon with multiple lines of text, having the balloon container scale with its height would be very useful.

Describe the solution you'd like:

At the moment the layout_balloon.xml file uses dp values instead of "wrap_content". If the layout uses "wrap_content" for height, the builder can drop builder.setHeight() and builder.setWidth(), and instead have something like builder.setPaddingVert() and builder.setPaddingHoriz().

Thoughts?

Not working on API 16

Please complete the following information:

  • Library Version: v1.1.2
  • Affected Device(s): Android Emulator API 16

Describe the Bug:

We are using this library to show a tooltip inside a dialog fragment but with crashs with a NPE when we try to show the balloon:

java.lang.NullPointerException
        at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:465)
        at android.view.View.measure(View.java:15172)
        at com.skydoves.balloon.Balloon$showAlignTop$$inlined$show$1.run(Balloon.kt:267)
        at android.os.Handler.handleCallback(Handler.java:615)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)

Code we use to build the Balloon:

@NonNull
    private Balloon buildBalloon(@NonNull final Context context) {
        final Balloon balloon = new Balloon.Builder(context)
                .setLayout(R.layout.partial_custom_field_tooltip)
                .setArrowSize(10)
                .setArrowOrientation(ArrowOrientation.BOTTOM)
                .setArrowVisible(true)
                .setSpace(20)
                .setPadding(8)
                .setCornerRadius(4f)
                .setTextColor(Color.WHITE)
                .setBackgroundColor(Colors.getColor(R.color.custom_fields_tooltip_background))
                .setBalloonAnimation(BalloonAnimation.FADE)
                .setDismissWhenClicked(true)
                .setOnBalloonOutsideTouchListener(this)
                .build();
        ((TextView) balloon.getContentView().findViewById(R.id.txt_customFieldTooltip))
                .setText("Text");
        return balloon;
    }

Custom layout:

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/txt_customFieldTooltip"
    android:layout_width="300dp"
    android:layout_height="wrap_content"
    android:textColor="@color/white"
    android:gravity="center"
    android:textSize="@dimen/font_normal"
    tools:background="@color/custom_fields_tooltip_background"
    tools:text="@tools:sample/lorem/random" />

And to show:
mBalloon.showAlignTop(view);

We also test on API 26 and it works fine.

App Crash : android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid;

Hi,
we use the Balloon library to show tooltips.
The balloon is shown with a little delay of 500ms. In Firebase Crashlytics I found some crashes while showing the balloon.

It look's like the user press the back button instantly while the balloon is showing.

Fatal Exception: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
       at android.view.ViewRootImpl.setView(ViewRootImpl.java:1056)
       at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:381)
       at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
       at android.widget.PopupWindow.invokePopup(PopupWindow.java:1478)
       at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1316)
       at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1272)
       at com.skydoves.balloon.Balloon$showAlignRight$$inlined$show$1.run(Balloon.kt:853)
       at android.os.Handler.handleCallback(Handler.java:873) 

This is happens also for

  • com.skydoves.balloon.Balloon$showAlignRight$$inlined$show$1.run(Balloon.kt:853)
  • com.skydoves.balloon.Balloon$showAlignTop$$inlined$show$1.run(Balloon.kt:853)
  • com.skydoves.balloon.Balloon$showAlignLeft$$inlined$show$1.run(Balloon.kt:853)

It would be great if you catch this exception

  • Library Version [e.g. v1.1.1]
  • Affected Device(s) : Galaxy Tab A (2018, 10.5) , Galaxy A50 , HTC, U Play , HUAWEI

Regards
Stephan

Corner radius doesn't work when using custom layout without padding

Please complete the following information:

  • Library Version 1.1.2
  • Affected Device(s) Emulator

Screen Shot 2020-03-24 at 15 59 55

setArrowSize(10)
//        setWidthRatio(1.0f)
setHeight(65)
setPadding(0)
//        setDismissWhenTouchOutside(true)
setPaddingLeft(10)
setPaddingRight(10)
//        setArrowPosition(.5f)
setSpace(10)
setCornerRadius(10f)
setAlpha(1f)
setTextColorResource(R.color.white)
setBackgroundColorResource(R.color.colorAccent)
setOnBalloonClickListener {
    onClick?.invoke()
}
setBalloonAnimation(BalloonAnimation.ELASTIC)
setLifecycleOwner(lifecycleOwner)

Arrow position in the center of the view. Wrap content

Is your feature request related to a problem?

  1. I have a button and when I tap I want to display the ballon at the top. I added at the top of the button but I cannot set the arrow at the center of the button. How I can set the arrow at the center/top of the button? Without using arrow position, bc in some cases I do not know where is the position of the center of the button.

  2. What value I have to set to see the ballon with width wrap content ? bc the text is cutting off.

Describe the solution you'd like:

Describe alternatives you've considered:

JDK8 dependency

It seems that with this commit, which is part of version 1.1.7, you added a dependency that makes the library only work with Java 8 and newer. This is a bit problematic, especially for a patch version update, as it breaks the library for older versions of Android which do not support Java 8 language features.

I have not tested it yet, but I assume this can be fixed by following the steps here, but I don't see that mentioned in your library's documentation. If that approach does not work then I will be unable to use this library in my project.

I recommend to either update the documentation, remove the dependency on Java 8 language features, or to change the minSDK version of your library.

.setDismissWhenTouchOutside(false) doesn't work

Hi

I am trying to disable dismiss altogether because i am using it to show delete progress.

.setDismissWhenTouchOutside(false) doesn't seem to work. I am able to still dismiss when touching outside.

Removing .setDismissWhenTouchOutside() has the same effect.

I can still dismiss when touch outside.

Please help

thanks in advance

Cannot start this animator on a detached view

Please complete the following information:

  • Version 1.1.1
  • Samsung s7 and maybe more

Describe the Bug:

Fatal Exception: java.lang.IllegalStateException: Cannot start this animator on a detached view!
       at android.view.RenderNode.addAnimator(RenderNode.java:803)
       at android.view.RenderNodeAnimator.setTarget(RenderNodeAnimator.java:300)
       at android.view.RenderNodeAnimator.setTarget(RenderNodeAnimator.java:282)
       at android.animation.RevealAnimator.<init>(RevealAnimator.java:37)
       at android.view.ViewAnimationUtils.createCircularReveal(ViewAnimationUtils.java:71)
       at com.skydoves.balloon.ViewExtensionKt.circularUnRevealed(ViewExtensionKt.java:58)
       at com.skydoves.balloon.Balloon.dismiss(Balloon.java:485)
       at com.skydoves.balloon.Balloon$dismissWithDelay$1.run(Balloon.java:496)
       at android.os.Handler.handleCallback(Handler.java:789)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6944)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Set Arrow seems to not working

Please complete the following information:

  • Library Version v1.1.2
  • Affected Device(s) (Tablet Samsung) Galaxy TAB A 2016

Describe the Bug:

I'm trying to add my custom arrow to the balloon but it only show the default one.
I tried with both methods

setArrowDrawableResource
setArrowDrawable

 val balloon = Balloon.Builder(this)
                .setLayout(R.layout.popup_qty)
                .setArrowSize(15)
                .setArrowOrientation(ArrowOrientation.TOP)
                .setArrowPosition(0.5f)
                .setCornerRadius(10f)
                .setArrowVisible(true)
                .setArrowDrawable(ContextCompat.getDrawable(this, R.drawable.ic_custom_arrow))
                .setBalloonAnimation(BalloonAnimation.OVERSHOOT)
                .setDismissWhenTouchOutside(true)
                .setLifecycleOwner(this)
                .build()

 balloon.showAlignBottom(view)

Expected Behavior:

Displaying my custom arrow

dismissWhenTouchOutside doesn't change isShowing property

  • Library Version: 1.1.2
  • Affected Device(s) Huawei P20 Pro Android: v9.0.0

Describe the Bug:

When dismissWhenTouchOutside is enabled, when touched outside, balloon closes but isShowing property stays true.

My code is:

val statusPopup = createBalloon(this) {
           setLayout(R.layout.popup_change_annoyed_status)
           setWidth(311)
           setArrowSize(10)
           setArrowOrientation(ArrowOrientation.TOP)
           setArrowPosition(0.85f)
           setCornerRadius(5f)
           setTextTypeface(R.font.montserrat_medium)
           setDismissWhenTouchOutside(true)
           setBackgroundColorResource(R.color.colorSecondary)
           setBalloonAnimation(BalloonAnimation.OVERSHOOT)
           setLifecycleOwner(lifecycleOwner)
        }

Expected Behavior: set isShowing property to false

dynamic text?

how can we set the text dynamically after create the balloon?

Button to open tooltip not interactive after opening/closing

Please complete the following information:

  • Library Version 1.1.2
  • Affected Device(s) Emulator

Describe the Bug:

When using setDismissWhenTouchOutside, after the tooltip has been opened once, it doesn't open again. Sometimes it works. Happens in a RecyclerView (see other issues for screenshots). I don't know if it happens when not in a RecyclerView.

setTextResource(text)
setPaddingLeft(10)
setPaddingRight(10)
setBackgroundColorResource(colorAccent)
setTextColorResource(white)
setCornerRadius(15f)
setArrowSize(10)
//        setWidthRatio(1.0f)
setHeight(65)
//        setPadding(0)
setDismissWhenTouchOutside(true)
//        setArrowPosition(.5f)
setSpace(-10)
setAlpha(1f)
setOnBalloonClickListener {
    onClick?.invoke()
}
setBalloonAnimation(ELASTIC)
setLifecycleOwner(lifecycleOwner)

Expected Behavior:

The tooltip can be opened again.

Support for XML animations

Basically just support for regular .startAnimations, I'd love to have some custom movement on my bubbles. Otherwise really useful <3

Arrow not it the right place on Android 23

  • Library Version 1.1.5
  • Affected Device: Emulator, Nexus S, API 23

Bug:

With the following code the arrow is always miss-placed on the devices with smaller screen, API 23 (please see the screenshot attached). It does not happen for example on the emulator Pixel 3, API 29.

Here is the Kotlin dsl I use:

val balloon = createBalloon(requireContext()) {
            setArrowSize(10)
            setArrowOrientation(ArrowOrientation.TOP)
            setPaddingTop(16)
            setPaddingRight(21)
            setPaddingBottom(16)
            setPaddingLeft(21)
            setCornerRadius(4f)
            setAlpha(0.85f)
            setText("12")
            setTextColorResource(R.color.black)
            setBackgroundColorResource(R.color.white)
            setLifecycleOwner(lifecycleOwner)
        }

It would be really nice if someone could help me with this :(

Emulator, Nexus S, API 23:
Bildschirmfoto 2020-05-07 um 22 22 25

Emulator Pixel 3a, API 29
Bildschirmfoto 2020-05-07 um 22 21 41

Auto dismiss

Hi, thanks for the great feature!

Is there a way to auto dismiss or a way to show it for certain amount of time? I tried .setShowTime() but it doesn't work.

I can put it in a runnable but if there is already a way to do it, I rather not.

Thanks in advance.

Text/images cut off on sides

If the width of the Balloon is close to the width of the content inside it, the content gets cut off on the left and right sides.

I've tried playing with various builder methods to fix this, and nothing does.

Screenshot_1587902594

ClassNotFoundException on App StartUp

  • Library Version [e.g. v1.1.4]
  • Affected Device(s) : Emulator]

Describe the Bug:

AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.appcompat.AppCompatImageView"

I presume this is caused by your dependency on the alpha version of the appcompat lib. Is it possible to use the stable version?

Expected Behavior:
App doesn't crash

Tooltips inside when recycler view cell goes out of viewport

Please complete the following information:

  • Library Version 1.1.2
  • Affected Device(s) Emulator

When I open a tooltip inside a recycler view cell and scroll such that the cell goes outside the view port, the tooltip stays inside (at the edge). This looks weird as it's not pointing to anything anymore.

Is it possible to make it go out of the screen together with the cell (and back in)?

Settings

setArrowSize(10)
//        setWidthRatio(1.0f)
setHeight(65)
setPadding(0)
//        setDismissWhenTouchOutside(true)
setPaddingLeft(10)
setPaddingRight(10)
//        setArrowPosition(.5f)
setSpace(10)
setCornerRadius(10f)
setAlpha(1f)
setTextColorResource(R.color.white)
setBackgroundColorResource(R.color.colorAccent)
setOnBalloonClickListener {
    onClick?.invoke()
}
setBalloonAnimation(BalloonAnimation.ELASTIC)
setLifecycleOwner(lifecycleOwner)

Note that setDismissWhenTouchOutside is commented. I don't want the tooltips to disappear immediately.

Screen Shot 2020-03-24 at 16 05 16

The tooltip showing in the screenshot belongs to an item that's outside (top) of the screen.

Stoke color to Balloon and Arrow

Hi , and thanks for thiis useful library,
I try to create a simple balloon with white background , arrow, and black stroke color.
Is it possible to have a stroke outline to balloon?
Alternatively, is it possible to create a shadow to simulate a stroke?

thanks in advance

Usage inside recyclerview item

Is your feature request related to a problem?

Hi, I've been struggling with the problem of using your library inside recyclerview item. For example I would like to display tooltip after click on circle avatar image at your sample project. It's popups balloon at different items or sometimes just nothing happens after a click event. My implementation is very simple I've used showAlignBottom method inside viewholder.

Describe the solution you'd like:

Could you provide some simple solution how to use you library with recyclerview?

Thanks!

Shadow not displaying. SetElevation not working

Please complete the following information:

  • Library-Version [v1.1.4]
  • Affected Device(s) [Android Emulator Pixel 3a with Android 9.0 API 28 - Google Play]
  • Min API [21]

Describe the Bug:

I tried the parameter setElevation in order to display the shadow as recently you released this feature in version 1.1.3 and I couldn't manage to get it to work.

I've tested in my own app and in the sample of the repo and I couldn't manage to get it to work, I've edited all the Factories without success:

Sample code

class TagBalloonFactory : Balloon.Factory() {

  override fun create(context: Context, lifecycle: LifecycleOwner?): Balloon {
    return createBalloon(context) {
      setLayout(R.layout.layout_custom_tag)
      setArrowSize(10)
      setArrowOrientation(ArrowOrientation.BOTTOM)
      setArrowPosition(0.5f)
      setElevation(10f)
      setPadding(4)
      isRtlSupport(BalloonUtils.isRtlLayout())
      setCornerRadius(4f)
      setBalloonAnimationStyle(R.style.ElasticAndFadeOut)
      setBackgroundColorResource(R.color.white_93)
      setAutoDismissDuration(2000L)
      setDismissWhenClicked(true)
      setDismissWhenShowAgain(true)
      setLifecycleOwner(lifecycle)
    }
  }
}

Also shouldn't the elevation be set as the padding or the width/height which is an Int and not a Float for consistency API reasons? The elevation should also be applied in dp.

Expected Behavior:

The elevation should behave as normal and be displayed in the UI.

PS: Thanks for the awesome library! Keep up the good work! ๐Ÿ’ช

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.