Welcome! Everything is fine.

[Android/study] 네이버 지도③-1 마커 클릭 이벤트, 인텐트로 데이터 전달 본문

Android

[Android/study] 네이버 지도③-1 마커 클릭 이벤트, 인텐트로 데이터 전달

개발곰발 2022. 8. 11.
728x90

네이버 지도를 사용하면서 겪은 시행착오를 기록하고 있다. 이전 포스팅에서 이어진다.

 

[Android] 네이버 지도① 맵 사용하기, 현재 위치 표시, 마커 띄우기

내가 네이버 지도를 사용해보며 정리하고 싶었던 내용을 작성해보고자 한다. 📌 네이버 지도 사용하기 클라이언트 ID 발급 네이버 지도 SDK를 사용하려면 네이버 클라우드 플랫폼에서 애플리케

3uomlkh.tistory.com

 

[Android] 네이버 지도② 다중 마커 띄우기, DB에서 위도와 경도 가져와 마커 띄우기

네이버 지도를 사용하면서 기억하고 싶은 부분을 정리하고자 한다. 아래의 이전 포스팅과 이어지는 내용이다. [Android] 네이버 지도 사용하기, 현재 위치 표시, 마커 띄우기 📌 네이버 지도 사용

3uomlkh.tistory.com

클릭이벤트를 발생시키는 것까지는 가능한데, 밑에 정보창을 어떻게 띄워야할지가 어려웠다. 그러다가 마커를 누르면 밑에 또다른 액티비티(정보창 액티비티)가 뜨도록 하는 것에 성공했다. 그러나 이 방법으로 하면 마커1을 누르고, 바로 마커2를 누를 수 있는 게 아니라, 뒤로가기를 먼저 눌러 정보창 액티비티에서 나온 후에 마커2를 눌러야 한다는 문제점이 생겼다. 우선 시도한 내용을 정리 해본 후 다른 방법으로 시도해봐야 할 것 같다.

 

내가 원하는 결과는 다음과 같이 지도 위에 띄워진 마커를 누르면 아래쪽에서 해당 장소에 대한 간단한 정보가 뜨도록 하는 것이다. 또한 정보창이 띄워진 상태로 다른 마커를 클릭하면 해당 정보창 안의 내용만 바뀌도록 하고싶다.

내가 원하는 결과

📌 액티비티 전환하기

먼저 기존의 MapActivity 위에 띄울 MapInfoActivity를 만든다. (왼쪽 상단에서 File - New - Activity - Empty Activity) 그리고 MapActivity.java 파일에서 클릭이벤트가 발생되는 부분에서 MapInfoActiviy로 전환되도록 다음과 같이 적어준다.

markers[i].setOnClickListener(new Overlay.OnClickListener() {
    @Override
    public boolean onClick(@NonNull Overlay overlay)
    {
        Intent intent = new Intent(MapActivity.this, MapInfoActivity.class);
        startActivity(intent);
        return false;
    }
});

전환되어 나타나는 부분인 activity_map_info.xml에 다음과 같이 임시로 텍스트를 입력하고 확인해본다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MapInfoActivity"
    android:gravity="center_vertical"
    android:layout_margin="15dp">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="지도 정보창 액티비티"
        android:textSize="24dp"
        android:textColor="@color/purple_200"/>
</LinearLayout>

마커를 누르면 내가 적은 '지도 정보창 액티비티'라는 텍스트가 새 액티비티 위에 나타난 것을 볼 수 있다.

마커 클릭이벤트 - 액티비티 전환

📌 화면 크기 조정하여 띄우기

내가 원하는 결과는 마커를 누를 시 액티비티 전체가 바뀌는 것이 아닌, 하단에 작은 창 형태로 나타나는 것이다. 또한 각각의 마커에 따라 정보가 바뀌도록 하고 싶다.  우선 activity_map_info.xml을 다음과 같이 수정하였다. 식당 이미지가 들어가는 ImageView와 식당명, 주소, 영업시간, 휴무일이 들어가는 TextView, 식당 상세 페이지로 들어가는 버튼인 ImageButton을 만들어 배치하였다. 이전 포스팅에서 retrofit2를 사용하여 마커를 찍은 것과 비슷한 방법으로 DB에 있는 식당명과 주소를 먼저 띄워볼 것이다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MapInfoActivity"
    android:gravity="center_vertical"
    android:layout_margin="15dp"
    android:background="@color/white"
    android:id="@+id/map_info_layout">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:src="@drawable/camera"
            android:layout_gravity="center"/>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/map_info_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="식당명"
                android:textSize="16dp" />

            <TextView
                android:id="@+id/map_info_addr"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="주소"
                android:textSize="12dp" />

            <TextView
                android:id="@+id/map_info_hour"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="영업시간"
                android:textSize="12dp" />

            <TextView
                android:id="@+id/map_info_break"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="휴무일"
                android:textSize="12dp" />
        </LinearLayout>
        <ImageButton
            android:id="@+id/map_info_button"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:src="@android:drawable/ic_media_play"
            android:layout_gravity="center"/>
    </LinearLayout>
