본문 바로가기
안드로이드스튜디오 개발

[안드로이드 스튜디오] 네이버지도 #4 - 마커 표시 및 이벤트처리

by jinu957 2020. 6. 15.
728x90

이번 포스팅에서는 네이버 지도에 마커를 표시하는 방법을 설명하도록 하겠습니다.

 

이전 포스팅에서 만들었던 프로젝트를 활용하여 계속 코딩합니다.

 

2020/06/15 - [안드로이드스튜디오 개발] - [안드로이드 스튜디오] 네이버 지도 #2 - MapView 활용하기

 

[안드로이드 스튜디오] 네이버 지도 #2 - MapView 활용하기

이번 포스팅에서는 네이버 클라우드 플랫폼에서 제공하는 네이버지도의 MapView 기능을 안드로이드 스튜디오에서 사용하는 방법을 살펴보도록 하겠습니다. 이전 포스트에서 네이버 지도를 사용�

andro-jinu.tistory.com

 

이번에는 마커를 표시할거라서 layout에 버튼을 3개 추가해서 테스트할 예정입니다.

 

먼저 수정된 activity_main.xml 입니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btnmark1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="마커1"/>
        <Button
            android:id="@+id/btnmark2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="마커2"/>
        <Button
            android:id="@+id/btnmark3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="마커3"/>
    </LinearLayout>

    <com.naver.maps.map.MapView
        android:id="@+id/map_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

 

기존 소스에서 btnmark1, btnmark2, btnmark3을 추가했습니다.

 

그리고 화면상단에 액션바가 보기싫어서 액션바를 없애줌니다.

액션바는 manifests에서 수정할 수 있습니다.

 

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.navermap">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.NoActionBar">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.naver.maps.map.CLIENT_ID"
            android:value="xioq8x8zza" />
    </application>

</manifest>

액션바는 application에서 테마를 변경함으로써 없애줄 수 있습니다.

기존 디폴트는 android:theme="@style/AppTheme" 이렇게 되있는데

이것을 android:theme="@style/Theme.AppCompat.NoActionBar" 이렇게 바꾸었습니다.

 

그리고 지도상에 표시될 마커의 아이콘을 추가합니다.

 

아이콘은 New => Vector Asset에서 추가합니다.

 

 

Vector Asset를 선택하면 위 그림처럼 나오는데 여기서 Clip Art의 그림을 클릭합니다.

그러면 미리 준비되어있는 아이콘들을 선택할 수 있습니다. 이 아이콘들은 벡터값으로 되어있기때문에 해상도에 상관없이 동일한 이미지를 보여줍니다.

 

 

저는 가장 많이 쓰이는 place라는 아이콘을 선택하였으며 색상은 빨간색으로 했습니다. 그리고 비교를 위해서 album이라는 아이콘을 녹색으로 하나 더 추가했습니다.

이제 마커를 표시하는 부분이 추가된 MainActivity입니다.

 

먼저 3개의 마커를 표시하기 위하여 setMark()라는 함수를 만들었습니다.

 

setMark()

    private void setMark(Marker marker,  double lat, double lng, int resourceID)
    {
        //원근감 표시
        marker.setIconPerspectiveEnabled(true);
        //아이콘 지정
        marker.setIcon(OverlayImage.fromResource(resourceID));
        //마커의 투명도
        marker.setAlpha(0.8f);
        //마커 위치
        marker.setPosition(new LatLng(lat, lng));
        //마커 우선순위
        marker.setZIndex(10);
        //마커 표시
        marker.setMap(naverMap);
    }

파라메타로는 미리 생성된 Marker 변수와 위도, 경도, 그리고 표시된 아이콘의 리소스ID입니다.

 

marker.setIconPerspectiveEnabled(true);

마커의 원근감을 표시하는 옵션입니다. (디폴트:false, 생략 가능)

앞 프로젝트에서 네이버 지도를 표출할때 tilt를 주었기때문에 마커도 원근감을 표시하기 위하여 값을 true로 주었습니다. 

 

marker.setIcon(OverlayImage.fromResource(resourceID));

마커의 아이콘을 지정합니다.

 

marker.setAlpha(0.8f);

마커의 투명도를 지정합니다. (디폴트:1.0, 생략가능)

 

marker.setPosition(new LatLng(lat, lng));

마커의 위경도를 지정합니다.

 

marker.setZIndex(zIndex);

마커가 서로 겹쳤을때 앞쪽에 표시될 우선순위를 지정합니다. 숫자가 높을 수록 상위로 올라갑니다.

단, ZIndex값을 지정하지 않을 경우 아래쪽에 위치한 마커가 위로 올라갑니다.

 

marker.setMap(naverMap);

마커를 지도 상에 표출합니다.

 

다음은 마커를 클릭했을때 이벤트 처리하는 부분입니다.

marker1.setOnClickListener(new Overlay.OnClickListener() {
	@Override
	public boolean onClick(@NonNull Overlay overlay)
	{
		Toast.makeText(getApplication(), "마커1 클릭", Toast.LENGTH_SHORT).show();
	return false;
	}
});

마커1을 클릭했을때 토스트메시지를 표시합니다.

 

 

이제 버튼이 눌렸을때 이벤트를 처리하는 부분이 포함된 전체 MainActivity입니다.

 

MainActivity.java

package com.test.navermap;

