Android - Google Map API 설치부터 심화 활용까지 (커스텀 마커) (2) (Kotlin)
업데이트:
- 연구주제 : Android - Google Map 활용 (Kotlin)
- 연구목적 : 안드로이드에서의 코틀린 활용
- 연구일시 : 2020년 04월 07일 09:00~17:00
- 연구자 : 이재환 ljh951103@naver.com
- 연구장비 : HP EliteDesk 800 G4 TWR, Kotlin, Android studio, IntelliJ
- 관련연구 : Java, Android, Kotlin, Google, API
서론
이번 시간에는 커스텀 마커를 이용해서 구글 맵을 활용해 보겠다.
위와 같이, 마커를 여러개 찍고, 일반적인 구글 맵 마커들의 테마를 변경해보자.
https://gun0912.tistory.com/57
포스팅을 기준으로 작성되었으므로 참고해도 좋다.
본론
우선 저번 포스팅의 내용을 따라왔다면 이제는 구글 맵 API를 활용할 수 있게 되었다.
1. 이미지 준비
우선 커스텀 마커를 이용하기 위해 이미지를 받아야한다.
이미지는 나인패치 이미지를 이용해야하는데 위의 링크 블로그에 있는 이미지를 사용해도 좋고 개인 이미지를 사용해도 좋다.
이 이미지는 링크 블로그에 포함된 나인패치 이미지이다.
2. 마커 레이아웃 작성
이미지를 성공적으로 옮겼다면 마커 레이아웃을 작성한다.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/tag_marker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_marker_phone"
android:gravity="center"
android:textSize="16sp" />
</FrameLayout>
3. 마커에 사용할 데이터 클래스 생성
마커에 사용하기 위한 데이터 클래스를 작성한다.
각자 서비스에 맞게 작성하면 된다.
class LatLngData(
val id : Long,
val latlng: LatLng,
val tag: String) {
}
4. 샘플 마커 데이터 생성
샘플로 테스트 하기 위한 데이터를 생성해준다.
그리고 마커를 추가할 수 있게 해준다.
var latlngdata = arrayListOf<LatLngData>()
latlngdata.add(LatLngData(1, LatLng(35.162339, 129.108509), "가"))
latlngdata.add(LatLngData(2, LatLng(35.224836, 129.088285), "나"))
latlngdata.add(LatLngData(3, LatLng(35.080117, 129.048376), "다"))
for (i in latlngdata.indices) {
addMarker(latlngdata[i], false)
}
5. 마커 추가 함수 정의
우선 커스텀 마커를 적용하기위한 xml을 가져온다.
private fun setCustomMarkerView() {
marker_view = LayoutInflater.from(this).inflate(R.layout.marker_layout, null)
tag_marker = marker_view.findViewById(R.id.tag_marker) as TextView
}
그리고 실제 마커를 추가하는 addMarker() 함수를 만들어준다.
private fun addMarker(latlngdata: LatLngData, isSelectedMarker:Boolean): Marker{
var list: List<Address>? = null
var markerOptions = MarkerOptions()
if (isSelectedMarker) {
tag_marker.setBackgroundResource(R.drawable.ic_marker_phone_blue)
tag_marker.setTextColor(Color.WHITE)
} else {
tag_marker.setBackgroundResource(R.drawable.ic_marker_phone)
tag_marker.setTextColor(Color.BLACK)
}
markerOptions.position(latlngdata.latlng)
tag_marker.setText(latlngdata.tag)
markerOptions.icon(
BitmapDescriptorFactory.fromBitmap(createDrawableFromView(this, marker_view
)
)
)
return mMap.addMarker(markerOptions)
}
이제 마커뷰를 비트맵으로 변환해주는 작업이 필요하다.
private fun createDrawableFromView(context: Context, view: View): Bitmap {
val displayMetrics = DisplayMetrics()
(context as Activity).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics)
view.setLayoutParams(
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
)
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels)
view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels)
view.buildDrawingCache()
val bitmap: Bitmap = Bitmap.createBitmap(
view.getMeasuredWidth(),
view.getMeasuredHeight(),
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
view.draw(canvas)
return bitmap
}
5. 마커 클릭 리스너 정의
이제 코드를 돌려보면 마커가 변환되어 지도에 표시되는 것을 확인할 수 있다.
하지만 아직 한 가지 할 일이 더 있다.
마커를 선택했을 때, 카메라 변화와 마커 테마가 변하도록 해야한다.
클릭 리스너에 대한 정의는 다음과 같이 해준다.
즉, 마커가 클릭되면 카메라를 이동시키고 마커 이미지를 변경한다.
mMap.setOnMarkerClickListener(object: GoogleMap.OnMarkerClickListener {
override fun onMarkerClick(marker: Marker): Boolean {
val center: CameraUpdate = CameraUpdateFactory.newLatLng(marker.getPosition())
mMap.animateCamera(center)
changeSelectedMarker(marker)
return true
}
})
마커를 되돌리는 함수를 정의한다.
selectMarker
에 선택된 마커를 저장하여 조건 분기를 통해 마커를 조정한다.
private fun changeSelectedMarker(marker: Marker?) {
// 선택했던 마커 되돌리기
if(selectedMarker != marker) {
if (selectedMarker != null) {
addMarker(selectedMarker!!, false)
selectedMarker!!.remove()
}
// 선택한 마커 표시
if (marker != null) {
addMarker(marker, true)
marker.remove()
}
else
selectedMarker = null
}
}
맵을 클릭했을 땐 선택된 마커를 제거해줘야 한다.
mMap.setOnMapClickListener (object: GoogleMap.OnMapClickListener{
override fun onMapClick(p0: LatLng?) {
changeSelectedMarker(null);
}
})
그리고 마지막으로 마커를 다시 생성하기 위한 별도의 addMarker() 함수를 만들어준다.
private fun addMarker(marker: Marker, isSelectedMarker: Boolean): Marker {
val lat: Double = marker.getPosition().latitude
val lon: Double = marker.getPosition().longitude
val tag: String = marker.getTitle()
val temp = MarkerItem(lat, lon, price)
return addMarker(temp, isSelectedMarker)
}
이제 실행시켜보면 제대로 적용되어 다음 사진처럼 출력된다.
결론
커스텀마커를 구글 맵에서 사용해보았다.
하지만 이렇게만 구현하게되면 마커가 굉장히 많을 경우, 마커가 겹쳐서 구분하기 힘들다.
따라서 다음 포스팅에선 이 문제를 해결할 수 있는 클러스터링 기능을 사용해보자.
향후과제
구글 맵 클러스터링 활용
참고자료
https://gun0912.tistory.com/57
Writer: Jae-Hwan Lee
댓글남기기