안 쓰던 블로그

안드로이드 kotlin - google map에 cardview로 세부정보 띄우기(구글맵 마커에 여러 정보 넣기) 본문

안드로이드

안드로이드 kotlin - google map에 cardview로 세부정보 띄우기(구글맵 마커에 여러 정보 넣기)

proqk 2020. 8. 21. 16:27
반응형

에러로 구글 맵이 로딩되지 않은 사진이지만..

이런 식으로 뒤에 구글맵이 뜨고 핀을 누르면 상제 정보가 뜨는 카드뷰를 만들고자 한다

 

 

먼저 이런 프레그먼트와 카드뷰를 띄운다

 

카드뷰를 사용하기 위해서 아래 라이브러리를 추가한다

roundedimageview는 이미지 끝을 둥글게 해 주고, 카드뷰는 카드뷰를 띄우게 해 준다

roundedimageview는 근데 검색으로는 뜨지 않아서 직접 추가하고 sync하였다

implementation 'com.makeramen:roundedimageview:2.3.0'
implementation 'com.android.support:cardview-v7:28.0.0'

 

아래는 xml코드

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:map="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" />

    <LinearLayout
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="220dp"
        android:layout_marginBottom="30dp"
        android:layout_alignParentBottom="true"
        xmlns:card_view="http://schemas.android.com/apk/res-auto">

        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            card_view:cardBackgroundColor="#ffffff"
            card_view:cardCornerRadius="20dp"
            card_view:cardElevation="4dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="220dp"
                android:layout_marginLeft="8.8dp"
                android:layout_marginBottom="40dp"
                android:orientation="vertical">

                <TextView
                    android:layout_width="375dp"
                    android:layout_height="45dp"
                    android:layout_marginLeft="10dp"
                    android:layout_marginTop="8dp"
                    android:gravity="center|left"
                    android:text="상세 정보"
                    android:textColor="#000000"
                    android:textSize="9pt"
                    android:textStyle="bold" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="25dp"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="70dp"
                        android:layout_height="20dp"
                        android:layout_marginLeft="16dp"
                        android:layout_marginTop="5dp"
                        android:text="공원이름:   "
                        android:textColor="#000000"
                        android:textSize="14dp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/park_name"
                        android:layout_width="290dp"
                        android:layout_height="20dp"
                        android:layout_marginTop="5dp"
                        android:text="갱신 전"
                        android:textSize="14dp"
                        android:textColor="#000000"
                        />
                </LinearLayout>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="25dp"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="70dp"
                        android:layout_height="20dp"
                        android:layout_marginLeft="16dp"
                        android:layout_marginTop="7dp"
                        android:text="공원분류: "
                        android:textColor="#000000"
                        android:textSize="14dp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/park_what"
                        android:layout_marginTop="7dp"
                        android:layout_width="290dp"
                        android:text="갱신 전"
                        android:textSize="14dp"
                        android:textColor="#000000"
                        android:layout_height="20dp" />
                </LinearLayout>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="25dp"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="20dp"
                        android:layout_marginLeft="16dp"
                        android:layout_marginTop="7dp"
                        android:text="신 주소:       "
                        android:textColor="#000000"
                        android:textSize="14dp"
                        android:textStyle="bold"  />

                    <TextView
                        android:id="@+id/park_add_lot"
                        android:layout_marginTop="7dp"
                        android:layout_width="290dp"
                        android:text="갱신 전"
                        android:textSize="14dp"
                        android:textColor="#000000"
                        android:layout_height="20dp" />
                </LinearLayout>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="25dp"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="20dp"
                        android:layout_marginLeft="16dp"
                        android:layout_marginTop="7dp"
                        android:text="구 주소:       "
                        android:textColor="#000000"
                        android:textSize="14dp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/park_add_road"
                        android:layout_marginTop="7dp"
                        android:layout_width="290dp"
                        android:text="갱신 전"
                        android:textSize="14dp"
                        android:textColor="#000000"
                        android:layout_height="20dp" />
                </LinearLayout>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="25dp"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="70dp"
                        android:layout_height="20dp"
                        android:layout_marginLeft="16dp"
                        android:layout_marginTop="7dp"
                        android:text="전화번호: "
                        android:textColor="#000000"
                        android:textSize="14dp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/phone_num"
                        android:layout_marginTop="7dp"
                        android:layout_width="290dp"
                        android:text="갱신 전"
                        android:textSize="14dp"
                        android:textColor="#000000"
                        android:layout_height="20dp" />
                </LinearLayout>


                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="25dp"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="70dp"
                        android:layout_height="20dp"
                        android:layout_marginLeft="16dp"
                        android:layout_marginTop="7dp"
                        android:layout_marginBottom="25dp"
                        android:text="편의시설: "
                        android:textColor="#000000"
                        android:textSize="14dp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/equip"
                        android:layout_marginTop="7dp"
                        android:layout_width="290dp"
                        android:text="갱신 전"
                        android:textSize="14dp"
                        android:textColor="#000000"
                        android:layout_height="20dp" />
                </LinearLayout>


            </LinearLayout>
        </androidx.cardview.widget.CardView>
    </LinearLayout>

