mapbox / mapbox-maps-android

Interactive, thoroughly customizable maps in native Android powered by vector tiles and OpenGL.
https://www.mapbox.com/mobile-maps-sdk
Other
478 stars 134 forks source link

Map bounds are wrong while toggling the keyboard #2398

Open dryaz opened 5 months ago

dryaz commented 5 months ago

Environment

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 commented 5 months ago

Found more context:

We put map inside container which has imePadding()

Column(
        modifier = Modifier
            .fillMaxSize()
            .imePadding()
rnalbandyan commented 2 months ago

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()
)
commonsguy commented 2 months ago

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 commented 1 month ago

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 })
            }
        }
    }
}
flasher297 commented 1 month ago

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

commonsguy commented 1 month ago

This is reproducible on:

It is not reproducible on:

So, perhaps it is an Android 14 issue.

One workaround is to switch to TextureView instead of SurfaceView.

flasher297 commented 1 month ago

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.