</LinearLayout>

activity_map_info.xml

화면의 크기를 조정하여 띄우는 방법은 아래 블로그 글과 책을 참고하였다. 

 

화면 크기 조정 하여 띄우기 android(kotlin)

화면 크기 조정 하는 방법을 포스팅 하려고 합니다. 다이얼로그 띄우는 거랑 비슷할 수 있는 activity로 화면 전환 액티비티 크기를 축소하여 마치 다이얼로그처럼 띄우는 방법입니다. 이 방법은

niqrid2020.pe.kr

themes.xml에 <style> 태그 삽입

<style name="AppTheme.Custom" parent="Theme.AppCompat.DayNight.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="android:windowIsTranslucent">true</item>
</style>

AndroidMenifest.xml에 <activity> 태그 삽입

<activity
    android:name=".MapInfoActivity"
    android:theme="@style/AppTheme.Custom"/>

MapInfoActivity.java

onResume()에서 호출하는 initLayout() 메서드에서는 다양한 스마트폰의 사이즈를 구하고, 그에 맞게 레이아웃을 조절하도록 하는 역할을 한다. 스마트폰의 사이즈 정보를 획득하는 방법에는 버전마다 차이가 있다. DisplayMetrics 객체는 API Level 30 이전 버전에서 이용하고, API Level 30 버전부터는 windowMetrics객체를 이용하는 것이 권장된다. 따라서 다음 코드와 같이 if-else문으로 API Level 30 이전/이후 버전으로 나누어서 작성해야한다. Build.VERSION.SDK_INT는 앱이 실행되는 기기의 버전 정보이고, Build.VERSION_CODES.R안드로이드 11버전(API Level 30 버전)을 뜻한다.

    @Override
    protected void onResume() {
        super.onResume();

        initLayout();
    }

    private void initLayout() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // API Level 30 버전
            WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
            width = windowMetrics.getBounds().width();
            height = windowMetrics.getBounds().height();
        } else { // API Level 30 이전 버전
            Display display = getWindowManager().getDefaultDisplay();
            DisplayMetrics displayMetrics = new DisplayMetrics();
            display.getRealMetrics(displayMetrics);
            width = displayMetrics.widthPixels;
            height = displayMetrics.heightPixels;
        }
        getWindow().setLayout((int) round(width * 0.9), (int)round(height * 0.22));
        getWindow().setGravity(Gravity.BOTTOM);
        getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    }
}

이 상태에서 실행하면 다음과 같은 결과가 나온다.

MapActivity.java

이제 '식당명'과 '주소' TextView에 DB에 있는 식당 이름과 주소를 넣어볼 것이다. 즉 각각의 마커를 눌렀을 때, 똑같은 정보창이 아닌 해당 마커 위치에 있는 식당의 이름과 주소가 나오는 것이다. retrofit2를 이용하여 DB로부터 데이터를 가져와 출력하는 자세한 과정은 네이버 지도② 포스팅을 참조한다. String 변수인 mapInfoNamemapInfoAddr에 각각 DB에 있는 정보를 넣는다. 그리고 putExtra() 함수를 이용하여 데이터를 인텐트 객체에 담아준다. Extra 데이터(key, value) 성격으로 담아주면 된다.

markers[i].setOnClickListener(new Overlay.OnClickListener() {
    @Override
    public boolean onClick(@NonNull Overlay overlay)
    {
        mapInfoName = naverMapInfo.get(finalI).getStoreName();
        mapInfoAddr = naverMapInfo.get(finalI).getStoreAddr();
        Intent intent = new Intent(MapActivity.this, MapInfoActivity.class);
        intent.putExtra("name", mapInfoName);
        intent.putExtra("addr", mapInfoAddr);
        startActivity(intent);
        return false;

    }
});

다시 MapInfoActivity.java로 돌아와서 onResume()에서 getIntent() 함수를 사용하여 내가 실행했던 인텐트를 얻는다. 그리고 getStringExtra() 함수로 그 인텐트 객체에 담긴 데이터를 얻는다. 얻은 데이터로 TextView에 있는 텍스트를 바꾸면된다.

@Override
protected void onResume() {
    super.onResume();

    getMapInfoName = findViewById(R.id.map_info_name);
    getMapInfoAddr = findViewById(R.id.map_info_addr);

    Intent intent = getIntent();
    name = intent.getStringExtra("name");
    addr = intent.getStringExtra("addr");

    getMapInfoName.setText(name);
    getMapInfoAddr.setText(addr);

    initLayout();
}

📌 결과

실행을 해보면 다음과 같은 결과가 나온다. DB에서 데이터를 정상적으로 불러왔지만, 마커 하나를 누르고 다른 마커를 누르려고 할 때마다 뒤로가기를 눌러야 한다. 사용자 경험이 매우 좋지 않은(...) 결과가 나왔기 때문에 다른 방법을 모색해봐야겠다.