태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

구글맵 API 활용하기 - (3) 지도에 확대/축소 기능 추가하기

2009.11.12 03:45

강좌 작성환경
SDK Version : Android SDK 2.0, release 1
ADT Version : 0.9.4

추후 SDK업데이트로 인해 글의 내용과 최신 SDK 내용간 차이가 있을 수 있습니다.

* SDK 2.0 기준 업데이트 완료됨 : 2009/11/12

저번 강좌 이후로 공백이 좀 길었네요.
이래저래 제가 자유롭게(?) 글을 쓸 환경이 되질 않다보니 -_-... 이렇게 띄엄~띄엄 포스팅을 하게 되네요.
(물론 최근에 렌즈 구한다고 장터매복 했던 이유도 없지않게 있겠지만요, ㅎㅎ;;;)

긴 이야기는 이쯤에서 접어두고, 오늘은 저번에 예고했던 대로, 맵을 컨트롤하는 기능을 추가해보도록 하겠습니다.
맵을 컨트롤하려면, 깜찍이님 강좌에서처럼 할 수도 있지만, 저 방법은 제가 보는 책 (Professional Android Application Development)에 나와있는 방법인데다가, 제 실력이 딸려서인지는 몰라도 잘 이해가 가지 않아서, 메뉴 이용법 및 Toast 이용법까지 익힐 수 있도록 다른 방식으로 작성하는 법에 대해서 강좌를 진행하도록 하겠습니다.

일단, 메뉴를 이용해서 지도 확대/축소 버튼을 추가할 것입니다. 다음과 같이 말이죠.



사실, 메뉴 아이템(지도 확대, 축소 버튼)에 아이콘도 넣을 수 있지만, 이번 강좌에서는 사정상(...) 아이콘 넣는 것은 생략하고 지나가도록 하겠습니다.

일단, 메뉴부터 넣어보도록 하죠. 메뉴를 넣으려면 onCreateOptionsMenu()와 onOptionsItemSelected() 메소드를 오버라이드 해야 합니다. onCreateOptionsMenu()에서는 메뉴에 항목들을 추가해주고, onOptionsItemSelected()에서는 사용자가 실제로 메뉴 항목을 눌렀을 경우 처리할 작업을 입력해줍니다.

다음과 같이 onCreateOptionsMenu()메소드와 onOptionsItemSelected() 메소드를 추가합니다.
package com.androidhuman.HelloMaps;

import com.google.android.maps.MapActivity; // Activity가 아닌 MapActivity를 추가합니다.

import android.os.Bundle;
import android.view.Menu; // 메뉴를 사용하기 위해 import합니다.
import android.view.MenuItem; // 메뉴를 사용하기 위해 import 합니다.

public class HelloMaps extends MapActivity { // MapActivity를 상속합니다.
	 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
                
    }
        

@Override 
protected boolean isRouteDisplayed() { // MapActivity를 상속하면, 이 메소드를 추가해줘야 합니다.
	// TODO Auto-generated method stub
	return false;
}
public boolean onCreateOptionsMenu(Menu menu){
	super.onCreateOptionsMenu(menu);
	// 메뉴에 항목을 추가하려면 이 메소드에서 추가해줍니다. 	
	return true;
}

public boolean onOptionsItemSelected(MenuItem item){
	super.onOptionsItemSelected(item);
		
	return true;
}
onCreateOptionsMenu() 메소드 오버라이드하고, 이를 수정함으로써 메뉴를 눌렀을 때 나오는 항목들을 변경할 수 있으며, onOptionsItemSelected() 메소드를 오버라이드하고 수저암으로써 메뉴의 각 항목을 눌렀을 때 나오는 항목들을 변경할 수 있습니다.

그럼, 먼저 메뉴 항목을 추가해볼까요??

아까 오버라이드한 onCreateOptionsMenu() 메소드를 다음과 같이 수정합니다.

