https://github.com/fornewid/naver-map-compose/tree/main
초기 설정은 위 링크에서 확인하시면 됩니다!
Composable 함수 내에서 NaverMap()을 선언하여 쉽게 Naver Map을 적용할 수 있습니다.
NaverMap()
1. 위치 정보 가져오기
위 방식은 구글에서 제공하는 fusedLocationProfierClient를 이용하는 방식입니다.
이 방식 말고도 NaverMap을 통해 위치 정보를 쉽게 받아올 수 있습니다.
NaverMap의 locationSource에 rememeberFusedLocationSource()
를 넣어주고
onLocationChange 콜백 함수를 통해 내 위치를 나타내는 Location 객체를 얻을 수 있습니다.
rememeberFusedLocationSource()
는 네이버 맵에서 제공하는 LocationSource 객체를 얻어올 수 있는데, 아래 코드를 참고하시면 됩니다.
LocationSource의 activate 함수를 통해서, onLocationChange() 콜백 함수를 받아올 수도 있습니다.
위처럼 사용하시면 안됩니다!
결론부터 말하면, NaverMap의 onLocationChange 디폴트 인자가 LocationSource의 onLocationChange에 적용되기 때문입니다.
처음에 위처럼 적용했다가 동작하지 않아서 내부 코드를 보며 원인을 파악해보았는데 궁금하신 분은 아래 코드를 참고해주시면 됩니다. 상관 없는 코드는 생략했습니다.
@ExperimentalNaverMapApi
@Composable
public fun NaverMap(
modifier: Modifier = Modifier,
...(생략)
**locationSource: LocationSource? = null,**
**onLocationChange: (Location) -> Unit = {} // default 인자**
) {
// rememberUpdatedState and friends are used here to make these values observable to
// the subcomposition without providing a new content function each recomposition
val **mapClickListeners** = remember { MapClickListeners() }.also {
it.onMapClick = onMapClick
it.onMapLongClick = onMapLongClick
it.onMapDoubleTab = onMapDoubleTab
it.onMapTwoFingerTap = onMapTwoFingerTap
it.onMapLoaded = onMapLoaded
**it.onLocationChange = onLocationChange // mapClickListener에 적용됨**
it.onOptionChange = onOptionChange
it.onSymbolClick = onSymbolClick
it.onIndoorSelectionChange = onIndoorSelectionChange
}
val currentLocationSource by rememberUpdatedState(locationSource)
...(생략)
LaunchedEffect(Unit) {
disposingComposition {
mapView.newComposition(parentComposition) {
// MapUpdater에 clickListener와 locationSource 적용
**MapUpdater**(
cameraPositionState = currentCameraPositionState,
**clickListeners = mapClickListeners**,
contentPadding = currentContentPadding,
**locationSource = currentLocationSource**,
locale = currentLocale,
mapProperties = currentMapProperties,
mapUiSettings = currentUiSettings,
)
CompositionLocalProvider(
LocalCameraPositionState provides cameraPositionState,
) {
currentContent?.invoke()
}
}
}
}
}
@Suppress("NOTHING_TO_INLINE")
@Composable
internal inline fun MapUpdater(
...(생략)
clickListeners: MapClickListeners,
locationSource: LocationSource?,
) {
val map = (currentComposer.applier as MapApplier).map
val density = LocalDensity.current
val layoutDirection = LocalLayoutDirection.current
ComposeNode<MapPropertiesNode, MapApplier>(
factory = {
**MapPropertiesNode**(
map = map,
cameraPositionState = cameraPositionState,
**clickListeners = clickListeners**,
density = density,
layoutDirection = layoutDirection,
)
}
) {
..(생략)
**set(locationSource) { map.locationSource = it }
update(clickListeners) { this.clickListeners = it } // clickListeners가 변경됨**
}
}
internal class MapPropertiesNode(
val map: NaverMap,
cameraPositionState: CameraPositionState,
var clickListeners: MapClickListeners,
var density: Density,
var layoutDirection: LayoutDirection,
) : MapNode {
override fun onAttached() {
(..생략)
**map.addOnLocationChangeListener(locationChangeListener)**
}
..(생략)
}
2. 카메라 이동하기
NaverMap의 카메라 시점을 이동하고 싶다면 CameraPositionState를 사용하면 됩니다.
NaverMap은 초기 로딩 시에 내 위치로 카메라를 전환하는 게 생각보다 느립니다.
그렇기 때문에 FusedLocationProviderClient를 통해 내 위치를 미리 저장해두고 NaverMap에서 내 위치로 바로 이동할 수 있도록 로직을 구현해두었습니다.
NaverMap에 커스텀한 cameraPositionState 객체를 넣어주시면 됩니다.
'Android' 카테고리의 다른 글
Compose에서 Naver Map 적용하기 - 2) PolyLine으로 내 경로 그리기 (0) | 2024.02.25 |
---|---|
편하게 사용하고자 만든 Extensions (0) | 2023.10.04 |
안드로이드 서비스(Service) 알아보기 (0) | 2023.06.19 |
Paging, 안드로이드에 맞는 커서 페이징 방식으로 구현하기 (0) | 2023.06.06 |
CoroutineDispatcher.Main.immediate 알아보기 (0) | 2023.05.31 |