skydoves/Balloon

Compose: Scrolling results in misplaced arrow

alexanderfilipzik opened this issue · 1 comments

Please complete the following information:

  • v1.6.1
  • all?

Describe the Bug:

If i dynamically want to change the orientation of the arrow based upon the position of the anchor view, it only works for the first 2 times.

  1. anchor below middle of screen -> showAlignTop -> WORKS
  2. scroll anchor above middle of the screen -> showAlignBottom -> WORKS
  3. scroll anchor below middle of the screen -> showAlignTop -> NOT WORKING

Expected Behavior:

showAlignTop & showAlignBottom should always work as expected

Screenshots

  1. anchor below middle of screen -> showAlignTop -> WORKS
Bildschirmfoto 2023-10-19 um 10 50 55
  1. scroll anchor above middle of the screen -> showAlignBottom -> WORKS
Bildschirmfoto 2023-10-19 um 10 51 02
  1. scroll anchor below middle of the screen -> showAlignTop -> NOT WORKING
Bildschirmfoto 2023-10-19 um 10 51 08

Example Code

val builder = rememberBalloonBuilder {
        setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
        setArrowPosition(0.5f)
        setMarginHorizontal(12)
      }

      var balloonWindow1: BalloonWindow? by remember { mutableStateOf(null) }
      val screenHeightInDp = LocalConfiguration.current.screenHeightDp
      val screenHeightInPx = with(LocalDensity.current) { screenHeightInDp.dp.toPx() }
      var showBalloonOnTop by remember { mutableStateOf(true) }

      LaunchedEffect(showBalloonOnTop) {
        println("-#- showBalloonOnTop: $showBalloonOnTop")
      }

      Column(
        modifier = Modifier
          .fillMaxWidth()
          .verticalScroll(rememberScrollState()),
        horizontalAlignment = Alignment.CenterHorizontally,
      ) {
        Spacer(modifier = Modifier.height(500.dp))
        Balloon(
          builder = builder,
          balloonContent = {
            Text(
              text = "Now you can edit your profile1 profile2 profile3 profile4",
              color = Color.White,
            )
          },
        ) { balloonWindow ->
          LaunchedEffect(key1 = Unit) {
            balloonWindow1 = balloonWindow
          }

          Button(
            modifier = Modifier
              .onGloballyPositioned {
                // check if the the content is below the middle (y-axis) of the screen or above
                val contentBounds = it.boundsInWindow()
                val contentHeight = contentBounds.height
                val contentY = contentBounds.top
                val contentCenterY = contentY + contentHeight / 2
                val isContentBelowMiddle = contentCenterY > screenHeightInPx / 2
                //println("-#- contentBounds: $contentBounds screenHeightInPx: $screenHeightInPx contentCenterY: $contentCenterY isContentBelowMiddle: $isContentBelowMiddle")
                showBalloonOnTop = isContentBelowMiddle
              }
              .size(48.dp, 48.dp),
            onClick = {
              println("-#- showBalloonOnTop: $showBalloonOnTop")
              if (showBalloonOnTop) {
                balloonWindow.showAlignTop()
              } else {
                balloonWindow.showAlignBottom()
              }
            },
          ) {
            Text(text = "|")
          }
        }
        Spacer(modifier = Modifier.height(500.dp))
      }

Hey @alexanderfilipzik, this issue has been addressed in the recent version 1.6.4. Thank you for reporting this issue and your patience!