import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.naver.maps.geometry.LatLng;
import com.naver.maps.map.CameraPosition;
import com.naver.maps.map.MapView;
import com.naver.maps.map.NaverMap;
import com.naver.maps.map.OnMapReadyCallback;
import com.naver.maps.map.overlay.Marker;
import com.naver.maps.map.overlay.Overlay;
import com.naver.maps.map.overlay.OverlayImage;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback
{
    private MapView mapView;
    private static NaverMap naverMap;

    //마커 변수 선언 및 초기화
    private Marker marker1 = new Marker();
    private Marker marker2 = new Marker();
    private Marker marker3 = new Marker();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnMark1 = (Button) findViewById(R.id.btnmark1);
        Button btnMark2 = (Button) findViewById(R.id.btnmark2);
        Button btnMark3 = (Button) findViewById(R.id.btnmark3);

        btnMark1.setOnClickListener(new Button.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                setMarker(marker1, 33.2712, 126.5354, R.drawable.ic_place_black_24dp, 0);

                marker1.setOnClickListener(new Overlay.OnClickListener() {
                    @Override
                    public boolean onClick(@NonNull Overlay overlay)
                    {
                        Toast.makeText(getApplication(), "마커1 클릭", Toast.LENGTH_SHORT).show();
                        return false;
                    }
                });
            }
        });

        btnMark2.setOnClickListener(new Button.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                setMarker(marker2, 33.49957, 126.531076, R.drawable.ic_album_black_24dp, 10);
            }
        });

        btnMark3.setOnClickListener(new Button.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                setMarker(marker3, 33.49957, 126.531128, R.drawable.ic_place_black_24dp, 0);
            }
        });


        //네이버 지도
        mapView = (MapView) findViewById(R.id.map_view);
        mapView.onCreate(savedInstanceState);
        mapView.getMapAsync(this);
    }

    private void setMarker(Marker marker,  double lat, double lng, int resourceID, int zIndex)
    {
        //원근감 표시
        marker.setIconPerspectiveEnabled(true);
        //아이콘 지정
        marker.setIcon(OverlayImage.fromResource(resourceID));
        //마커의 투명도
        marker.setAlpha(0.8f);
        //마커 위치
        marker.setPosition(new LatLng(lat, lng));
        //마커 우선순위
        marker.setZIndex(zIndex);
        //마커 표시
        marker.setMap(naverMap);
    }


    @Override
    public void onMapReady(@NonNull NaverMap naverMap)
    {
        this.naverMap = naverMap;

        //배경 지도 선택
        naverMap.setMapType(NaverMap.MapType.Navi);

        //건물 표시
        naverMap.setLayerGroupEnabled(naverMap.LAYER_GROUP_BUILDING, true);

        //위치 및 각도 조정
        CameraPosition cameraPosition = new CameraPosition(
                new LatLng(33.38, 126.55),   // 위치 지정
                9,                                     // 줌 레벨
                45,                                       // 기울임 각도
                0                                     // 방향
        );
        naverMap.setCameraPosition(cameraPosition);
    }

    @Override
    public void onStart()
    {
        super.onStart();
        mapView.onStart();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        mapView.onResume();
    }

    @Override
    public void onPause()
    {
        super.onPause();
        mapView.onPause();
    }

    @Override
    public void onStop()
    {
        super.onStop();
        mapView.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }

    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }

    @Override
    public void onLowMemory()
    {
        super.onLowMemory();
        mapView.onLowMemory();
    }
}

이제 실행을 해보면 

3개의 마커가 잘 표시되는걸 볼수 있습니다. 그리고 마커1을 눌렀을때 토스트메시지도 잘 표출됩니다.

 

여기서 2번 3번 마커의 위도가 같음에도 ZIndex 높은 2번 마커가 위로 올라간걸 볼 수 있습니다.

 

그리고 위 그림에서 보면 빨간색 마커의 아래 뾰족한 부분이 실제 위경도값을 가리키고 있습니다.

이것은 앵커 속성의 디폴트값이 바닥, 가운데로 설정되어있기때문입니다.

녹색 마커의 경우 중앙의 점이 실제 위치로 이동시키려면 앵커 속성을 조정해주면 됩니다.

marker.setAnchor(new PointF(0.5f, 0.5f));

이렇게 하면 아이콘의 중앙이 실제 좌표로 이동하게 됩니다.

앵커는 왼쪽 위가 (0, 0), 오른쪽 아래가 (1, 1)인 비율로 표현합니다.

 

그리고 마커에 캡션을 주려면 setCaptionText 함수를 이용합니다.

marker.setCaptionText("제주시청");

 

그 밖에도 다양한 함수들이 존재하니 나머지는 네이버 클라우드 플랫폼의 가이드를 참조하시기 바랍니다.

 

그럼 다음 포스팅에서는 InfoWindow 표시하는 방법을 설명하도록 하겠습니다.

 

 

PS. 매번 프로젝트만 진행하다가 개인적으로 앱을 하나 출시했습니다.

비록 허접한 앱이기는 하지만 이걸 토대로 몇몇가지 팁에 대해 포스팅을 작성하려고 하오니 아래 포스팅 글 한번 읽어봐 주시면 감사하겠습니다. ^^

andro-jinu.tistory.com/entry/todaysaying1

 

[안드로이드 스튜디오] 앱 출시 소식 - 오늘의 명언(명언, 고사성어, 속담)

아주 오랜만에 포스팅을 하게 됐네요 그동안 다른 프로젝트로 매우 바뻤던 관계로 한동안 포스팅을 못했는데 요즘 짬이 나서 간단하게 앱을 만들고 출시까지 하였습니다. 그동안은 앱을 만들긴

andro-jinu.tistory.com

 

728x90

댓글