mapbox-maps-android icon indicating copy to clipboard operation
mapbox-maps-android copied to clipboard

Map bounds are wrong while toggling the keyboard

Open dryaz opened this issue 1 year ago • 7 comments

Environment

  • Android OS version: Android 14
  • Devices affected: google pixel 6a
  • Maps SDK Version: 11.4.0 (compose)

Observed behavior and steps to reproduce

If you go from screen with opened keyboard back to the map screen the map won't be drawn on part of the screen below keyboard.

https://github.com/mapbox/mapbox-maps-android/assets/1395176/e708ad81-de84-4a35-b819-0eb7dc9e6f88

If you first close keyboard and then go back to the map screen - all good.

https://github.com/mapbox/mapbox-maps-android/assets/1395176/a4481428-2417-486e-b1e4-45266fc2c915

Expected behavior

Map successfully defines it bounds in case of composing the same time keyboard toggling.

Notes / preliminary analysis

Other several devices + emulator yet works OK. Current mode is android:windowSoftInputMode="adjustResize"

dryaz avatar Jun 06 '24 12:06 dryaz

Found more context:

We put map inside container which has imePadding()

Column(
        modifier = Modifier
            .fillMaxSize()
            .imePadding()

dryaz avatar Jun 06 '24 14:06 dryaz

We are also facing similar issue, when navigating back to the map screen. The mapViewportState.cameraState is kept and has the same value, but when trying to get the bounds it returns wrong values. We are using the MapEffect to get the bounds.

val bounds = map.coordinateBoundsForCamera(
    cameraState.toCameraOptions()
)

rnalbandyan avatar Sep 06 '24 14:09 rnalbandyan

A probably related problem: if you resize the MapboxMap() to a larger size, it will not draw tiles in the newly-available space. The underlying map expands to fill the space (I see the Mapbox logo and the scale bar move to be in the new space), but whatever trigger there is for the tiles is not working.

commonsguy avatar Sep 23 '24 16:09 commonsguy

This sample project illustrates the problem. The code is trivial:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        MapboxOptions.accessToken = getString(R.string.mapbox_access_token)

        setContent {
            Column(modifier = Modifier.fillMaxSize()) {
                var boxHeight by remember { mutableStateOf(400.dp) }

                MapboxMap(
                    modifier = Modifier.weight(1.0f),
                    scaleBar = { ScaleBar(alignment = Alignment.BottomEnd) }
                )

                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(boxHeight)
                        .clickable { boxHeight /= 2 })
            }
        }
    }
}

Tap the Box(), and the map expands without drawing tiles in the new space. However, the logo and scale bar render in the new space, so MapboxMap() itself knows about its new size.

https://github.com/user-attachments/assets/9875fcaa-d9a5-4630-bd40-7817d7dc6e11

However, I discovered that removing the Box() (by conditionally rendering it) instead of changing its height worked — the map retiled appropriately:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        MapboxOptions.accessToken = getString(R.string.mapbox_access_token)

        setContent {
            Column(modifier = Modifier.fillMaxSize()) {
                var showBox by remember { mutableStateOf(true) }

                MapboxMap(
                    modifier = Modifier.weight(1.0f),
                    scaleBar = { ScaleBar(alignment = Alignment.BottomEnd) }
                )

                if (showBox)
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(400.dp)
                            .clickable { showBox = false })
            }
        }
    }
}

commonsguy avatar Sep 30 '24 20:09 commonsguy

@commonsguy thank you for the example and sample project. Could you please elaborate on what device/emulator with what Android version you are facing this issue? I see that @dryaz has the issue on Android 14 google pixel 6a. I tried your sample app on a couple of emulators and one real device and can't reproduce the problem.

flasher297 avatar Oct 07 '24 12:10 flasher297

This is reproducible on:

  • Pixel 6 running Android 14
  • Pixel 8a running Android 14

It is not reproducible on:

  • Pixel 4 running Android 13
  • Samsung Galaxy S10e running Android 12
  • Samsung Galaxy A50 running Android 11 (required modifying build.gradle.kts to have minSdk be 30)

So, perhaps it is an Android 14 issue.

One workaround is to switch to TextureView instead of SurfaceView.

commonsguy avatar Oct 07 '24 13:10 commonsguy

Thank you for the update on the devices' description. Seems it is not a pure Android 14 issue but a hardware problem too, because I can't reproduce it on Pixel 6 emulator running Android 14. Anyway, I've raised an internal ticket to investigate the issue and will come back as soon as we have an update.

flasher297 avatar Oct 07 '24 14:10 flasher297

hey @commonsguy thanks for the reproduction app, I'm able to reproduce, and you are correct about using TextureView instead of SurfaceView will fix the issue:

MapboxMap(
    modifier = Modifier.weight(1.0f),
    composeMapInitOptions = with(LocalDensity.current) {
        remember {
            ComposeMapInitOptions(density, textureView = true)
        }
    },
    scaleBar = { ScaleBar(alignment = Alignment.BottomEnd) }
)

As the TextureView draws image buffers via the GPU and is more responsive to layout changes, in your use cases where the map size will change dynamically, it's recommended to use TextureView instead of the default SurfaceView to have a snappier experience.

pengdev avatar Mar 12 '25 18:03 pengdev

Going to close this issue and feel free to reopen if the above solution doesn't work for you

pengdev avatar Mar 18 '25 12:03 pengdev