사용자 인터페이스

사용자는 컨트롤, 제스처 등 다양한 방법으로 지도와 상호작용할 수 있습니다. 개발자는 사용자가 지도와 상호작용하는 방법을 제어하고, UI 이벤트를 처리해 알맞은 피드백을 줄 수 있습니다.

UI 설정

UiSettings는 UI와 관련된 설정을 담당하는 클래스입니다. UiSettings의 속성을 변경하면 컨트롤, 제스처 등 UI와 관련된 요소를 제어할 수 있습니다.

객체 접근

UiSettings 클래스의 인스턴스는 직접 생성할 수 없고 NaverMap.getUiSettings()를 호출해 가져와야 합니다. 하나의 UiSettings 인스턴스는 하나의 NaverMap 인스턴스와 1:1로 대응됩니다.

다음은 NaverMap으로부터 UiSettings 인스턴스를 가져오는 예제입니다.

UiSettings uiSettings = naverMap.getUiSettings();

Java

UiSettings uiSettings = naverMap.getUiSettings();

Kotlin

val uiSettings = naverMap.uiSettings

컨트롤

컨트롤은 지도에 대한 정보 및 간단한 조작 기능을 제공하는 지도 위 버튼을 의미합니다. 네이버 지도 SDK는 다음과 같은 여섯 가지 컨트롤을 제공합니다.

  • 나침반: 카메라의 회전 및 틸트 상태를 표현합니다. 클릭하면 카메라의 베어링과 틸트가 0으로 초기화됩니다. 베어링과 틸트가 0이 되면 자동으로 사라집니다. compassEnabled 속성으로 활성화 여부를 지정할 수 있습니다.

나침반

  • 축척 바: 지도의 축척을 표현합니다. 지도를 조작하는 기능은 없습니다. scaleBarEnabled 속성으로 활성화 여부를 지정할 수 있습니다.

축척 바

  • 줌 버튼: 클릭하면 지도의 줌 레벨을 1씩 증가 또는 감소합니다. zoomButtonEnabled 속성으로 활성화 여부를 지정할 수 있습니다.

줌 버튼

  • 실내지도 층 피커: 노출 중인 실내지도 구역의 층 정보를 표현합니다. 층을 선택하면 해당 층의 실내지도가 노출됩니다. 실내지도가 보이는 상황에만 나타납니다. indoorLevelPickerEnabled 속성으로 활성화 여부를 지정할 수 있습니다.

실내지도 층 패널

  • 현위치 버튼: 위치 추적 모드를 표현합니다. 클릭하면 모드가 변경됩니다. locationButtonEnabled 속성으로 활성화 여부를 지정할 수 있습니다. 단, 현위치 버튼을 활성화하더라도 LocationSource가 지정되지 않으면 컨트롤을 클릭하더라도 위치 추적 기능이 동작하지 않습니다. 자세한 내용은 위치 문서를 참고하세요.

현위치 버튼

  • 네이버 로고: 클릭하면 범례, 법적 공지, 오픈소스 라이선스를 보여주는 다이얼로그가 열립니다. 네이버 로고는 비활성화할 수 없으나, 위치를 조정하거나 클릭을 비활성화할 수는 있습니다. 네이버 지도 SDK를 사용하는 앱은 반드시 네이버 로고가 앱의 UI 요소에 가려지지 않도록 해야 합니다.
    • logoGravity 속성으로 그래비티를, logoMargin 속성으로 마진을 지정해 위치를 조정할 수 있습니다.
    • logoClickEnabled 속성으로 클릭 활성화 여부를 지정할 수 있습니다. 로고 클릭을 비활성화한 앱은 반드시 앱 내에 네이버 지도 SDK의 법적 공지 액티비티(LegalNoticeActivity) 및 오픈소스 라이선스 액티비티(OpenSourceLicenseActivity)로 연결되는 메뉴를 만들어야 합니다.

네이버 로고

UiSettings의 속성을 변경하면 각 컨트롤의 활성화 여부를 제어할 수 있습니다. 비활성화된 컨트롤은 화면에서 사라집니다.

다음은 나침반을 비활성화하고 현위치 버튼을 활성화하는 예제입니다.

uiSettings.setCompassEnabled(false);
uiSettings.setLocationButtonEnabled(true);

