Android 기술 Q&A 
Q&A 게시판에 질문을 남기신 글에 대한 답변/덧글/쪽글에 대한 Push 메일 서비스를 받고자 하시는 분들은
☞ Push 메일 서비스 공지를 필독하시기 바랍니다.
"Hit" testing on a View(MapView)
작성자
작성일 2008-06-04 (수) 05:42
ㆍ추천: 0  ㆍ조회: 13915      
IP: 221.xxx.120
저도 요즘 MapView에 대한 작업을 좀 하고 있는데, 아래의 정보 참조하시면 도움이 될 것입니다.
 
아래의 소스는 오래 전에 어느 블로그에서 받아놓았던 sample인데 참조하세요.
소스코드는 m5-r15 용으로 제작된 것은 아니니까 대충 참조하시면 될 듯합니다.
기본 개념은, Overlay에서 onTap을 overriding하여서 click 이벤트를 제어하는 방법입니다.
 
 
출처 : http://blog.pocketjourney.com/
소스코드 : tutorial2.zip(107.2KB)
 

 

"Hit" testing on a View(MapView)

 
The following tutorial addresses how to perform ‘hit’ testing for user ‘clicks’ in a View. By hit testing, we mean the
ability to determine when a user’s selection of a specific Point in a View overlaps with a region that we are
monitoring for further action.
In other words at the end of this MapView tutorial, your users will be able to click on any icon that you draw onto
the map, and you’ll be able to take whatever action you like such as displaying a transparent popup window (as
we do in the tutorial).
Here’s what the final result will look like:
 
 
 
We’ll assume you already know how to add a MapView to a layout and create an Overlay and will jump right into
how to test whether a user selection ‘hit’ one of those mapped icons.
Our icons are rendered by an extension of Overlay we have named MapLocationOverlay which has 2 primary
methods called during an Overlay.draw(). We’ll go through each of these in detail:
drawMapLocations(canvas, calculator, shadow);
drawInfoWindow(canvas, calculator, shadow);

More important perhaps, we’ll discuss the following method which performs the hit testing of each user tap
on the screen.
isHitMapLocation(calculator,point);

Starting with locations on our MapView
 
We start by creating a class, MapLocation, to store our map location name, latitude, & longitude. Four instances
of MapLocation are created as shown in the screenshot of San Francisco above:
mapLocations = new ArrayList<MapLocation>();
mapLocations.add(new MapLocation(”North Beach”,37.799800872802734,-122.40699768066406));
mapLocations.add(new MapLocation(”China Town”,37.792598724365234,-122.40599822998047));
mapLocations.add(new MapLocation(”Fisherman’s Wharf”,37.8091011047,-122.416000366));
mapLocations.add(new MapLocation(”Financial District”,37.79410171508789,-122.4010009765625));

These map locations will be drawn to the MapView and used for testing user clicks.
 
Drawing Map Locations
 
Before we can test for users clicking our icon, we need to first learn how those icons are drawn to the screen.
Once you are comfortable setting the screen coordinates for drawing of your icon, it will be simple to test those
same coordinates for ‘hits’ (user clicks” on that icon).
Screen coordinates start at (0,0) in the upper-left and end at the bottom-right (screenWidth,screenHeight) of
our screen. To draw our location’s icon, we must first know how to translate from the latitude/longitude
coordinates of our map location to these x & y screen coordinates. Android provides this function for us via a
PixelCalculator which is passed in Overlay’s draw() method.
public void draw(Canvas canvas, PixelCalculator calculator, boolean shadow)
To use PixelCalculator, simply pass an int[2] to the calculator along with our location’s latitude/longitude as a
Point. The calculator does its magic and returns the screen coordinates of our map location.
int[] screenCoords = new int[2];
calculator.getPointXY(testLocation.getPoint(), screenCoords);

As we will be drawing a bitmap balloon icon to the screen, we must ensuring that the bottom middle of our icon
is directly on top of our location’s latitude & longitude screen coordinates (as shown in the image below). This
accurate positioning of our icon will be key to hit testing later on.
 
 

To draw the balloon icon then, we call drawBitmap() and ensure the top/left of our icon is properly offset.
canvas.drawBitmap(icon, screenCoords[0] - icon.width()/2, screenCoords[1] - icon.height(),null);
And that’s it, our icons is now properly drawn on the screen. Now we need to perform ‘hit’ tests for user
interaction with these icons.
 
Listening for Map Taps & Then Testing for ‘Hits’

