지도 객체
하나의 지도는 뷰 요소와 인터페이스 요소로 구성됩니다. 뷰 요소는 화면에 지도를 나타내는 역할을 하며, MapFragment
와 MapView
가 여기에 해당합니다. 지도를 다루는 인터페이스 역할을 하는 인터페이스 요소는 NaverMap
클래스가 담당하며, 오버레이를 추가하고 상호작용하는 등 지도와 관련된 기능 대부분을 이 클래스에서 제공합니다. MapFragment
및 MapView
는 개발자가 직접 생성할 수 있으나 NaverMap
객체는 오직 콜백 메서드를 이용해서 얻어올 수 있습니다.
지도 표시
지도 화면은 프래그먼트 및 뷰로 제공됩니다. 이 중 한 가지를 레이아웃에 추가하면 화면에 지도가 나타납니다.
MapFragment
지도를 화면에 나타내는 방법 중 가장 권장되는 것은 MapFragment
를 사용하는 것입니다. MapFragment
는 androidx.fragment.app.Fragment
의 하위 클래스로, 여타 프래그먼트와 마찬가지로 레이아웃 XML 또는 FragmentTransaction
을 사용해 추가할 수 있습니다.
다음은 레이아웃 XML을 사용해 지도를 화면에 나타내는 예제입니다.
<androidx.fragment.app.FragmentContainerView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.naver.maps.map.MapFragment" />
다음은 FragmentTransaction
을 사용해 지도를 화면에 나타내는 예제입니다.
<FrameLayout
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
FragmentManager fm = getSupportFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = MapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
Java
FragmentManager fm = getSupportFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = MapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
Kotlin
val fm = supportFragmentManager
val mapFragment = fm.findFragmentById(R.id.map) as MapFragment?
?: MapFragment.newInstance().also {
fm.beginTransaction().add(R.id.map, it).commit()
}
MapFragment
를 다른 프래그먼트 내에 배치할 경우 supportFragmentManager
대신 childFragmentManager
를 사용해 MapFragment
를 자식 프래그먼트로 두어야 합니다.
다음은 MapFragment
를 다른 프래그먼트 내에 배치하는 예제입니다.
FragmentManager fm = getChildFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = MapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
Java
FragmentManager fm = getChildFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = MapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
Kotlin
val fm = childFragmentManager
val mapFragment = fm.findFragmentById(R.id.map) as MapFragment?
?: MapFragment.newInstance().also {
fm.beginTransaction().add(R.id.map, it).commit()
}
MapView
프래그먼트를 사용하지 않고 뷰를 바로 사용할 수도 있습니다. MapView
를 레이아웃에 추가하면 MapFragment
를 사용한 것과 마찬가지로 지도가 화면에 나타납니다.
다음은 레이아웃 XML에 MapView
를 추가해 지도를 화면에 나타내는 예제입니다.
<com.naver.maps.map.MapView
android:id="@+id/map_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
MapView
를 사용할 때는 반드시 MapView
가 포함된 액티비티의 라이프 사이클에 맞추어 onCreate()
, onStart()
, onResume()
, onPause()
, onStop()
, onDestroy()
, onSaveInstanceState()
, onLowMemory()
를 호출해야 합니다. 단, MapView
가 프래그먼트에 포함될 경우 프래그먼트의 onCreateView()
또는 onViewCreated()
에서 onCreate()
를, onDestroyView()
에서 onDestroy()
를 호출해야 합니다. 그렇지 않으면 지도가 정상적으로 동작하지 않습니다. MapFragment
를 사용하면 이러한 절차가 필요하지 않으므로 MapFragment
를 사용하는 것을 권장합니다.
다음은 프래그먼트에서 MapView
의 라이프 사이클 메서드를 호출하는 예제입니다.
public class MapViewFragment extends Fragment {
private MapView mapView;
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
// ...
}
@Override
public void onViewCreated(@NonNull View view,
@Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mapView = view.findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
}
@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 onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
public void onStop() {
super.onStop();
mapView.onStop();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
Java
public class MapViewFragment extends Fragment {
private MapView mapView;
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
// ...
}
@Override
public void onViewCreated(@NonNull View view,
@Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mapView = view.findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
}
@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 onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
public void onStop() {
super.onStop();
mapView.onStop();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
Kotlin
class MapViewFragment : Fragment() {
private lateinit var mapView: MapView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup,
savedInstanceState: Bundle): View {
// ...
}
override fun onViewCreated(view: View, @Nullable savedInstanceState: Bundle) {
super.onViewCreated(view, savedInstanceState)
mapView = view.findViewById(R.id.map_view)
mapView.onCreate(savedInstanceState)
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
override fun onDestroyView() {
super.onDestroyView()
mapView.onDestroy()
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
}
다음은 액티비티에서 MapView
의 라이프 사이클 메서드를 호출하는 예제입니다.
public class MapViewActivity extends Activity {
private MapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
mapView = findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
Java
public class MapViewActivity extends Activity {
private MapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
mapView = findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
Kotlin
class MapViewActivity : Activity() {
private lateinit var mapView: MapView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
mapView = findViewById(R.id.map_view)
mapView.onCreate(savedInstanceState)
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
}
NaverMap 객체 얻어오기
MapFragment
및 MapView
는 지도에 대한 뷰 역할만을 담당하므로 API를 호출하려면 인터페이스 역할을 하는 NaverMap
객체가 필요합니다. MapFragment
또는 MapView
의 getMapAsync()
메서드로 OnMapReadyCallback
을 등록하면 비동기로 NaverMap
객체를 얻을 수 있습니다. NaverMap
객체가 준비되면 onMapReady()
콜백 메서드가 호출됩니다.
다음은 OnMapReadyCallback
을 등록해 NaverMap
객체를 얻어오는 예제입니다.
public class MapFragmentActivity extends FragmentActivity
implements OnMapReadyCallback {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_fragment_activity);
FragmentManager fm = getSupportFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = MapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
mapFragment.getMapAsync(this);
}
@UiThread
@Override
public void onMapReady(@NonNull NaverMap naverMap) {
// ...
}
}
Java
public class MapFragmentActivity extends FragmentActivity
implements OnMapReadyCallback {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_fragment_activity);
FragmentManager fm = getSupportFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = MapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
mapFragment.getMapAsync(this);
}
@UiThread
@Override
public void onMapReady(@NonNull NaverMap naverMap) {
// ...
}
}
Kotlin
class MapFragmentActivity : FragmentActivity(), OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.map_fragment_activity)
val fm = supportFragmentManager
val mapFragment = fm.findFragmentById(R.id.map) as MapFragment?
?: MapFragment.newInstance().also {
fm.beginTransaction().add(R.id.map, it).commit()
}
mapFragment.getMapAsync(this)
}
@UiThread
override fun onMapReady(naverMap: NaverMap) {
// ...
}
}