Android 기술 Q&A 
Q&A 게시판에 질문을 남기신 글에 대한 답변/덧글/쪽글에 대한 Push 메일 서비스를 받고자 하시는 분들은
☞ Push 메일 서비스 공지를 필독하시기 바랍니다.
"Hit" testing on a View(MapView)
작성자
작성일 2008-06-04 (수) 05:42
ㆍ추천: 0  ㆍ조회: 14119      
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 9125
4952 도와주세요~ 2008-05-05 8678
4951 에뮬의 system과 data를 추출할때.... 2008-05-06 8576
4950 커널 사이즈가 얼마정도 나오시나요? 2008-05-07 8620
4949 sd카드에서 데이터 가져오기에 대한 질문 2008-05-07 8815
4948 UI와 디자인에 대해서 궁금한 점이 있습니다. 2008-05-07 8361
4947 2.6.23을 zImage빌드를 하였습니다 2008-05-07 8475
4946 안드로이드에서 파일 다운로드에 관해 여쭤봅니다... 2008-05-13 9602
4945 UI이벤트 처리 질문. 2008-05-13 8485
4944 다이얼로그 허접하게 만들었습니다 참조하세요~.. 2008-05-14 8557
4943 혹시m5버전 멥에 오버레이 띄우는 방법 아시는분~.. 2008-05-15 8665
4942 Bitmap 사용하는 방법 아시는분 계신가요??? 2008-05-16 8767
4941 loop back 마운트에 대해서 2008-05-16 8526
4940 문자를 이용하려 하는데... 2008-05-19 8591
4939 안드로이드에서의 한글 지원은? 2008-05-19 10637
4938 안드로이드를 띠울때 2008-05-19 8587
4937 포팅 관련 질문입니다. 2008-05-19 8557
4936 포팅관련 framebuffer에 관하여.. 2008-05-19 11459
4935 service를 이용한 네트워크 접속, 어떤가요? 2008-05-20 8863
4934 Spinner관련해서요.ㅠ 2008-05-20 9538
4933 질문이 있습니다. 2008-05-20 8551
4932 Re.. 수정해서 다시 올려욤 2008-05-21 14482
4931 메시지박스띄우기 2008-05-21 10955
4930 multicast programming 2008-05-21 10542
4929 가장 먼저 실행되는 Activity 2008-05-23 9145
4928 Dialog View 에서 activity 로 Dialog의 종료된 상태를 넘겨주.. 2008-05-23 10667
4927 Bitmap형식의 이미지사이즈를 바꾸고 싶습니다... 2008-05-26 11691
4926 안드로이드 App. 메뉴에서 32번 글 VideoPlayer 2008-05-28 17933
4925 포팅시 binder 문제에 대하여.. 2008-05-30 12925
4924 파일첨부가 않되어 밑의글에 이어 추가해요~ 2008-05-31 8502
4923 localhost로도 접속이 안되는데 왜 그럴까요?? 2008-06-01 8634
4922 invain님께.. (리플에 대한 내용입니다) 2008-06-02 9296
4921 안드로이드에서 DataBase접근하는 방법에 대해서.... 2008-06-02 15383
4920 안드로이드 플랫폼상의 문자입력기 관련 질문.. 2008-06-03 8518
4919 안드로이드 플랫폼상의 문자입력기 관련 질문.. 2008-06-03 11441
4918 간만에 또 막히는 곳이 있어서 질문올립니다. 2008-06-03 8529
4917 "Hit" testing on a View(MapView) 2008-06-04 14119
4916 들풀님의 Safari 분석 자료에서 질문 있어요... 2008-06-04 8836
4915 invain님~ 두가지 질문이 있습니다` 2008-06-05 10261
4914 에뮬레이터 내장 폰북의 DB에 연동한 폰북에 사진등록 방법 질.. 2008-06-05 11433
4913 안드로이드 소스 상에서의 폰트 변경 2008-06-05 11383
4912 contact database에 photo 추가 관련 2008-06-06 11419
4911 Google IO: Android 50 Q&A 2008-06-06 8735
4910 다시 외부 DB 접근하는 것에 대해 여쭤봅니다. 2008-06-09 9804
4909 오류가 나는데 이유를 잘 몰르겠네요.-_-;; 2008-06-09 14269
4908 다이얼로그 질문이 있습니다. 2008-06-10 8565
4907 들풀님께 여쭈어봅니다 ^^ 2008-06-12 8532
4906 invain님께 의견을 듣고 싶습니다. 2008-06-14 8774
4905 폰에 그림이나 문자 표시하는법. 2008-06-16 8453
4904 맵 소스는 어디서 볼 수 있나요? 2008-06-17 8572
12345678910,,,101