</RelativeLayout>

 

시설이름: ______ 형식으로 만들었고 문자열이 들어갈 자리는 id를 붙여주는 작업을 했다

구글 맵은 fragment로 띄워질 것이다

 

이 문서에서 구글 지도를 띄우는 부분은 자세하게 다루지 않겠습니다

구글 맵은 이 문서를 참고해 주세요 https://developers.google.com/maps/documentation/android-sdk/current-place-tutorial

 

지도에서 현재 장소 선택 및 세부정보 표시하기  |  Maps SDK for Android  |  Google Developers

이 가이드에서는 Android 기기의 현재 위치를 찾고 해당 위치에 있는 장소(비즈니스 또는 기타 관심 장소)의 세부정보를 표시하는 방법을 설명합니다. Maps SDK for Android, Places SDK for Android, Google Play �

developers.google.com

 

메인액티비티

    override fun onMapReady(googleMap: GoogleMap) {
        map = googleMap
        var i = 0
        val collection = arrayOf<String>("Gangbuk", "Jungnang", "Nowon", "Seongbuk")

        //for문: DB에 저장된 정보를 바탕으로 핀을 그립니다.
        for (path in collection) {
            db.collection(path)
                .get()
                .addOnSuccessListener { result ->
                    for (document in result) {
                        i++
                        var location = LatLng(
                            document.data["lat"].toString().toDouble(),
                            document.data["lng"].toString().toDouble()
                        ) //위도, 경도

                        val markerOptions = MarkerOptions() //핀
                        markerOptions.title(document.id) //공원 이름

                        markerOptions.snippet(document.data["snippet"] as String) //공원 종류
                        markerOptions.position(location) //위치(위도, 경도 값)
                        markerOptions.icon(
                            BitmapDescriptorFactory.defaultMarker(
                                BitmapDescriptorFactory.HUE_AZURE
                            )
                        )

                        //핀 추가하면서 나머지 데이터도 미리 저장해 둔다
                        val marker: Marker = googleMap.addMarker(markerOptions) //핀 추가 및 마커 생성
                        marker.tag =
                            document.data["address(lot)"] as String + "/" +
                            document.data["address(road)"] as String + "/" +
                            document.data["phoneNumber"] as String + "/" +
                            document.data["Equipment"] as String
                        Log.d("tkdtpwjdqh", document.data["address(lot)"] as String)
                        
                        //해당 핀으로 카메라 이동
                        if (result.size() <= i) //마지막 핀으로 카메라 이동
                            googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 16F))
                    }
                }
                .addOnFailureListener { exception ->
                    Log.w("mapPoint", "Error getting documents.", exception)
                }
        }

        //마커 클릭 리스너-마커 클릭하면 카드뷰 띄움
        googleMap!!.setOnMarkerClickListener(object : GoogleMap.OnMarkerClickListener {
            override fun onMarkerClick(marker: Marker): Boolean {
                card_view.visibility = View.VISIBLE
                var parkname = findViewById<TextView>(R.id.park_name)
                var parkwhat = findViewById<TextView>(R.id.park_what)
                var parkadd1 = findViewById<TextView>(R.id.park_add_lot)
                var parkadd2 = findViewById<TextView>(R.id.park_add_road)
                var parkphone = findViewById<TextView>(R.id.phone_num)
                var parkequip = findViewById<TextView>(R.id.equip)
                var arr = marker.tag.toString().split("/") //마커에 붙인 태그
                parkname.text = marker.title
                parkwhat.text = marker.snippet
                parkadd1.text = arr[0]
                parkadd2.text = arr[1]
                parkphone.text = arr[2]
                parkequip.text = arr[3]
//                Log.d("parkinfo", "parkname->"+marker.title+"___pakrwhat->")
                return false
            }
        })

        //맵 클릭 리스너-맵 클릭하면 카드뷰 없어짐
        googleMap!!.setOnMapClickListener(object : GoogleMap.OnMapClickListener {
            override fun onMapClick(latLng: LatLng) {
                card_view.visibility = View.GONE
            }
        })

        getLocationPermission()
        updateLocationUI()


    }