Java

uiSettings.setCompassEnabled(false);
uiSettings.setLocationButtonEnabled(true);

Kotlin

uiSettings.isCompassEnabled = false
uiSettings.isLocationButtonEnabled = true

컨트롤 배치

UiSettings로 활성화 여부를 제어하는 기본 컨트롤의 위치는 변경할 수 없습니다. 그러나 각 컨트롤은 뷰의 형태로 제공되므로 UiSettings에서 기본 컨트롤을 비활성화하고 별도의 컨트롤 뷰를 원하는 위치에 배치할 수 있습니다. 컨트롤 뷰는 widget 패키지에 있습니다. 뷰를 레이아웃에 추가하고 map 속성에 지도 객체를 지정하면 컨트롤이 동작합니다.

다음은 기본 줌 컨트롤을 비활성화하고 오른쪽 아래에 별도의 줌 컨트롤을 배치하는 예제입니다.

<FrameLayout ...>
    <FrameLayout
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.naver.maps.map.widget.ZoomControlView
        android:id="@+id/zoom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp" 
        android:layout_gravity="end|bottom" />
</FrameLayout>

FragmentManager fm = getSupportFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
    NaverMapOptions options = new NaverMapOptions().zoomControlEnabled(false);
    mapFragment = MapFragment.newInstance(options);
    fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
mapFragment.getMapAsync(naverMap -> {
    ZoomControlView zoomControlView = findViewById(R.id.zoom);
    zoomControlView.setMap(naverMap);
});

Java

FragmentManager fm = getSupportFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
    NaverMapOptions options = new NaverMapOptions().zoomControlEnabled(false);
    mapFragment = MapFragment.newInstance(options);
    fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
mapFragment.getMapAsync(naverMap -> {
    ZoomControlView zoomControlView = findViewById(R.id.zoom);
    zoomControlView.setMap(naverMap);
});

Kotlin

val fm = supportFragmentManager
val mapFragment = fm.findFragmentById(R.id.map) as MapFragment?
        ?: MapFragment.newInstance(NaverMapOptions().zoomControlEnabled(false))
                .also {
                    fm.beginTransaction().add(R.id.map, it).commit()
                }
mapFragment.getMapAsync {
    val zoomControlView = findViewById(R.id.zoom) as ZoomControlView
    zoomControlView.map = naverMap
}

제스처

사용자는 탭, 드래그, 핀치 등의 각종 제스처로 카메라를 이동할 수 있습니다. 네이버 지도 SDK는 다음과 같은 다섯 가지 제스처를 제공합니다.

  • 스크롤: 한 개 또는 두 개 이상의 손가락으로 지도를 드래그하면 카메라가 손가락을 따라 이동합니다. scrollGesturesEnabled 속성으로 활성화 여부를 지정할 수 있습니다.
  • 줌: 지도를 더블 탭하면 줌 레벨이 한 단계 확대됩니다. 두 손가락 탭하면 한 단계 축소됩니다. 핀치와 스트레치 또는 한 손가락 줌 제스처로도 지도의 줌 레벨을 변경할 수 있습니다. zoomGesturesEnabled 속성으로 활성화 여부를 지정할 수 있습니다.
  • 틸트: 두 개의 손가락으로 지도를 위아래로 드래그하면 기울임 각도가 바뀝니다. tiltGesturesEnabled 속성으로 활성화 여부를 지정할 수 있습니다.
  • 회전: 두 개의 손가락으로 지도를 돌리면 베어링 각도가 바뀝니다. rotateGesturesEnabled 속성으로 활성화 여부를 지정할 수 있습니다.
  • 스톱: 카메라 애니메이션이 진행 중일 때 지도를 터치하면 애니메이션이 취소되고 카메라가 현재 위치에 멈춥니다. stopGesturesEnabled 속성으로 활성화 여부를 지정할 수 있습니다.

UiSettings의 속성을 변경하면 각 제스처의 활성화 여부를 제어할 수 있습니다. 만약 사용자에게 기울어지거나 회전되지 않은 지도만을 보여주고자 한다면, 카메라 이동 시 틸트나 베어링 각도를 지정하지 않는 것뿐만 아니라 제스처 또한 비활성화해서 사용자가 지도를 기울이거나 회전하지 못하도록 해야 합니다.