User taps on the MapView are captured by overriding Overlay’s onTap() method and then testing for overlap
with our icons’ locations on the screen. If a hit occurs and new information popup displayed (or a prior
information popup removed), then we invalidate the map so Overlay.draw() is called.
@Override
public boolean onTap(DeviceType deviceType, Point p, PixelCalculator calculator) {
// Store whether prior popup was displayed so call invalidate() to remove it if necessary.
boolean isRemovePriorPopup = selectedMapLocation != null;
// Next test whether a new popup should be displayed
selectedMapLocation = getHitMapLocation(calculator,p);
if ( isRemovePriorPopup || selectedMapLocation != null) {
mapView.invalidate();
}
// Lastly return true if we handled this onTap()
return selectedMapLocation != null;
}
So here’s the real point of this tutorial…how do we match the screen coordinates that the user clicks to the
latitude & longitude of our icon on the map?
Just as we determined the location of our map for drawing on the screen, we will now create a Rectangle
to represent that drawn icon and use the Rectangle.contains() method to test whether the user’s MotionEvent
occurred within that Rectangle.
private MapLocation getHitMapLocation(PixelCalculator calculator, Point tapPoint) {
// Track which MapLocation was hit…if any
MapLocation hitMapLocation = null;
RectF hitTestRecr = new RectF();
int[] screenCoords = new int[2];
Iterator<MapLocation> iterator = mapView.getMapLocations().iterator();
while(iterator.hasNext()) {
MapLocation testLocation = iterator.next();
// As above, translate MapLocation lat/long to screen coordinates
calculator.getPointXY(testLocation.getPoint(), screenCoords);
// Use this information to create a ‘hit” testing Rectangle to represent the size
// of our location’s icon at the correct location on the screen.

// As we want the base of our balloon icon to be at the exact location of
//
our map location, we set our Rectangle’s location so the bottom-middle of
//
our icon is at the screen coordinates of our map location (shown above).
hitTestRecr.set(-bubbleIcon.width()/2,-bubbleIcon.height(),bubbleIcon.width()/2,0);
// Next, offset the Rectangle to location of our location’s icon on the screen.
hitTestRecr.offset(screenCoords[0],screenCoords[1]);
// Finally test for match between ‘hit’ Rectangle and location clicked by the user.
// If a hit occurred, then we stop processing and return the result;

calculator.getPointXY(tapPoint, screenCoords);
if (hitTestRecr.contains(screenCoords[0],screenCoords[1])) {
hitMapLocation = testLocation;
break;
}
}
return hitMapLocation;
}
And that’s it for hit testing. If a hit occurred in our Rectangle, we track the selected map location and render a
popup window above the map location’s icon with the name of the location.
 
Drawing a Popup Information Window
 
The following code for displaying a popup window may look complex, but the goal is simple - to set the correct
screen coordinates for the information window to display directly above & centered on our location’s icon.
private void drawInfoWindow(Canvas canvas, PixelCalculator calculator, boolean shadow) {
// Again get our screen coordinate
int[] selDestinationOffset = new int[2];
calculator.getPointXY(selectedMapLocation.getPoint(), selDestinationOffset);

// Setup the info window with the right size & location
int INFO_WINDOW_WIDTH = 125;
int INFO_WINDOW_HEIGHT = 25;
RectF infoWindowRect = new RectF(0,0,INFO_WINDOW_WIDTH,INFO_WINDOW_HEIGHT);
int infoWindowOffsetX = selDestinationOffset[0]-INFO_WINDOW_WIDTH/2;
int infoWindowOffsetY = selDestinationOffset[1]-INFO_WINDOW_HEIGHT-bubbleIcon.height();
infoWindowRect.offset(infoWindowOffsetX,infoWindowOffsetY);

// Draw inner info window
canvas.drawRoundRect(infoWindowRect, 5, 5, getInnerPaint());

// Draw border for info window
canvas.drawRoundRect(infoWindowRect, 5, 5, getBorderPaint());

// Draw the MapLocation’s name
int TEXT_OFFSET_X = 10;
int TEXT_OFFSET_Y = 15;
canvas.drawText(selectedMapLocation.getName(),infoWindowOffsetX+TEXT_OFFSET_X,infoWindowOffsetY+TEXT_OFFSET_Y,getTextPaint());

}
And that’s it. Please let me know of any points that need clarification or that I should expand/improve upon.
Here is the .apk you can use along with the source files:
 
Happy coding,
Anthony (Acopernicus)
이름아이콘 현국이다
2008-06-04 10:46
자료감사합니다 ^^
   
 
덧글 쓰기 0
3500
※ 회원등급 레벨 0 이상 읽기가 가능한 게시판입니다.
    N     분류     제목    글쓴이 작성일 조회
