[Android/Kotlin] 카카오맵 마커 여러 개 사용하기

코코아의 개발일지·2023년 9월 20일
0

Android-Kotlin

목록 보기
10/31
post-thumbnail

이는 G.IT 와글와글 해커톤 때 있었던 해프닝을 정리한 글입니다.

✍🏻 요구사항 분석

해커톤의 주제는 '학교 생활과 접목하는 IT'였다.
우리팀은 항상 수업만 들으러 다니고, 학교를 잘 걸어다니지 않는 학생들을 위해 매일 3개씩 학교 안에서 할 수 있는 미션을 제공하고, 만보기를 통해 경험치를 쌓을 수 있는, 다마고치 앱을 기획했다. 레벨이 올라갈 때마다 우리 학교의 마스코트를 알에서부터 진화시킬 수 있도록, 캐릭터 디자인까지 했었다.
원래는 만보기 기능으로 지도에 내 위치를 실시간으로 받아와서 표시하고, 걸음수를 기록하는 것이 주요 기능이었다. 하지만 1박 2일의 짧은 기간 내에 구현하기엔 무리일 거 같아 지도에 내 위치를 표시하는 걸로만 바뀌게 되었다.
근데 그렇게 기능을 없애고, 메인 화면에 있는 맵에서 딱 내 위치 하나만 뜨면 화면이 너무 심심할 것 같았고, 서버 파트분께 미션과 함께 위도 경도를 보내줄 수 있냐고 부탁드렸다. 아무래도 프론트에서 보여줄 기능이 좀 있어야 하니까...

서버 분께서 학교 건물들의 위도, 경도를 다 보내주시고 확인했더니 위의 사진처럼 핀이 잘 찍히는 걸 확인할 수 있었다!
그렇다면 코드를 한 번 살펴보자.

💻 코드 작성

** 카카오맵은 불러왔다는 걸 전제로 그 이후부터 설명

1️⃣ 카카오맵 설정

lateinit var mapView: MapView
private lateinit var mapViewContainer : ViewGroup

private var uLatitude : Double = 0.0
private var uLongitude : Double = 0.0
    
override fun onCreate() {
	super.onCreate()
    
    // 위치 권한 허용
    getLocationPermission()
    // 맵뷰 표시
    initMapView()
    // 지도가 현재 위치로 표시
    setCurrentLocaion()
}

private fun initMapView() {
        mapView = MapView(this)
        mapViewContainer = binding.activityMainKakaoMapView
        mapViewContainer.addView(mapView)

        // 줌 레벨 변경
        mapView.setZoomLevel(1, true)
    }

private fun setCurrentLocation() {
        val uNowPosition = MapPoint.mapPointWithGeoCoord(uLatitude, uLongitude)
        mapView.setMapCenterPoint(uNowPosition, true)

        Log.d("Map", "${uLatitude}, ${uLongitude}")
    }
    
private fun getLocationPermission() {
        val permissionCheck = ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION
        )
        if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "위치 권한이 없습니다.", Toast.LENGTH_SHORT).show()
            finish()
            return
        }

        val lm = getSystemService(Context.LOCATION_SERVICE) as LocationManager
        try {
            val userNowLocation : Location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)!!
            uLatitude = userNowLocation.latitude
            uLongitude = userNowLocation.longitude
        } catch (e : NullPointerException) {
            Log.e("LOCATION_ERROR", e.toString())
            ActivityCompat.finishAffinity(this)

            finish()
        }
    }

2️⃣ 현재 위치에 마커 표시

private fun addCustomMarker() {
        // 현재 위치에 마커 추가
        val marker = MapPOIItem()
        marker.apply {
            itemName = "현재 위치"   // 마커 이름
            mapPoint = MapPoint.mapPointWithGeoCoord(uLatitude, uLongitude)   // 좌표
            markerType = MapPOIItem.MarkerType.CustomImage          // 마커 모양 (커스텀)
            customImageResourceId = R.drawable.ic_custom_marker               // 커스텀 마커 이미지
            selectedMarkerType = MapPOIItem.MarkerType.CustomImage  // 클릭 시 마커 모양 (커스텀)
            selectedMarkerType = MapPOIItem.MarkerType.RedPin // 클릭 시 마커 이미지
            isCustomImageAutoscale = false      // 커스텀 마커 이미지 크기 자동 조정
            setCustomImageAnchor(0.5f, 1.0f)    // 마커 이미지 기준점
        }
        mapView.addPOIItem(marker)
    }

현재 위치에는 빨간색 원형 모양의 마커를 달아줬다. customImageResourceId의 R.drawable.ic_custom_marker가 그 내용이다.

3️⃣ 미션 위치 마커 표시 (다중 마커)

* Data Class 작성

data class MissionMapData(
    var missionId: Long,
    var missionName: String? = null, // 미션 이름
    var latitude: Double, // 위도
    var longitude: Double // 경도
)

서버에서 미션이 오는 형태
미션 아이디와 미션명, 그리고 위도와 경도가 같이 온다.

* 미션 위치 마커 표시

private var missionMapData = ArrayList<MissionMapData>()

private fun setMissionMark(dataList: ArrayList<MissionMapData>) {
        for (data in dataList) {
            val marker = MapPOIItem()
            marker.apply {
                itemName = data.missionName
                mapPoint = MapPoint.mapPointWithGeoCoord(data.latitude, data.longitude)
//                markerType = MapPOIItem.MarkerType.BluePin
                selectedMarkerType = MapPOIItem.MarkerType.RedPin
            }
            mapView.addPOIItem(marker)
        }
    }
  • missionMapData에는 서버에서 받아온 response를 넣어주면 된다.
  • markType은 기본이 BluePin이라 주석 처리해두었고,
  • 마커를 선택(클릭)하면 빨간색으로 표시되도록 selectedMarkerType는 Redpin으로 설정해주었다.

🤩 결과 화면

위의 사진을 보면,

  1. 현재 위치는 빨간색 원으로 표시
  2. 미션 핀은 BluePin으로 표시
  3. 선택된 미션 핀은 RedPin으로 표시 + 미션 내용 보여주기

조건을 모두 만족하는 것을 확인할 수 있다!
카카오맵을 직접 써본 것은 처음인데, 학교 내의 여러 장소에 대한 핀을 찍어보니 재밌었다.


📚 참고 자료

profile
우당탕탕 성장하는 개발자

0개의 댓글