다음은 틸트와 회전 제스처를 비활성화하는 예제입니다.

uiSettings.setTiltGesturesEnabled(false);
uiSettings.setRotateGesturesEnabled(false);

Java

uiSettings.setTiltGesturesEnabled(false);
uiSettings.setRotateGesturesEnabled(false);

Kotlin

uiSettings.isTiltGesturesEnabled = false
uiSettings.isRotateGesturesEnabled = false

초깃값 지정

NaverMapOptions 또는 XML 속성을 사용하면 지도 객체를 생성하기 전에 각 속성의 초깃값을 지정할 수 있습니다.

다음은 NaverMapOptions를 사용해 현위치 버튼을 활성화하고 틸트 제스처를 비활성화하는 예제입니다.

NaverMapOptions options = new NaverMapOptions()
    .locationButtonEnabled(true)
    .tiltGesturesEnabled(false);

Java

NaverMapOptions options = new NaverMapOptions()
    .locationButtonEnabled(true)
    .tiltGesturesEnabled(false);

Kotlin

val options = NaverMapOptions()
        .locationButtonEnabled(true)
        .tiltGesturesEnabled(false)

다음은 XML 속성을 사용해 현위치 버튼을 활성화하고 틸트 제스처를 비활성화하는 예제입니다.

<androidx.fragment.app.FragmentContainerView xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/map"
    android:name="com.naver.maps.map.MapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:navermap_locationButtonEnabled="true"
    app:navermap_tiltGesturesEnabled="false" />

UI 이벤트

네이버 지도 SDK는 사용자의 터치에 반응하는 다양한 UI 이벤트를 제공합니다.

클릭과 롱 클릭

setOnMapClickListener() 메서드로 OnMapClickListener를 지정하면 지도에 대한 클릭 이벤트를 받을 수 있습니다. 지도가 클릭되면 onMapClick() 콜백 메서드가 호출되며, 파라미터로 클릭된 지점의 화면 좌표와 지도 좌표가 전달됩니다.

다음은 지도를 클릭했을 때 클릭된 지점의 좌표를 토스트로 표시하는 예제입니다.

naverMap.setOnMapClickListener((point, coord) ->
    Toast.makeText(this, coord.latitude + ", " + coord.longitude,
        Toast.LENGTH_SHORT).show());

Java

naverMap.setOnMapClickListener((point, coord) ->
    Toast.makeText(this, coord.latitude + ", " + coord.longitude,
        Toast.LENGTH_SHORT).show());

Kotlin

naverMap.setOnMapClickListener { point, coord ->
    Toast.makeText(this, "${coord.latitude}, ${coord.longitude}",
            Toast.LENGTH_SHORT).show()
}

setOnMapLongClickListener() 메서드로 OnMapLongClickListener를 지정하면 지도에 대한 롱 클릭 이벤트를 받을 수 있습니다. 지도가 롱 클릭되면 onMapLongClick() 콜백 메서드가 호출되며, 파라미터로 클릭된 지점의 화면 좌표와 지도 좌표가 전달됩니다.

다음은 지도를 롱 클릭했을 때 롱 클릭된 지점의 좌표를 토스트로 띄우는 예제입니다.

naverMap.setOnMapLongClickListener((point, coord) ->
    Toast.makeText(this, coord.latitude + ", " + coord.longitude,
        Toast.LENGTH_SHORT).show());

Java

naverMap.setOnMapLongClickListener((point, coord) ->
    Toast.makeText(this, coord.latitude + ", " + coord.longitude,
        Toast.LENGTH_SHORT).show());

Kotlin

naverMap.setOnMapLongClickListener { point, coord ->
    Toast.makeText(this, "${coord.latitude}, ${coord.longitude}",
            Toast.LENGTH_SHORT).show()
}

심벌 클릭

네이버 지도 SDK는 지도 심벌을 클릭한 경우와 지도 자체를 클릭한 경우를 구분합니다. setOnSymbolClickListener() 메서드로 OnSymbolClickListener를 지정하면 지도 심벌에 대한 클릭 이벤트를 받을 수 있습니다. 심벌이 클릭되면 onSymbolClick() 콜백 메서드가 호출되며, 클릭된 심벌 객체가 파라미터로 전달됩니다. 심벌 객체로부터 클릭된 심벌의 위치와 캡션 텍스트를 얻을 수 있습니다.

심벌 클릭 이벤트는 지도로 전파될 수 있습니다. 이벤트를 지도로 전파하려면 OnSymbolClickListeneronSymbolClick()false를 반환하도록 구현해야 합니다. 그렇게 하면 onSymbolClick()이 반환된 후 지도의 OnClickListener.onClick()이 호출됩니다. 반대로 onSymbolClick()true를 반환할 경우 심벌이 이벤트를 소비한 것으로 간주되어 지도의 OnClickListener.onClick()은 호출되지 않습니다.

다음은 캡션 텍스트가 "서울특별시청"인 심벌이 클릭되면 "서울시청 클릭"이라는 토스트를, 그 외의 심벌 또는 지도가 클릭되면 "지도 클릭"이라는 토스트를 표시하는 예제입니다.

naverMap.setOnMapClickListener((point, coord) ->
    Toast.makeText(this, "지도 클릭", Toast.LENGTH_SHORT).show()
);

naverMap.setOnSymbolClickListener(symbol -> {
    if ("서울특별시청".equals(symbol.getCaption())) {
        Toast.makeText(this, "서울시청 클릭", Toast.LENGTH_SHORT).show();
        // 이벤트 소비, OnMapClick 이벤트는 발생하지 않음
        return true;
    }
    // 이벤트 전파, OnMapClick 이벤트가 발생함
    return false;
});

Java

naverMap.setOnMapClickListener((point, coord) ->
    Toast.makeText(this, "지도 클릭", Toast.LENGTH_SHORT).show()
);

naverMap.setOnSymbolClickListener(symbol -> {
    if ("서울특별시청".equals(symbol.getCaption())) {
        Toast.makeText(this, "서울시청 클릭", Toast.LENGTH_SHORT).show();
        // 이벤트 소비, OnMapClick 이벤트는 발생하지 않음
        return true;
    }
    // 이벤트 전파, OnMapClick 이벤트가 발생함
    return false;
});

Kotlin

naverMap.setOnMapClickListener {
    Toast.makeText(this, "지도 클릭", Toast.LENGTH_SHORT).show()
}

naverMap.setOnSymbolClickListener { symbol ->
    if (symbol.caption == "서울특별시청") {
        Toast.makeText(this, "서울시청 클릭", Toast.LENGTH_SHORT).show()
        // 이벤트 소비, OnMapClick 이벤트는 발생하지 않음
        true
    } else {
        // 이벤트 전파, OnMapClick 이벤트가 발생함
        false
    }
}

오버레이 클릭

오버레이도 심벌과 마찬가지로 클릭 이벤트를 받고, 이벤트를 소비하거나 전파할 수 있습니다. 오버레이의 클릭 이벤트는 지도 또는 심벌 클릭 이벤트와 달리 각 오버레이가 받으므로 이벤트 리스너도 각 오버레이에 등록해야 합니다. 오버레이의 setOnClickListener() 메서드로 Overlay.OnClickListener를 지정하면 오버레이에 대한 클릭 이벤트를 받을 수 있습니다. 오버레이가 클릭되면 onClick() 콜백 메서드가 호출되며, 클릭된 오버레이 객체가 파라미터로 전달됩니다.

오버레이의 클릭 이벤트는 지도로 전파될 수 있습니다. 이벤트를 지도로 전파하려면 Overlay.OnClickListeneronClick()false를 반환하도록 구현합니다. 그렇게 하면 onClick()이 반환된 후 지도의 OnClickListener.onClick()이 호출됩니다. 반대로 onClick()true를 반환할 경우 오버레이가 이벤트를 소비한 것으로 간주되어 지도의 OnClickListener는 호출되지 않습니다.

다음은 마커가 클릭되면 "마커 클릭"이라는 토스트를 표시하는 예제입니다.

marker.setOnClickListener(overlay -> {
    Toast.makeText(this, "마커 1 클릭", Toast.LENGTH_SHORT).show();
    // 이벤트 소비, OnMapClick 이벤트는 발생하지 않음
    return true;
});

Java

marker.setOnClickListener(overlay -> {
    Toast.makeText(this, "마커 1 클릭", Toast.LENGTH_SHORT).show();
    // 이벤트 소비, OnMapClick 이벤트는 발생하지 않음
    return true;
});

Kotlin

marker.setOnClickListener { overlay ->
    Toast.makeText(this, "마커 1 클릭", Toast.LENGTH_SHORT).show()
    // 이벤트 소비, OnMapClick 이벤트는 발생하지 않음
    true
}

오버레이에서 이벤트가 전파되는 곳은 오직 지도뿐입니다. 즉, 이벤트가 발생한 오버레이의 아래에 다른 오버레이나 심벌이 겹쳐져 있더라도 이 오버레이나 심벌로는 이벤트가 전파되지 않습니다. 또한 이벤트 리스너가 등록되지 않은 오버레이는 클릭 시 무시됩니다. 즉, 두 오버레이가 겹쳐져 있고 위를 덮고 있는 오버레이에 이벤트 리스너가 등록되어 있지 않다면 아래에 덮힌 오버레이가 이벤트를 받습니다. 덮힌 오버레이가 없거나 이벤트 리스너가 등록되어 있지 않다면 지도가 클릭된 것으로 간주됩니다.

더블 탭과 두 손가락 탭

더블 탭과 두 손가락 탭은 줌 제스처를 비활성화하지 않는 한 각각 지도를 확대 또는 축소하는 기능을 합니다. 지도에 이벤트 리스너를 추가하면 이들 이벤트도 받을 수 있으며, 이벤트를 소비해 기본 동작을 하지 않도록 할 수도 있습니다.

setOnMapDoubleTapListener() 메서드로 OnMapDoubleTapListener를 지정하면 더블 탭 이벤트를 받을 수 있습니다. 지도가 더블 탭되면 onMapDoubleTap() 콜백 메서드가 호출되며, 더블 탭된 지점의 화면 좌표와 지도 좌표가 파라미터로 전달됩니다. onMapDoubleTap()true를 반환하도록 구현하면 이벤트가 소비되어 화면이 확대되지 않습니다.

다음은 지도를 더블 탭했을 때 더블 탭된 지점의 좌표를 토스트로 표시하고 이벤트를 소비해 화면이 확대되지 않도록 하는 예제입니다.

naverMap.setOnMapDoubleTapListener((point, coord) -> {
    Toast.makeText(this, coord.latitude + ", " + coord.longitude,
        Toast.LENGTH_SHORT).show();
    return true;
});

Java

naverMap.setOnMapDoubleTapListener((point, coord) -> {
    Toast.makeText(this, coord.latitude + ", " + coord.longitude,
        Toast.LENGTH_SHORT).show();
    return true;
});

Kotlin

naverMap.setOnMapDoubleTapListener { point, coord ->
    Toast.makeText(this, "${coord.latitude}, ${coord.longitude}",
            Toast.LENGTH_SHORT).show()
    true
}

setOnMapTwoFingerTapListener 메서드로 OnMapTwoFingerTapListener를 지정하면 두 손가락 탭 이벤트를 받을 수 있습니다. 지도가 두 손가락 탭되면 onMapTwoFingerTap() 콜백 메서드가 호출되며, 두 손가락 탭된 두 지점의 중심에 해당하는 화면 좌표와 지도 좌표가 파라미터로 전달됩니다. onMapTwoFingerTap()true를 반환하도록 구현하면 이벤트가 소비되어 화면이 축소되지 않습니다.

다음은 지도를 두 손가락 탭했을 때 두 손가락 탭된 지점의 좌표를 토스트로 표시하고 이벤트를 소비해 화면이 축소되지 않도록 하는 예제입니다.

naverMap.setOnMapTwoFingerTapListener((point, coord) -> {
    Toast.makeText(this, coord.latitude + ", " + coord.longitude,
        Toast.LENGTH_SHORT).show();
    return true;
});

Java

naverMap.setOnMapTwoFingerTapListener((point, coord) -> {
    Toast.makeText(this, coord.latitude + ", " + coord.longitude,
        Toast.LENGTH_SHORT).show();
    return true;
});

Kotlin

naverMap.setOnMapTwoFingerTapListener { point, coord ->
    Toast.makeText(this, "${coord.latitude}, ${coord.longitude}",
            Toast.LENGTH_SHORT).show()
    true
}

results matching ""

    No results matching ""