4953 안드로이드에 탑재된 프로그램 지우는 방법 좀 알려주세요... 2008-04-25 8985
4952 도와주세요~ 2008-05-05 8564
4951 에뮬의 system과 data를 추출할때.... 2008-05-06 8444
4950 커널 사이즈가 얼마정도 나오시나요? 2008-05-07 8472
4949 sd카드에서 데이터 가져오기에 대한 질문 2008-05-07 8685
4948 UI와 디자인에 대해서 궁금한 점이 있습니다. 2008-05-07 8239
4947 2.6.23을 zImage빌드를 하였습니다 2008-05-07 8347
4946 안드로이드에서 파일 다운로드에 관해 여쭤봅니다... 2008-05-13 9487
4945 UI이벤트 처리 질문. 2008-05-13 8353
4944 다이얼로그 허접하게 만들었습니다 참조하세요~.. 2008-05-14 8423
4943 혹시m5버전 멥에 오버레이 띄우는 방법 아시는분~.. 2008-05-15 8539
4942 Bitmap 사용하는 방법 아시는분 계신가요??? 2008-05-16 8668
4941 loop back 마운트에 대해서 2008-05-16 8412
4940 문자를 이용하려 하는데... 2008-05-19 8455
4939 안드로이드에서의 한글 지원은? 2008-05-19 10519
4938 안드로이드를 띠울때 2008-05-19 8476
4937 포팅 관련 질문입니다. 2008-05-19 8423
4936 포팅관련 framebuffer에 관하여.. 2008-05-19 11352
4935 service를 이용한 네트워크 접속, 어떤가요? 2008-05-20 8740
4934 Spinner관련해서요.ㅠ 2008-05-20 9433
4933 질문이 있습니다. 2008-05-20 8391
4932 Re.. 수정해서 다시 올려욤 2008-05-21 14151
4931 메시지박스띄우기 2008-05-21 10824
4930 multicast programming 2008-05-21 10439
4929 가장 먼저 실행되는 Activity 2008-05-23 9001
4928 Dialog View 에서 activity 로 Dialog의 종료된 상태를 넘겨주.. 2008-05-23 10554
4927 Bitmap형식의 이미지사이즈를 바꾸고 싶습니다... 2008-05-26 11568
4926 안드로이드 App. 메뉴에서 32번 글 VideoPlayer 2008-05-28 17745
4925 포팅시 binder 문제에 대하여.. 2008-05-30 12751
4924 파일첨부가 않되어 밑의글에 이어 추가해요~ 2008-05-31 8377
4923 localhost로도 접속이 안되는데 왜 그럴까요?? 2008-06-01 8516
4922 invain님께.. (리플에 대한 내용입니다) 2008-06-02 9158
4921 안드로이드에서 DataBase접근하는 방법에 대해서.... 2008-06-02 15260
4920 안드로이드 플랫폼상의 문자입력기 관련 질문.. 2008-06-03 8394
4919 안드로이드 플랫폼상의 문자입력기 관련 질문.. 2008-06-03 11307
4918 간만에 또 막히는 곳이 있어서 질문올립니다. 2008-06-03 8390
4917 "Hit" testing on a View(MapView) 2008-06-04 13915
4916 들풀님의 Safari 분석 자료에서 질문 있어요... 2008-06-04 8719
4915 invain님~ 두가지 질문이 있습니다` 2008-06-05 10131
4914 에뮬레이터 내장 폰북의 DB에 연동한 폰북에 사진등록 방법 질.. 2008-06-05 11317
4913 안드로이드 소스 상에서의 폰트 변경 2008-06-05 11256
4912 contact database에 photo 추가 관련 2008-06-06 11309
4911 Google IO: Android 50 Q&A 2008-06-06 8596
4910 다시 외부 DB 접근하는 것에 대해 여쭤봅니다. 2008-06-09 9694
4909 오류가 나는데 이유를 잘 몰르겠네요.-_-;; 2008-06-09 14138
4908 다이얼로그 질문이 있습니다. 2008-06-10 8449
4907 들풀님께 여쭈어봅니다 ^^ 2008-06-12 8390
4906 invain님께 의견을 듣고 싶습니다. 2008-06-14 8639
4905 폰에 그림이나 문자 표시하는법. 2008-06-16 8314
4904 맵 소스는 어디서 볼 수 있나요? 2008-06-17 8410
12345678910,,,101