<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Best Android apps - Androidapps.org - Your source for technology news &#187; hit testing for user clicks in view</title>
	<atom:link href="http://www.androidapps.org/tag/hit-testing-for-user-clicks-in-view/feed" rel="self" type="application/rss+xml" />
	<link>http://www.androidapps.org</link>
	<description>Android apps and Tech News</description>
	<lastBuildDate>Fri, 03 Feb 2012 20:42:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>“Hit” testing on a View (MapView)</title>
		<link>http://www.androidapps.org/%e2%80%9chit%e2%80%9d-testing-on-a-view-mapview</link>
		<comments>http://www.androidapps.org/%e2%80%9chit%e2%80%9d-testing-on-a-view-mapview#comments</comments>
		<pubDate>Sun, 27 Apr 2008 00:56:27 +0000</pubDate>
		<dc:creator>Admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[hit testing for user clicks in view]]></category>

		<guid isPermaLink="false">http://www.androidapps.org/?p=173</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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.</p>
<p>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).</p>
<p>Here’s what the final result will look like:</p>
<p><img src="http://pocketjourney.files.wordpress.com/2008/03/tutorial-2-final-view.gif" alt="Screenshot of Tutorial 2 results" /></p>
<p>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.</p>
<p>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:</p>
<blockquote><p><em>drawMapLocations(canvas, mapView, shadow);<br />
drawInfoWindow(canvas, </em><em>mapView</em><em>, shadow);</em></p></blockquote>
<p>More important perhaps, we’ll discuss the following method which performs the hit testing of each user tap on the screen.</p>
<blockquote><p><em>isHitMapLocation(mapView,point);<br />
</em></p></blockquote>
<p><strong>Starting with locations on our MapView</strong></p>
<p>We start by creating a class, MapLocation, to store our map location name, latitude, &amp; longitude. Four instances of MapLocation are created as shown in the screenshot of San Francisco above:</p>
<blockquote><p><em>mapLocations = new ArrayList&lt;MapLocation&gt;();<br />
mapLocations.add(new MapLocation(”North Beach”,37.799800872802734,-122.40699768066406));<br />
mapLocations.add(new MapLocation(”China Town”,37.792598724365234,-122.40599822998047));<br />
mapLocations.add(new MapLocation(”Fisherman’s Wharf”,37.8091011047,-122.416000366));<br />
mapLocations.add(new MapLocation(”Financial District”,37.79410171508789,-122.4010009765625));</em></p></blockquote>
<p>These map locations will be drawn to the MapView and used for testing user clicks.</p>
<p><strong>Drawing Map Locations</strong></p>
<p>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).</p>
<p>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 &amp; y screen coordinates. Android provides this function for us via the Projection class which is available from the MapView passed in Overlay’s draw() method: MapView.getProjection()</p>
<blockquote><p><em>public void draw(Canvas canvas, MapView mapView, boolean shadow)</em></p></blockquote>
<p>To use Projection, simply pass an int[2] to Projection along with our location’s latitude/longitude as a Point. The projection does its magic and returns the screen coordinates of our map location.</p>
<blockquote><p><em>int[] screenCoords = new int[2];<br />
mapView.getProjection().getPointXY(testLocation.getPoint(), screenCoords);</em></p></blockquote>
<p>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 &amp; longitude screen coordinates (as shown in the image below). This accurate positioning of our icon will be key to hit testing later on.</p>
<blockquote><p><a title="Screen coordinates of icon" href="http://pocketjourney.files.wordpress.com/2008/03/screen-coordinates-of-icon.gif"><img src="http://pocketjourney.files.wordpress.com/2008/03/screen-coordinates-of-icon.gif" alt="Screen coordinates of icon" /></a></p></blockquote>
<p>To draw the balloon icon then, we call drawBitmap() and ensure the top/left of our icon is properly offset.</p>
<blockquote><p><em>canvas.drawBitmap(icon, screenCoords[0] – icon.width()/2, screenCoords[1] – icon.height(),null);</em></p></blockquote>
<p>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.</p>
<p><strong>Listening for Map Taps &amp; Then Testing for ‘Hits’<br />
</strong></p>
<p>User taps on the MapView are captured by overriding Overlay’s onTouchEvent() 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.</p>
<blockquote><p>@Override<br />
public boolean onTouchEvent(MotionEvent event, MapView mapView) {</p>
<blockquote><p><span style="color: #008000;">// Store whether prior popup was displayed so call invalidate() to remove it if necessary.</span><br />
boolean isRemovePriorPopup = selectedMapLocation != null;</p>
<p><span style="color: #008000;">// Next test whether a new popup should be displayed</span><br />
selectedMapLocation = getHitMapLocation(mapView,event);<br />
if ( isRemovePriorPopup || selectedMapLocation != null) {</p>
<blockquote><p>mapView.invalidate();</p></blockquote>
<p>}</p>
<p><span style="color: #008000;">// Lastly return true if we handled this onTap()</span><br />
return selectedMapLocation != null;</p></blockquote>
<p>}</p></blockquote>
<p>So here’s the real point of this tutorial…how do we match the screen coordinates that the user clicks to the latitude &amp; longitude of our icon on the map?</p>
<p>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.</p>
<blockquote><p>private MapLocation getHitMapLocation(MapView mapView, MotionEvent    event) {</p>
<blockquote><p><span style="color: #008000;">// Track which MapLocation was hit…if any</span><br />
MapLocation hitMapLocation = null;</p>
<p>RectF hitTestRecr = new RectF();<br />
int[] screenCoords = new int[2];<br />
Iterator&lt;MapLocation&gt; iterator = mapView.getMapLocations().iterator();<br />
while(iterator.hasNext()) {</p>
<blockquote><p>MapLocation testLocation = iterator.next();</p>
<p><span style="color: #008000;">// As above, translate MapLocation lat/long to screen coordinates</span><br />
mapView.getProjection().getPointXY(testLocation.getPoint(), screenCoords);</p>
<p><em><span style="color: #008000;">// Use this information to create a ‘hit” testing Rectangle to represent the size<br />
// of our location’s icon at the correct location on the screen. </span><br />
<span style="color: #008000;">// As we want the base of our balloon icon to be at the exact location of<br />
// </span></em><em><span style="color: #008000;">our map location, </span></em><em><span style="color: #008000;">we set our Rectangle’s location so the bottom-middle of<br />
// </span></em><em><span style="color: #008000;">our icon is at </span></em><em><span style="color: #008000;">the screen coordinates of our map location (shown above).<br />
</span></em>hitTestRecr.set(-bubbleIcon.width()/2,-bubbleIcon.height(),bubbleIcon.width()/2,0);</p></blockquote>
<blockquote><p><em><span style="color: #008000;">// Next, offset the Rectangle to location of our location’s icon on the screen.</span></em><br />
hitTestRecr.offset(screenCoords[0],screenCoords[1]);</p>
<p><span style="color: #008000;">// Finally test for match between ‘hit’ Rectangle and location clicked by the user.<br />
// If a hit occurred, then we stop processing and return the result;</span><br />
if (hitTestRecr.contains(event.getX(),event.getY()) {</p></blockquote>
<blockquote>
<blockquote><p>hitMapLocation = testLocation;<br />
break;</p></blockquote>
<p>}</p></blockquote>
</blockquote>
<blockquote><p>}</p></blockquote>
<blockquote><p>return hitMapLocation;</p></blockquote>
</blockquote>
<blockquote><p>}</p></blockquote>
<p>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.</p>
<p><strong>Drawing a Popup Information Window</strong></p>
<p>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 &amp; centered on our location’s icon.</p>
<blockquote><p><em>private void drawInfoWindow(Canvas canvas, MapView mapView, boolean shadow) { </em></p></blockquote>
<blockquote>
<blockquote><p><em><span style="color: #008000;">// Again get our screen coordinate</span><br />
int[] selDestinationOffset = new int[2];<br />
mapView.getProjection().getPointXY(selectedMapLocation.getPoint(), selDestinationOffset);</em></p>
<p><em><span style="color: #008000;">// Setup the info window with the right size &amp; location</span><br />
int INFO_WINDOW_WIDTH = 125;<br />
int INFO_WINDOW_HEIGHT = 25;<br />
RectF infoWindowRect = new RectF(0,0,INFO_WINDOW_WIDTH,INFO_WINDOW_HEIGHT);<br />
int infoWindowOffsetX = selDestinationOffset[0]-INFO_WINDOW_WIDTH/2;<br />
int infoWindowOffsetY = selDestinationOffset[1]-INFO_WINDOW_HEIGHT-bubbleIcon.height();<br />
infoWindowRect.offset(infoWindowOffsetX,infoWindowOffsetY);</em></p>
<p><em><span style="color: #008000;">// Draw inner info window</span><br />
canvas.drawRoundRect(infoWindowRect, 5, 5, getInnerPaint());</em></p>
<p><em><span style="color: #008000;">// Draw border for info window</span><br />
canvas.drawRoundRect(infoWindowRect, 5, 5, getBorderPaint());</em></p>
<p><em><span style="color: #008000;">// Draw the MapLocation’s name</span><br />
int TEXT_OFFSET_X = 10;<br />
int TEXT_OFFSET_Y = 15;<br />
canvas.drawText(selectedMapLocation.getName(),infoWindowOffsetX+TEXT_OFFSET_X,infoWindowOffsetY+TEXT_OFFSET_Y,getTextPaint());</em></p></blockquote>
<p>}</p></blockquote>
<p>And that’s it. Please let me know of any points that need clarification or that I should expand/improve upon.</p>
<p>Here is the .apk you can use along with the source files: <a href="http://www.pocketjourney.com/downloads/pj/tutorials/tutorial2.zip">tutorial2.zip</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.androidapps.org/%e2%80%9chit%e2%80%9d-testing-on-a-view-mapview/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