public boolean onCreateOptionsMenu(Menu menu){
	super.onCreateOptionsMenu(menu);
	MenuItem zoomin = menu.add(0, 1, Menu.NONE, "지도 확대"); // 메뉴에 항목 추가
	MenuItem zoonout = menu.add(0, 2, Menu.NONE, "지도 축소"); // 메뉴에 항목 추가
	
	return true;
}

메뉴의 항목을 추가해주기 위해서는 add()메소드를 사용하면 됩니다.

public abstract MenuItem add (int groupId, int itemId, int order, CharSequence titleRes)
- groupid : 메뉴 항목의 그룹을 지정합니다.
- itemId : 각 메뉴 항목의 고유의 번호입니다.
- order : 각 항목의 정렬 방식입니다.
- titleRes : 메뉴 항목의 이름입니다.


위의 과정까지 추가하고 프로젝트를 실행한 후, 메뉴를 눌러보면 위 스크린샷과 같이 메뉴가 뜨는 것을 볼 수 있습니다. 하지만, 아직까지는 메뉴를 눌러도 아무런 동작을 하지 않을 것입니다. 메뉴 항목을 누름에 따라 어떻게 반응할지 지정해 주지 않았기 때문이죠.

그럼, 이제부터 메뉴 항목에 따라 어떤 동작을 할 지 지정해 주도록 하겠습니다.

그 전에, 우리가 하고싶은 일이 지도의 확대/축소, 즉 MapView를 컨트롤하는 일이므로 MapView의 컨트롤러를 받아와야 합니다. MapView의 컨트롤러는 MapView 객체를 받아온 후, getController() 메소드를 통해 받아올 수 있습니다.

우리는 여기에서 지도의 확대/축소를 구현하고, 확대/축소 레벨이 최대에 도달했을 경우 사용자에게 이를 알려주는 기능까지 구현해보도록 합시다. 지도를 확대/ 축소하는 등 지도를 '컨트롤' 하려면 MapView의 컨트롤러를 받아야 하는데, 이를 위해 MapView에 id를 지정해주어야 합니다. 그래야 findViewById()를 통해 MapView 객체를 받아올 수 있게 되겠죠. 다음과 같이 MapView의 ID를 지정해주도록 합니다.

<com.google.android.maps.MapView
	android:id="@+id/mapview"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
        android:focusable="true" 
	android:clickable="true"
        android:apiKey="내 API KEY" />


MapView 객체과 그의 컨트롤러인 MapController를 사용하기 위해, 필요한 요소들을 import 하고 다음과 같이 코드를 수정합니다.

package com.androidhuman.HelloMaps;

import com.google.android.maps.MapActivity; // Activity가 아닌 MapActivity를 추가합니다.
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class HelloMaps extends MapActivity { // MapActivity를 상속합니다.
	MapView v; // MapView를 연결해줄 객체를 생성합니다.
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        v = (MapView)findViewById(R.id.mapview);
        
    }
        

@Override 
protected boolean isRouteDisplayed() { // MapActivity를 상속하면, 이 메소드를 추가해줘야 합니다.
	// TODO Auto-generated method stub
	return false;
}
public boolean onCreateOptionsMenu(Menu menu){
	super.onCreateOptionsMenu(menu);
	MenuItem zoomin = menu.add(0, 1, Menu.NONE, "지도 확대");
	MenuItem zoomout = menu.add(0, 2, Menu.NONE, "지도 축소");
	
	return true;
}

public boolean onOptionsItemSelected(MenuItem item){
	super.onOptionsItemSelected(item);
	MapController control = v.getController(); // 맵 컨트롤러를 받아옵니다.
	Context context = getApplicationContext(); // Toast를 띄우기 위해 Context를 받아옵니다.
	
	switch(item.getItemId()){
	case 1: // 지도 확대
		if(!control.zoomIn()){
			Toast toast = Toast.makeText(context, "최대 줌 레벨에 도달했습니다.", Toast.LENGTH_SHORT);
			toast.show(); // Toast를 표시
			break;
		}
		break;
	case 2: // 지도 축소
		if(!control.zoomOut()){
			Toast toast = Toast.makeText(context, "최소 줌 레벨에 도달했습니다.", Toast.LENGTH_SHORT);
			toast.show(); // Toast를 표시
			break;
		}
		
		
	}
	return true;
}

}


