[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When used in a LazyColumn, GoogleMap cannot be scrolled vertically #14

Open
JRR-OSU opened this issue Feb 7, 2022 · 17 comments
Open

When used in a LazyColumn, GoogleMap cannot be scrolled vertically #14

JRR-OSU opened this issue Feb 7, 2022 · 17 comments
Assignees
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. type: docs Improvement to the documentation for an API. type: question Request for information or clarification. Not an issue.

Comments

@JRR-OSU
Copy link
JRR-OSU commented Feb 7, 2022

Thanks for your work on this one, it's really great to finally have an official Compose wrapper for Google Maps!

In our use case, we have a custom GoogleMaps wrapper using AndroidView that sits inside a LazyColumn. It is able to be scrolled vertically and horizontally without scrolling the LazyColumn by using a transparent view and calling .requestDisallowInterceptTouchEvent(true) on the parent.

We are hoping to switch to this, but we noticed it still suffers from the original issue we had to work around. Is usage in a LazyColumn a supported use case and is there a more Compose-friendly way to get nested scrolling working properly with this wrapper?

Thanks!

Steps to reproduce

  1. Include GoogleMap in a LazyColumn
  2. Vertically drag on the map to attempt to scroll it
  3. Observe the LazyColumn scrolls instead of the map

Thanks!

@JRR-OSU JRR-OSU added triage me I really want to be triaged. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Feb 7, 2022
@jpoehnelt
Copy link
Contributor

@JRR-OSU Thank you for opening this issue. 🙏
Please check out these other resources that might be applicable:

This is an automated message, feel free to ignore.

@arriolac
Copy link
Member
arriolac commented Feb 8, 2022

I have not yet been able to test this scenario. Perhaps a boolean property should be exposed in the GoogleMap composable to support the case when the map is nested in a scrollable parent as implementing the default GoogleMap using the solution you had mentioned may have unintended consequences in other use cases. Feel free to chime in with other ideas as well.

@arriolac arriolac added priority: p2 Moderately-important priority. Fix may not be included in next release. and removed triage me I really want to be triaged. labels Feb 8, 2022
@sandorbogyo
Copy link

I successfully solved it with cameraPositionState:
Column (
.verticalScroll(rememberScrollState(), enabled = !cameraPositionState.isMoving)
)

@arriolac arriolac added type: question Request for information or clarification. Not an issue. and removed type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Mar 7, 2022
@arriolac
Copy link
Member
arriolac commented Mar 7, 2022

Thanks @sandorbogyo. Just confirmed that that solution works.

@arriolac arriolac closed this as completed Mar 7, 2022
@LouisCAD
Copy link
LouisCAD commented Mar 7, 2022

I think it'd be nice to have that solution in the documentation, what do you think?

@arriolac
Copy link
Member
arriolac commented Mar 7, 2022

@LouisCAD good idea. Would be good to have under a "Common Patterns" section. I'd be happy to add but feel free to send a pull request as well.

@LouisCAD
Copy link
LouisCAD commented Mar 7, 2022

If you have the time, it's best that you do it, I'm quite busy working with OSS projects and starting a company.

@basurahan
Copy link
basurahan commented Apr 9, 2022

This solution does not work as mentioned here link

Please re open this issue and make sure to test it for yourself before accepting a solution

@bubenheimer
Copy link
Contributor

I'd like to request for this issue to be reopened, as it has not been adequately addressed. There is a documented workaround available now thanks to @barbeau, but that's all it is, a workaround, and it's fairly messy. It's also unclear what parts of the elaborate sample code are needed to actually make it work and what can be left out. (I figured it out via my own minimal sample project.)

A Compose component that is draggable by nature should expose draggable behavior out of the box even in the context of nested scrolling, without additional configuration needed.

A custom wrapper using requestDisallowInterceptTouchEvent()as described in the OP may be a good approach, and as @arriolac suggested it can be controlled by a flag for the time being to gather feedback. This is the approach that I've used for years, but maps-compose has taken it away for now.

Another, preferable, avenue that should be fully explored is the standard Compose nested scrolling support that has been worked on here: https://issuetracker.google.com/issues/174348612. The work is ongoing and I have pointed out its current inapplicability to MapView, so this would be the time to connect with the people behind it and see if it can be done.

@barbeau barbeau reopened this Jun 10, 2022
@JRR-OSU
Copy link
Author
JRR-OSU commented Oct 7, 2022

Sorry for the very late reply here, I've finally had some time to circle back to this library.

In #78 a solution was added to allow for scrolling working inside a normal Column. The solution doesn't work for LazyColumn, but I've found it can easily be adapted to work. Just swap out the MapInColumn with the code below in the test app to see it in action. Seems to work well!

If others can verify this works for them, I'd like to see the docs just updated to show something like this as an example, and then we can again close this issue. Thanks all!

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun MapInLazyColumn(modifier: Modifier = Modifier,
                        cameraPositionState: CameraPositionState,
                        columnScrollingEnabled: Boolean,
                        onMapTouched: () -> Unit,
                        onMapLoaded: () -> Unit,) {
    var isMapLoaded by remember { mutableStateOf(false) }
    LazyColumn(modifier, userScrollEnabled = columnScrollingEnabled) {
        item {
            Box(
                Modifier
                    .fillMaxWidth()
                    .height(200.dp)
            ) {
                GoogleMapViewInColumn(
                    modifier = Modifier
                        .fillMaxSize()
                        .testTag("Map")
                        .pointerInteropFilter(
                            
                                when (it.action) {
                                    MotionEvent.ACTION_DOWN -> {
                                        onMapTouched()
                                        false
                                    }
                                    else -> {
                                        Log.d(
                                            TAG,
                                            "MotionEvent ${it.action} - this never triggers."
                                        )
                                        true
                                    }
                                }
                            }
                        ),
                    cameraPositionState = cameraPositionState,
                    
                        isMapLoaded = true
                        onMapLoaded()
                    },
                )
                if (!isMapLoaded) {
                    AnimatedVisibility(
                        modifier = Modifier
                            .fillMaxSize(),
                        visible = !isMapLoaded,
                        enter = EnterTransition.None,
                        exit = fadeOut()
                    ) {
                        CircularProgressIndicator(
                            modifier = Modifier
                                .background(MaterialTheme.colors.background)
                                .wrapContentSize()
                        )
                    }
                }
            }
        }

        items(100) { item ->
            Text("$item", modifier = Modifier
                .padding(start = 10.dp, bottom = 10.dp)
                .testTag("Item $item"))
        }
    }
}

