본문 바로가기
Android

[Mapbox] Pulsing puck을 이용하여 현재 유저 위치 그리기

by 역삼동개발자D 2024. 1. 23.
반응형

이번 장에는 Mapbox map에서 현재 유저 위치를 Puck을 활용해 표시하고 pulse effect까지 나타내는 작업을 진행하려고 한다.

 

현재 유저 위치를 디바이스로부터 가져오는 부분은 permission 작업과 더불어 FusedLocationProviderClient를 활용하여 진행하였으며 이번장에서는 해당 내용을 생략하려고 한다.

 

Pulse user location

 

먼저 LocationProvider에 대한 정의가 필요한데, 아래와 같이 locationConsumer는 LocationProvider로부터 위치와 방위 업데이트를 받는다. 따라서 디바이스로부터 받은 현재 위치값을 locationConsumer에 전달하고, 이때의 LocationProvider는 mapview에 등록해주면 된다.

interface LocationProvider {
  /**
   * Register the location consumer to the Location Provider.
   *
   * The Location Consumer will get location and bearing updates from the Location Provider.
   *
   * @param locationConsumer
   */
  fun registerLocationConsumer(locationConsumer: LocationConsumer)

  /**
   * Unregister the location consumer from the Location Provider.
   *
   * @param locationConsumer
   */
  fun unRegisterLocationConsumer(locationConsumer: LocationConsumer)
}

 

위의 작업을 위해 LocationProvider를 상속받는 UserLocationProvider를 다음과 같이 작성하였으며 이를 Mapview에 등록하였다.

class UserLocationProvider: LocationProvider {
    private var locationConsumer: LocationConsumer? = null

    override fun registerLocationConsumer(locationConsumer: LocationConsumer) {
        this.locationConsumer = locationConsumer
    }

    override fun unRegisterLocationConsumer(locationConsumer: LocationConsumer) {
        this.locationConsumer = null
    }

    fun onLocationUpdated(latitude: Double, longitude: Double){
        locationConsumer?.onLocationUpdated(Point.fromLngLat(longitude, latitude))
    }
}
MapboxMap(
    ...
) {
    MapEffect(key1 = Unit) {
        it.location.setLocationProvider(mapViewModel.userLocationProvider)
    }
}

 

ViewModel에서는 현재 위치 정보를 flow로 받도록 작업하여 새로운 데이터가 들어왔을때 위치정보를 업데이트할 수 있도록 작성하였다.

val location = getCurrentLocationUseCase().stateIn(
    viewModelScope,
    SharingStarted.WhileSubscribed(),
    Location(
        latitude = 27.941584,
        longitude = -82.450957,
    )
).also {
    viewModelScope.launch {
        it.collectLatest { location ->
            userLocationProvider.onLocationUpdated(location.latitude, location.longitude)
        }
    }
}

 

 

다음은 puck 작업인데, LocationPuck2D를 사용하였고 이때 커스텀된 이미지를 사용하고싶어 아래와 같이 추가하였다. pulse effect을 주기 위해서 pulsingEnabled를 true로 설정하였고, pulsing radius값까지 아래와 같이 설정해주었다.

MapboxMap(
    ...
    locationComponentSettings = LocationComponentSettings(
        LocationPuck2D(topImage = ImageHolder.Companion.from(R.drawable.ic_current_location_pin))
    ) {
        enabled = true
        pulsingEnabled = true
        showAccuracyRing = true
        pulsingMaxRadius = LocationComponentConstants.PULSING_MAX_RADIUS_FOLLOW_ACCURACY
    },
) {
    ...
}

 

반응형