메뉴 항목을 선택했을 때, 이를 처리해주는 onOptionsItemSelected()메소드를 보시면, switch구문에 getId()메소드로 각 메뉴 항목의 id를 가지고 처리하는 것을 볼 수 있습니다. 때문에, 메뉴 항목을 추가할 때 이 id가 겹치지 안도록 하는 것이 중요합니다.

지도의 확대/축소는 각각 MapController 객체의 zoomIn(), zoomOut() 메소드를 사용합니다. 이 메소드들은 지도를 확대/축소하는 기능 뿐만 아니라 만약 더이상 확대/축소가 가능하지 않다면 false를 반환합니다. 따라서, 이러한 특성을 이용하여 확대/축소가 최대 레벨에 도달하였을 대 사용자에게 이를 알려주도록 작성하였습니다.



코드를 보면, 사용자에게 최대 / 최소 줌 레벨 여부를 알려주는 수단으로 Toast를 이용하였습니다.
Toast는 간단한 메시지 등을 사용자에게 전달할 때 많이 사용하는데요, 마치 그 특성이 토스터기에서 나오는 빵처럼 '톡' 튀어나오는것과 비슷합니다. ^^;;;

Toast에 관한 내용은 다음 강좌에서 다루도록 하겠습니다. :)
저작자 표시 비영리 변경 금지
신고