@ptornhult
Copy link

Sorry for the very late reply here, I've finally had some time to circle back to this library.

In #78 a solution was added to allow for scrolling working inside a normal Column. The solution doesn't work for LazyColumn, but I've found it can easily be adapted to work. Just swap out the MapInColumn with the code below in the test app to see it in action. Seems to work well!

If others can verify this works for them, I'd like to see the docs just updated to show something like this as an example, and then we can again close this issue. Thanks all!

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun MapInLazyColumn(modifier: Modifier = Modifier,
                        cameraPositionState: CameraPositionState,
                        columnScrollingEnabled: Boolean,
                        onMapTouched: () -> Unit,
                        onMapLoaded: () -> Unit,) {
    var isMapLoaded by remember { mutableStateOf(false) }
    LazyColumn(modifier, userScrollEnabled = columnScrollingEnabled) {
        item {
            Box(
                Modifier
                    .fillMaxWidth()
                    .height(200.dp)
            ) {
                GoogleMapViewInColumn(
                    modifier = Modifier
                        .fillMaxSize()
                        .testTag("Map")
                        .pointerInteropFilter(
                            
                                when (it.action) {
                                    MotionEvent.ACTION_DOWN -> {
                                        onMapTouched()
                                        false
                                    }
                                    else -> {
                                        Log.d(
                                            TAG,
                                            "MotionEvent ${it.action} - this never triggers."
                                        )
                                        true
                                    }
                                }
                            }
                        ),
                    cameraPositionState = cameraPositionState,
                    
                        isMapLoaded = true
                        onMapLoaded()
                    },
                )
                if (!isMapLoaded) {
                    AnimatedVisibility(
                        modifier = Modifier
                            .fillMaxSize(),
                        visible = !isMapLoaded,
                        enter = EnterTransition.None,
                        exit = fadeOut()
                    ) {
                        CircularProgressIndicator(
                            modifier = Modifier
                                .background(MaterialTheme.colors.background)
                                .wrapContentSize()
                        )
                    }
                }
            }
        }

        items(100) { item ->
            Text("$item", modifier = Modifier
                .padding(start = 10.dp, bottom = 10.dp)
                .testTag("Item $item"))
        }
    }
}

