fornewid / naver-map-compose

NAVER Map Android SDK for Jetpack Compose 🗺
https://fornewid.github.io/naver-map-compose/
Apache License 2.0
115 stars 7 forks source link

cameraPositionState.isMoving가 계속 true인 현상 #52

Closed fivelayer closed 2 months ago

fivelayer commented 1 year ago

안녕하세요.

Naver Map을 Bottom sheet와 사용하기 위해서 샘플 프로젝트의 첫번째 화면인 MapScreen을 아래와 같이 수정하였습니다. 바텀시트의 높이에 따라서 Map의 높이를 조절하기 위해 아래와 같은 코드를 구현하였는데요, 화면을 띄우고나면 cameraPositionState.isMoving가 false였다가, 곧바로 true로 바뀐 채로 유지됩니다.

테스트 결과 bottomSheetState를 Collapsed 상태로 변경하면 나타나는 현상을 보입니다. Map의 사이즈가 변경되면서 카메라 위치는 바뀌기 때문에 OnCameraChangeListener는 호출되지만, isMoving을 false로 바꿔주는 OnCameraIdleListener는 호출되지 않아서 생기지 않는 문제가 아닌가 싶네요.

이슈 제보합니다.

@Composable
fun MapScreen(upPress: () -> Unit) {

    val scaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = rememberBottomSheetState(
            initialValue = BottomSheetValue.Collapsed
        ),
    )

    LaunchedEffect(true) {
        delay(1000)
        scaffoldState.bottomSheetState.expand() // 이 함수가 호출된 후 isMoving은 true로 바뀐채 유지된다.
    }

    val cameraPositionState: CameraPositionState = rememberCameraPositionState {
        position = CameraPosition.INVALID
    }

    LaunchedEffect(
        cameraPositionState.isMoving,
    ) {
        println("${cameraPositionState.isMoving}") // false -> true 로 변경되어 true 상태가 유지됨
    }

    BottomSheetScaffold(
        modifier = Modifier.fillMaxSize(),
        topBar = {
            DefaultTopAppBar(
                text = stringResource(R.string.name_map),
                upPress = upPress
            )
        },
        scaffoldState = scaffoldState,
        sheetContent = {
            Box(modifier = Modifier.height(300.dp).fillMaxWidth().background(Color.Gray))
        }
    ) { contentPadding ->
        val offset by scaffoldState.bottomSheetState.offset
        Box(
            modifier = Modifier
                .height(offset.toDp() + 15.dp) // 이 부분을 지우면 cameraPositionState.isMoving은 최초 false로 한번만 뜨지만, 지우지 않으면 false 직후 바로 true로 바뀌고, 다시 false로 바뀌지 않는다.
                .fillMaxWidth()
                .padding(contentPadding),
        ) {
            NaverMap(
                modifier = Modifier.fillMaxSize(),
                cameraPositionState = cameraPositionState,
                contentPadding = contentPadding
            )
        }
    }
}

@Composable
fun Float.toDp(): Dp {
    return (this / LocalDensity.current.density).dp
}
fornewid commented 1 year ago

이슈 등록 감사합니다. :)

적어주신 내용을 보니, 제스처로 Bottom Sheet를 움직일 때 동적으로 높이를 변경하는 것으로 보이는데요. 이러면 recomposition이 자주 발생될 수 있어서 권장되는 형태는 아닌 것 같습니다. 높이를 변경하기보다는, contentPadding을 변경하는 것을 권장드리고 싶구요.

제보해주신 isMoving 이슈는 확인해보겠습니다.

fivelayer commented 1 year ago

@fornewid 답변 감사합니다~ 혹시 NaverMap의 contentPadding을 말씀하시는걸까요? contentPadding을 조절하면 지도는 그대로 표현되고 위치랑 버튼들의 위치만 바뀌어서요..;;

fornewid commented 1 year ago

@fivelayer

혹시 NaverMap의 contentPadding을 말씀하시는걸까요?

네, 맞습니다.

contentPadding을 조절하면 지도는 그대로 표현되고 위치랑 버튼들의 위치만 바뀌어서요..;;

contentPadding을 조절하는 동시에, 카메라 이동도 함께 구현해주시면 될 것 같아요.

이해가 되도록 네이버지도 앱을 예시로 올려봅니다. BottomSheet의 노출위치에 따라, contentPadding을 조정하고 bounds에 맞춰서 지도의 카메라를 이동해줍니다.

https://user-images.githubusercontent.com/3405740/216606463-2947357a-4aef-4130-81c2-4dc797ec350b.mp4

카메라 이동 API는 아래 코드를 참고해보시면 될 것 같아요.

https://github.com/fornewid/naver-map-compose/blob/62cc93a3a15b5e40bd0bbe076acb5391f652abc3/app/src/main/java/com/naver/maps/map/compose/demo/camera/FitBoundsScreen.kt#L85-L92

fivelayer commented 1 year ago

아하.. 감사합니다! 그럼 padding을 주었을 때, camera의 중앙 positoin은 padding된걸 고려한 위경도가 반환되는건가요? 그것도 코드 수정이 필요할까요?

fornewid commented 1 year ago

@fivelayer 어떤 시나리오를 구현하시는 것인지 모르니, 저는 잘 이해가 되지 않는데요.

특정한 위치에 Marker 같은 Symbol이 선택된 상태에서 Bottom Sheet가 나오는 형태가 아닌가요? 그러면 선택한 위치로 카메라 이동을 해주시면 될 것 같습니다.

fivelayer commented 1 year ago

@fivelayer 아 제가 잠시 헷갈리고 있었네요..ㅎㅎ 친절한 답변 갑사합니다 🙇‍♂️