커니 위치 기반 서비스 사용하기/구글 지도 (Google Maps) , , , , , , , , ,

  1. 이전 댓글 더보기
  2. Blog Icon
    행인임

    v.setBuiltInZoomControls(true)
    이걸 사용해도 됩니다.

  3. Blog Icon
    아낙

    좋은 정보 잘보고 값니다 인증 때리고 나니 할만하네요 ㅋ

  4. Blog Icon
    어플

    현재 구글맵을 통해 간단한 어플을 제작중인데 처음이라 그런지 쉽지 않네요 하지만 커니님 책을 보면서 열심히 따라하고 있어서 다행히 over기능에 마커까지하게되었습니다.;; 여기서 질문을 드리고 싶습니다.
    구글맵스를 이용해서 GPS기능을 하게 할순 없을까요? 또한 탭을 이용해서 한 탭에는 구글맵스를 나타내고
    다른 탭에는 여러 부가적인 요소를 넣고 싶은데요 조언 부탁드립니다. 소스를 믹스해야하니 머리가 아픕니다ㅠ

  5. GPS를 이용한다는 것이 정확히 어떤 것을 의미하는건가요?? 단순히 자신의 위치만 표시하는건 간단합니다.

    그리고 탭은... 일반적으로 탭 구성하는 것과 별다를 것이 없습니다. 대신, 뷰가 아닌 액티비티로 탭을 구성하는 것이라면 탭의 내용을 설정하는 부분에 해당 액티비티를 타겟으로 하는 인텐트를 넣어주면 됩니다.

  6. Blog Icon
    어플

    아 일단은 차량용 네비게이션과 마찬가지로 구성하고싶은데요 아무래도 자신의 위치를 계속적으로 나타내고 싶거든요

  7. GPS 값을 받아오면 위도와 경도를 알 수 있고, 마커를 사용하실 줄 아신다면 이미 필요한 것 대부분을 알고 계시는 상태입니다.

    경로를 그리는 것이 필요하다면 ApiDemos의 Path 그리는 부분을 한번 참고해보시면 되겠습니다.

  8. Blog Icon
    퍼버

    저도 어플님과 비슷한 것을 구현시키고 싶은데요...
    마커까지 띄우는 것은 책을 보고 실행시켜보았습니다.
    하지만 제가 하고 싶은 것은 지정된 곳에 마커를 띄우는것이 아니라
    제 위치에 마커를 띄우는것인데요 어떻게 하는건지 알고싶습니다.

  9. 책의 7.5.4절을 보시면 관련 내용이 소개되어있습니다 :)

  10. Blog Icon
    퍼버

    책의 7.5.4절이 오버레이 사용과 이벤트 처리부분 아닌가요?
    책 대로 하면 마커가 구글회사에 위치하는것만 나오는 것뿐인데,
    제가 하고 싶은건 제 위치에 마커를 띄우는것을 하고 싶습니다.
    혹시 onCreate()메서드에 addOverLayItem(숫자, 숫자, "글","글";);
    이 부분에서 숫자부분에 자신의 경도와 위도를 넣는 방법을 사용해야 하는건지 또 어떻게 넣는건지 알고싶습니다.
    같은 질문을 여러번 한 점 죄송하게 생각하고 있습니다.
    하지만 정말 구현시키고 싶어서 이렇게 염치불구하고 또 질문 남깁니다.

  11. 7.5.4절에 MyLocationOverlay를 사용하시면 자신의 위치를 마커로 쉽게 표시할 수 있습니다.

  12. Blog Icon
    퍼버

    쉽게 어떻게 표시할 수 있다는건지 알고 싶습니다.
    IinitItemizedOverlay() 함수를 쓰지 않고 MyLocationOverlay만 써서 하는건지...
    아무리 책과 같이 표현을 해도 제 위치는 나오지 않고
    처음에 지정해 놓은 구글회사에만 마크가 띄네요. 그 위도와 경도의 숫자를 바꿔서 제가 있는 위도와 경도로 써넣으면 그때는 제 위에 마크가 있지만 제가 움직이는 걸 알 수가 없잖습니까.. 어떻게 하는지 조금만 더 자세히 알려주시길 바랍니다.

  13. 테스트 단말이 어떤 것인지요?

    에물레이터라면 DDMS를 사용해서 에뮬레이터에 가상의 위치를 설정해주어야합니다. (265~266페이지 참조)

    실제 단말기라면 위치정보를 가지고오는데 시간이 걸릴 수 있구요. 예제 그대로만 한다면 구글 본사 위치를 표시하는 ItemizedOverlay와 MyLocationOverlay 두개가 모두 표시되며, 단말기상 위치가 설정되어있지 않다면 당연히 위치정보와 상관없이 표시되는 ItemizedIverlay만 표시됩니다.

    그리고, 굳이 MyLocationOverlay를 쓰지 않더라도 ItemizedOverlay를 커스터마이즈하면 내 위치를 계속 표시하도록 충분히 구현할 수 있습니다.

    그리고, 가급적이면 공식 개발자 문서나 다른 문서, 참고자료를 조금 더 찾아보고 원하는 것을 구현하기 위해 필요한 것들을 스스로 검토해보기를 권합니다.

  14. Blog Icon
    학생

    ZoomControllor 를 이용해서 예를 들면 지도 줌의 상태가10배확대이상 일때와 10배확대 이하 일때 현제위치 아이콘을 다르게 하고싶을땐 어떻게 해야되나요??

  15. Blog Icon
    와기

    귀중한 정보 공유해주셔서 감사합니다. 막히는부분이 있어서 질문드릴게요.
    v = (MapView)findViewById(R.id.mapview); 이부분에 에러가 뜨는데
    android:id="@+id/mapv" 이부분을 mainxml에 추가하면 된다고 윗댓글에 적혀있더군요.
    이건 어느부분에 추가해야 되는건가요?

  16. 레이아웃 내 MapView항목 attribute로 추가해주면 됩니다~

  17. Blog Icon
    와기

    <com.google.android.maps.MapView
    android:id="@+id/map_view"
    android:id="@+id/mapv" <=에러
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:enabled="true"
    android:clickable="true"
    android:apiKey="0zmvUmIPNASYa_3mTZDRUuP-KQEktriNeXNpjPw"
    />

  18. Blog Icon
    와기

    이렇게 되는데 어디에다가 android:id="@+id/mapv"를 넣어야되죠?
    이것저것 나름대로 해봤지만 안되네요. 자세히 가르쳐주시면 안될까요? ^^;

  19. Blog Icon
    와기

    참 layout에서 mapview는 선언해 줬어요.
    그리고 맵뷰안에 android:id="@+id/mapv" 를 선언해 주니까 에러떠서
    android:id="@+id/mapv" 만 따로 선언해보기도 했는데
    v = (MapView)findViewById(R.id.mapview); 이부분에 여전히 에러가 뜨네요.
    도와주세요~

  20. 레이아웃 내 mapview의 id를 map_view 혹은 mapv 둘 중 하나로 지정하셔야합니다. id가 두개일수는 없죠.

    코드에서 레이아웃을 참조할 떄도 당연히 바뀐 레이아웃 id에 따라 적절히 id를 바꿔주셔야 합니다.

  21. Blog Icon
    와기

    v = (MapView)findViewById(R.id.mapview); 이부분에서
    (mpaview)를 (map_view)로 바꾸니까 되네요.
    id를 통일시켯더니 되네요. 답변갑사합니다.

  22. Blog Icon
    구글

    저는요 왜 우리지도가 안보이고 다른 지도만 보이죠?

  23. 다른 국가의 지도만 보인다는 말씀이신가요?

  24. Blog Icon
    더레드

    맵은 보이는데 메뉴가 보이지 않네요.. 강좌에서 생략한게 있는건지 모르겠지만 맵만 보여요
    저 완전 초보티!!!를 냈네요...
    메뉴 이제야 보는방법을 알았어요.. 에뮬레이터 오른쪽에 메뉴키를 누르니까 보이네요.. 그런데 한번 클릭하면 메뉴가 사라져서 다시 메뉴 보이게 하고 줌인 하니까 상당히 번거럽네요.. 이런것은 항상 보이게 할수 있는 방법이 없을까요?

  25. MapView.setBuiltInZoomControls(true)로 지도 위에 줌 버튼을 표시하게 할 수 도 있습니다~

  26. Blog Icon
    송남용

    커니님 커니의 안드로이드 따라하기 책에는 예제 소스 CD가 들어 있나요 ?!
    그리고 구글 길안내 API 사용법도 나와 있나요?

  27. 길안내 API는 별도의 API로 여기에서는 다루지 않습니다.
    소스코드는 다운로드 형태로 블로그를 통해 제공되며, 이번에 출간 예정인 2판은 SVN을 통해 제공됩니다.

  28. Blog Icon
    송남용

    위의 프로젝트를 똑같이 따라해서 지도를 확대 축소 하는것 까지 성공 했는데
    이클립스을 닫았다가 다시 여니까 전부 에러가,., 메소드가 다 에러로 바뀌는데 이럴떼 어떻게 해야하나요

  29. Blog Icon
    송남용

    커니님 처음에 이어플 띄우면 세계지도가 나오는데

    특정 (울산, 서울 시청) 좌표를 확보해서 줌인 레벨을 설정해서 맵으로 보여주는 방법좀 가르쳐주세요

  30. API 문서를 참조하세요.
    http://code.google.com/intl/ko/android/add-ons/google-apis/reference/index.html

  31. Blog Icon
    고윤성

    강의 항상 잘 보고 있습니다^^
    다름이 아니라 이번에 구글 v2 가 나와서 커니님이 올려주신 걸 보고 해서 됬는데요,
    그 걸로 MapController 를 쓰려고 하니깐 import 를 시키려고 보니 MapController 가 없어서요...
    구글맵 api v2 에서는 맵을 조작할 때 보통 어떤 방식을 사용하는 지 궁금합니다.

  32. GoogleMap 클래스를 그대로 사용하시면 됩니다.
    http://developer.android.com/reference/com/google/android/gms/maps/GoogleMap.html

    카메라 조작 메서드로 animateCamera(), moveCamera() 등이 있으며, 맵타일 종류 설정, 현재위치 표시여부 설정 등 다양한 항목을 조작할 수 있습니다.

  33. 좋은글 출처를 표시하고 블로그에 담아갑니다. ^^