Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This works with your MapActivity and will allow you to:</p> <ol> <li>Set your own time threshold for what constitutes a long press on the map (0.8 seconds is good for me). </li> <li>Not interpret a scroll, multi-touch, or non-multi-touch event as a long press. It also let's you set a tolerance for someone's finger to ever so slightly move on the screen as they are holding down a long press. </li> </ol> <hr> <p>This solution is based on <a href="http://www.kind-kristiansen.no/2011/android-handling-longpresslongclick-on-map-revisited/" rel="nofollow">Roger Kristiansen's solution</a>. I added x and y point detection so that scrolling is not seen as a long press. This solution is not as elegant as Roger's because I use class variables and put the code in my existing MapActivity instead of extending MapView and creating a listener like he did. But if you want to stick with his code but have better non-multi-touch support, just take the x and y point stuff out of mine and add it to his.</p> <hr> <p>Class variables set at the top of my MapActivity:</p> <pre><code>//variable for determining long press and then automatically adding a pin to the map private int minMillisecondThresholdForLongClick = 800; private long startTimeForLongClick = 0; private float xScreenCoordinateForLongClick; private float yScreenCoordinateForLongClick; private float xtolerance=10;//x pixels that your finger can be off but still constitute a long press private float ytolerance=10;//y pixels that your finger can be off but still constitute a long press private float xlow; //actual screen coordinate when you subtract the tolerance private float xhigh; //actual screen coordinate when you add the tolerance private float ylow; //actual screen coordinate when you subtract the tolerance private float yhigh; //actual screen coordinate when you add the tolerance </code></pre> <p>Add this function in your MapActivity:</p> <pre><code> @Override public boolean dispatchTouchEvent(MotionEvent ev) { /* We want to capture the place the user long pressed on the map and add a marker (pin) on the map at that lat/long. * This solution: * 1. Allows you to set the time threshold for what constitutes a long press * 2. Doesn't get fooled by scrolling, multi-touch, or non-multi-touch events * Thank you Roger Kind Kristiansen for the main idea */ //get the action from the MotionEvent: down, move, or up int actionType = ev.getAction(); if (actionType == MotionEvent.ACTION_DOWN) { //user pressed the button down so let's initialize the main variables that we care about: // later on when the "Action Up" event fires, the "DownTime" should match the "startTimeForLongClick" that we set here // the coordinate on the screen should not change much during the long press startTimeForLongClick=ev.getEventTime(); xScreenCoordinateForLongClick=ev.getX(); yScreenCoordinateForLongClick=ev.getY(); } else if (actionType == MotionEvent.ACTION_MOVE) { //For non-long press actions, the move action can happen a lot between ACTION_DOWN and ACTION_UP if (ev.getPointerCount()&gt;1) { //easiest way to detect a multi-touch even is if the pointer count is greater than 1 //next thing to look at is if the x and y coordinates of the person's finger change. startTimeForLongClick=0; //instead of a timer, just reset this class variable and in our ACTION_UP event, the DownTime value will not match and so we can reset. } else { //I know that I am getting to the same action as above, startTimeForLongClick=0, but I want the processor //to quickly skip over this step if it detects the pointer count &gt; 1 above float xmove = ev.getX(); //where is their finger now? float ymove = ev.getY(); //these next four values allow you set a tiny box around their finger in case //they don't perfectly keep their finger still on a long click. xlow = xScreenCoordinateForLongClick - xtolerance; xhigh= xScreenCoordinateForLongClick + xtolerance; ylow = yScreenCoordinateForLongClick - ytolerance; yhigh= yScreenCoordinateForLongClick + ytolerance; if ((xmove&lt;xlow || xmove&gt; xhigh) || (ymove&lt;ylow || ymove&gt; yhigh)){ //out of the range of an acceptable long press, reset the whole process startTimeForLongClick=0; } } } else if (actionType == MotionEvent.ACTION_UP) { //determine if this was a long click: long eventTime = ev.getEventTime(); long downTime = ev.getDownTime(); //this value will match the startTimeForLongClick variable as long as we didn't reset the startTimeForLongClick variable because we detected nonsense that invalidated a long press in the ACTION_MOVE block //make sure the start time for the original "down event" is the same as this event's "downTime" if (startTimeForLongClick==downTime){ //see if the event time minus the start time is within the threshold if ((eventTime-startTimeForLongClick)&gt;minMillisecondThresholdForLongClick){ //make sure we are at the same spot where we started the long click float xup = ev.getX(); float yup = ev.getY(); //I don't want the overhead of a function call: xlow = xScreenCoordinateForLongClick - xtolerance; xhigh= xScreenCoordinateForLongClick + xtolerance; ylow = yScreenCoordinateForLongClick - ytolerance; yhigh= yScreenCoordinateForLongClick + ytolerance; if ((xup&gt;xlow &amp;&amp; xup&lt;xhigh) &amp;&amp; (yup&gt;ylow &amp;&amp; yup&lt;yhigh)){ //**** safe to process your code for an actual long press **** //comment out these next rows after you confirm in logcat that the long press works long totaltime=eventTime-startTimeForLongClick; String strtotaltime=Long.toString(totaltime); Log.d("long press detected: ", strtotaltime); /* //Now get the latitude/longitude of where you clicked. Replace all the code below if you already know how to translate a screen coordinate to lat/long. I know it works though. //***************** //I have my map under a tab so I have to account for the tab height and the notification bar at the top of the phone. // Maybe there are other ways so just ignore this if you already know how to get the lat/long of the pixels that were pressed. int TabHeightAdjustmentPixels=tabHost.getTabWidget().getChildAt(0).getLayoutParams().height; int EntireTabViewHeight = tabHost.getHeight(); Display display = getWindowManager().getDefaultDisplay(); int EntireScreenHeight = display.getHeight(); int NotificationBarHeight=EntireScreenHeight-EntireTabViewHeight; //the projection is mapping pixels to where you touch on the screen. Projection proj = mapView.getProjection(); GeoPoint loc = proj.fromPixels((int)(ev.getX(ev.getPointerCount()-1)), (int)(ev.getY(ev.getPointerCount()-1)-TabHeightAdjustmentPixels-NotificationBarHeight)); int longitude=loc.getLongitudeE6(); int latitude=loc.getLatitudeE6(); //***************** //**** here's where you add code to: // put a marker on the map, save the point to your SQLite database, etc */ } } } } return super.dispatchTouchEvent(ev); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload