일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 정처기
- 카카오코테
- 오블완
- groupby
- 정보처리기사
- Android
- CS
- 안드로이드스튜디오
- 스터디
- 자바
- Til
- 프로그래머스
- 인프런
- MySQL
- join
- 티스토리챌린지
- 알고리즘
- 코테
- 자료구조
- select
- 안드로이드
- Kotlin
- 기술면접
- java
- 코틀린
- 혼공단
- 혼공파
- SQL
- 혼공챌린지
- doitandroid
- Today
- Total
Welcome! Everything is fine.
[Android/study] 네이버 지도③-1 마커 클릭 이벤트, 인텐트로 데이터 전달 본문
네이버 지도를 사용하면서 겪은 시행착오를 기록하고 있다. 이전 포스팅에서 이어진다.
클릭이벤트를 발생시키는 것까지는 가능한데, 밑에 정보창을 어떻게 띄워야할지가 어려웠다. 그러다가 마커를 누르면 밑에 또다른 액티비티(정보창 액티비티)가 뜨도록 하는 것에 성공했다. 그러나 이 방법으로 하면 마커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>
화면의 크기를 조정하여 띄우는 방법은 아래 블로그 글과 책을 참고하였다.
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 변수인 mapInfoName과 mapInfoAddr에 각각 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에서 데이터를 정상적으로 불러왔지만, 마커 하나를 누르고 다른 마커를 누르려고 할 때마다 뒤로가기를 눌러야 한다. 사용자 경험이 매우 좋지 않은(...) 결과가 나왔기 때문에 다른 방법을 모색해봐야겠다.
+ 해결
레이아웃을 활용해 뒤로가기를 눌러야하는 문제를 해결하였다.
'Android' 카테고리의 다른 글
[Android/Kotiln] 스플래시(Splash) 화면 만들기 (0) | 2023.04.19 |
---|---|
[Android/study] 네이버 지도③-2 마커 클릭 이벤트, 레이아웃 visibility 속성 (0) | 2022.08.11 |
[Android/study] 네이버 지도② 다중 마커 띄우기, DB에서 위도와 경도 가져와 마커 띄우기 (1) | 2022.08.03 |
[Android/study] 네이버 지도① 맵 사용하기, 현재 위치 표시, 마커 띄우기 (0) | 2022.08.01 |
[Android/study] 불필요한 텍스트 제거하기, 리사이클러뷰 만들기 (0) | 2022.05.24 |