DB내용도 있고 함수 전체를 가져오지 않아서 그대로 다른 프로젝트에 사용하면 물론 작동하지 않는다

여기서는 안 나왔는데 메인액티비티 맨 위에 onCreate()할 때 카드뷰를 보이지 않게 해야 한다

override fun onCreate(savedInstanceState: Bundle?) {
	... //구글맵 로딩 부분
    
        //시작하면 세부 화면은 안 보이게
        card_view.visibility = View.GONE
    }

이런 식으로 한다

즉 xml파일이 메인 액티비티에 로딩되는 파일이여야 한다

왜냐하면 이 코드 자체가 fragment로 구글맵 로딩하고 그 위에 '갱신 전'을 넣은 카드뷰가 이미 있는 상태에서

onCreate할 때 안 보이게 했다가 마커 클릭하면 보이게 했다가 맵 클릭하면 안 보이게 했다가.. 그런 식으로 동작하기 때문

 

자세한 코드를 봅시다

val marker: Marker = googleMap.addMarker(markerOptions) //핀 추가 및 마커 생성
marker.tag =
	document.data["address(lot)"] as String + "/" +
	document.data["address(road)"] as String + "/" +
	document.data["phoneNumber"] as String + "/" +
	document.data["Equipment"] as String
Log.d("tkdtpwjdqh", document.data["address(lot)"] as String)

이 부분이 구글맵에 마커(핀)를 찍는 코드인데, 원래는 아래 코드처럼 addMarker.~에 여러 정보를 담는 식으로 title이나 snippet 등의 정보를 넣을 수 있다

markerOptions.title(document.id)
markerOptions.snippet(document.data["snippet"] as String)

하지만 snippet같은 경우 하나의 정보만 넣을 수 있기 때문에 적합하지 않았고, 여러 정보를 넣어야만 했다

 

그래서 snippet은 대표 정보만 넣고 marker에 string으로 넣고 싶은 정보를 슬래쉬와 함께 다 때려넣고

	googleMap!!.setOnMarkerClickListener(object : GoogleMap.OnMarkerClickListener {
            override fun onMarkerClick(marker: Marker): Boolean {
                card_view.visibility = View.VISIBLE
                var parkname = findViewById<TextView>(R.id.park_name)
                var parkwhat = findViewById<TextView>(R.id.park_what)
                var parkadd1 = findViewById<TextView>(R.id.park_add_lot)
                var parkadd2 = findViewById<TextView>(R.id.park_add_road)
                var parkphone = findViewById<TextView>(R.id.phone_num)
                var parkequip = findViewById<TextView>(R.id.equip)
                var arr = marker.tag.toString().split("/") //마커에 붙인 태그
                parkname.text = marker.title
                parkwhat.text = marker.snippet
                parkadd1.text = arr[0]
                parkadd2.text = arr[1]
                parkphone.text = arr[2]
                parkequip.text = arr[3]
                return false
            }
        })

이렇게 마커를 눌렀을 때(상세 정보가 띄워질 때) 그 String을 / 기준으로 split으로 나눠서 정보를 쪼개고

해당 정보를 하나씩 text에 붙여서 넘기는 식으로 했다

 

자바는 이렇게 보다는 HashMap을 써서 합친 후 쪼개는 식으로도 하던데, 코틀린도 HashMap처럼 할 수는 있겠지만 이렇게 하는 게 더 직관적이고 좋아보였다

 

        //맵 클릭 리스너-맵 클릭하면 카드뷰 없어짐
        googleMap!!.setOnMapClickListener(object : GoogleMap.OnMapClickListener {
            override fun onMapClick(latLng: LatLng) {
                card_view.visibility = View.GONE
            }
        })

이후 맵을 클리하면 카드뷰를 보이지 않게 설정하면 되었다

반응형
Comments