I wasn't able to get it working exactly like this, but the experimental motionEventSpy worked like a charm:

var columnScrollingEnabled: Boolean by remember { mutableStateOf(true) }

...

LazyColumn(userScrollEnabled = columnScrollingEnabled)

...

item {
    GoogleMap(Modifier.motionEventSpy {
        when (it.action) {
            MotionEvent.ACTION_DOWN -> {
                columnScrollingEnabled = false
            }
            MotionEvent.ACTION_UP -> {
                columnScrollingEnabled = true
            }
        }
    },
...

@funyin
Copy link
funyin commented Dec 18, 2022

I successfully solved it with cameraPositionState: Column ( .verticalScroll(rememberScrollState(), enabled = !cameraPositionState.isMoving) )

Didn't work for me

@funyin
Copy link
funyin commented Dec 18, 2022

I wasn't able to get it working exactly like this, but the experimental motionEventSpy worked like a charm:

var columnScrollingEnabled: Boolean by remember { mutableStateOf(true) }

...

LazyColumn(userScrollEnabled = columnScrollingEnabled)

...

item {
    GoogleMap(Modifier.motionEventSpy {
        when (it.action) {
            MotionEvent.ACTION_DOWN -> {
                columnScrollingEnabled = false
            }
            MotionEvent.ACTION_UP -> {
                columnScrollingEnabled = true
            }
        }
    },
...

By @ptornhult , This worked for me

@stale
Copy link
stale bot commented Jun 18, 2023

This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!

@stale stale bot added the stale label Jun 18, 2023
@flaringapp
Copy link
flaringapp commented Aug 4, 2023

the experimental motionEventSpy worked like a charm:

var columnScrollingEnabled: Boolean by remember { mutableStateOf(true) }

...

LazyColumn(userScrollEnabled = columnScrollingEnabled)

...

item {
    GoogleMap(Modifier.motionEventSpy {
        when (it.action) {
            MotionEvent.ACTION_DOWN -> {
                columnScrollingEnabled = false
            }
            MotionEvent.ACTION_UP -> {
                columnScrollingEnabled = true
            }
        }
    },
...

Indeed it works fine.
Tip for those who have a map nested in multiple composable layers, but don't want to pass state parameter through each. Use CompositionLocalProvider to incapsulate logic of accessing/providing current pressed state in a custom class.

@stale stale bot removed stale labels Aug 4, 2023
@wangela
Copy link
Member
wangela commented Aug 11, 2023

TODO: update the docs / sample code to demonstrate this LazyColumn workaround.

@wangela wangela added the type: docs Improvement to the documentation for an API. label Aug 11, 2023
@kikoso kikoso self-assigned this Aug 16, 2023
@meet-m-simformsolutions
Copy link

I don't know if anyone faced this issue but if we use pointerInteropFilter to detect touch events and based on that we enable/disable scrolling, it will solve the scrolling problem but in the case Where we just tap on the map and then try to scroll the column then it won't work because we just tapped the map and as per our logic we are setting columnScrollingEnabled=false in MotionEvent.ACTION_DOWN and it is never going to Change to `true' because we haven't moved the camera but we've just tapped on the map.

Instead we can use the solution mentioned by @funyin. That will solve the issue.

I wasn't able to get it working exactly like this, but the experimental motionEventSpy worked like a charm:

var columnScrollingEnabled: Boolean by remember { mutableStateOf(true) }

...

LazyColumn(userScrollEnabled = columnScrollingEnabled)

...

item {
    GoogleMap(Modifier.motionEventSpy {
        when (it.action) {
            MotionEvent.ACTION_DOWN -> {
                columnScrollingEnabled = false
            }
            MotionEvent.ACTION_UP -> {
                columnScrollingEnabled = true
            }
        }
    },
...

By @ptornhult , This worked for me

I hope this helps everyone. It resolved issue for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. type: docs Improvement to the documentation for an API. type: question Request for information or clarification. Not an issue.
Projects
None yet
Development

No branches or pull requests