onPanListener issues after sdk update from 10.1.1 to 10.2.3

2848
4
05-20-2014 05:55 AM
KeithTurner
New Contributor III
We were using postPointerUp to update a textview after the user panned, which is working good in our released app (still running 10.1.1 sdk).  Since that version, the only changes I've made was to update the sdk to 10.2.3, add the line to setClientID and changed several values that control whether the app is hitting our prod or development API server.  postPointerUp is no longer being called and prePointerUp is not being called reliably.  I've tried this on a physical device running android 2.3.3 and an emulator running android 4.3.  I stripped all of our code out of the onPanListener and replaced it with Log.d statements, which confirms that pre and post pointer move are getting called reliably, prepointerup is getting called sometime and postpointerup is never getting called.  I also stripped out our onSingleTapListener, which had no effect.

Here's our onstatuschangedlistener, where the onpanlistener is set:
  mMapView.setOnStatusChangedListener(new OnStatusChangedListener() {

   private static final long serialVersionUID = 1L;

   public void onStatusChanged(Object source, STATUS status) {
    
    if (source == mMapView && status == STATUS.INITIALIZED) {
     
     mMapView.setOnPanListener(new OnPanListener() {

      @Override
      public void postPointerMove(float arg0, float arg1, float arg2,
        float arg3) {
       Log.d("pointertest", "in postPointerMove");
      }

      @Override
      public void postPointerUp(float arg0, float arg1, float arg2,
        float arg3) {
       Log.d("pointertest", "in postPointerUp");

      }

      @Override
      public void prePointerMove(float arg0, float arg1, float arg2,
        float arg3) {
       Log.d("pointertest", "in prePointerMove");

      }

      @Override
      public void prePointerUp(float arg0, float arg1, float arg2,
        float arg3) {
       Log.d("pointertest", "in prePointerUp");

      }
     
     });

    }

   }
  });


When I test it, logcat shows alternating "in prepointerMove" and "in postpointermove" while I'm panning, and sometimes shows a "in prepointerup" when I stop panning, but I have yet to see a single "in postpointerup".

Any ideas whats going on?  The api reference for onpanlistener is pretty sparse and doesn't mention any new requirements.
0 Kudos
4 Replies
KeithTurner
New Contributor III
I have two different 'test' apps that behave the same way.  One was an existing test that I upgraded from a prior version of the sdk.  The other is a brand new project I just created by following the hello world tutorial.  In both cases, the app is about the minimum you can have to show a mapview, and the addition of an onpanlistener that writes to logcat on each of the four events.  They both behave like my app - pre/post pointer move appears to work as expected, prepointerup appears sometimes and I don't see any postpointerup.  See code below.


HelloWorldActivity.Java
package com.esri.arcgis.android.samples.helloworld;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;


import com.esri.android.map.MapView;
import com.esri.android.map.ags.ArcGISTiledMapServiceLayer;
import com.esri.android.map.event.OnPanListener;
import com.esri.android.map.event.OnStatusChangedListener;


public class HelloWorldActivity extends Activity {
 
 MapView mMapView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

  // Retrieve the map and initial extent from XML layout
  mMapView = (MapView)findViewById(R.id.map);
  // Add dynamic layer to MapView
  mMapView.addLayer(new ArcGISTiledMapServiceLayer("" +
  "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"));
  
  
  mMapView.setOnStatusChangedListener(new OnStatusChangedListener() {

   private static final long serialVersionUID = 1L;

   public void onStatusChanged(Object source, STATUS status) {
    
    if (source == mMapView && status == STATUS.INITIALIZED) {
     
     mMapView.setOnPanListener(new OnPanListener() {

    
      private static final long serialVersionUID = 1L;

      public void postPointerMove(float arg0, float arg1, float arg2,
        float arg3) {
       Log.d("pointertest", "in postPointerMove");
      }

      public void postPointerUp(float arg0, float arg1, float arg2,
        float arg3) {
       Log.d("pointertest", "in postPointerUp");

      }

      public void prePointerMove(float arg0, float arg1, float arg2,
        float arg3) {
       Log.d("pointertest", "in prePointerMove");

      }

      public void prePointerUp(float arg0, float arg1, float arg2,
        float arg3) {
       Log.d("pointertest", "in prePointerUp");

      }
     


     });

    }

   }
  });

    }

 @Override
 protected void onDestroy() {
  super.onDestroy();
 }
 @Override
 protected void onPause() {
  super.onPause();
  mMapView.pause();
 }
 @Override
 protected void onResume() {
  super.onResume();
  mMapView.unpause();
 }

}


And main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    tools:context=".HelloWorldActivity"
    >
<!-- MapView layout and initial extent -->
<com.esri.android.map.MapView
android:id="@+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
initExtent = "-1.3296373526814876E7 3930962.41823043 -1.2807176545789773E7 4201243.7502468005">
</com.esri.android.map.MapView>

</LinearLayout>


logcat output:
05-20 12:49:54.840: D/pointertest(1090): in prePointerMove
05-20 12:49:54.840: D/pointertest(1090): in postPointerMove
05-20 12:49:54.908: D/pointertest(1090): in prePointerMove
05-20 12:49:54.908: D/pointertest(1090): in postPointerMove
05-20 12:49:55.108: D/pointertest(1090): in prePointerMove
05-20 12:49:55.108: D/pointertest(1090): in postPointerMove
05-20 12:49:55.258: D/pointertest(1090): in prePointerMove
05-20 12:49:55.258: D/pointertest(1090): in postPointerMove
05-20 12:49:56.747: D/pointertest(1090): in prePointerMove
05-20 12:49:56.747: D/pointertest(1090): in postPointerMove
05-20 12:49:56.778: D/pointertest(1090): in prePointerMove
05-20 12:49:56.778: D/pointertest(1090): in postPointerMove
05-20 12:49:56.908: D/pointertest(1090): in prePointerMove
05-20 12:49:56.917: D/pointertest(1090): in postPointerMove
05-20 12:49:57.237: D/pointertest(1090): in prePointerMove
05-20 12:49:57.237: D/pointertest(1090): in postPointerMove
05-20 12:49:57.257: D/pointertest(1090): in prePointerMove
05-20 12:49:57.257: D/pointertest(1090): in postPointerMove
05-20 12:49:58.418: D/pointertest(1090): in prePointerMove
05-20 12:49:58.418: D/pointertest(1090): in postPointerMove
05-20 12:49:58.448: D/pointertest(1090): in prePointerMove
05-20 12:49:58.448: D/pointertest(1090): in postPointerMove
05-20 12:49:58.738: D/pointertest(1090): in prePointerMove
05-20 12:49:58.738: D/pointertest(1090): in postPointerMove
05-20 12:49:58.758: D/pointertest(1090): in prePointerUp
05-20 12:49:59.528: D/pointertest(1090): in prePointerMove
05-20 12:49:59.538: D/pointertest(1090): in postPointerMove
05-20 12:49:59.558: D/pointertest(1090): in prePointerMove
05-20 12:49:59.558: D/pointertest(1090): in postPointerMove
05-20 12:49:59.700: D/pointertest(1090): in prePointerMove
05-20 12:49:59.700: D/pointertest(1090): in postPointerMove
05-20 12:49:59.838: D/pointertest(1090): in prePointerMove
05-20 12:49:59.838: D/pointertest(1090): in postPointerMove
05-20 12:49:59.918: D/pointertest(1090): in prePointerMove
05-20 12:49:59.918: D/pointertest(1090): in postPointerMove
0 Kudos
ShellyGill1
Esri Contributor
Hi Keith,

I have reproduced this and found that this changed between 10.2 and 10.2.2 - in 10.2 I see both pre and post up move events, at 10.2.2 and 10.2.3 I don't get postPointerUp, but I do get prePointerUp when my pan action ends in a fling gesture (perhaps this explains why you sometimes saw this called and sometimes not). I will submit an issue about this change, although I cant say at this point when a fix may happen, I do know there has been a number of changes over the last few releases with gestures in the map. 

As a partial workaround, I have found that if I set a MapTouchListener in MapView.setOnTouchListener, I reliably get the ACTION_UP MotionEvent action called - this is called before the pan listener prePointerUp (when that happens). There is no equivalent to the postPointerUp in this listener though.

Hope this helps a bit,
0 Kudos
KeithTurner
New Contributor III
Hi Keith,

I have reproduced this and found that this changed between 10.2 and 10.2.2 - in 10.2 I see both pre and post up move events, at 10.2.2 and 10.2.3 I don't get postPointerUp, but I do get prePointerUp when my pan action ends in a fling gesture (perhaps this explains why you sometimes saw this called and sometimes not). I will submit an issue about this change, although I cant say at this point when a fix may happen, I do know there has been a number of changes over the last few releases with gestures in the map. 

As a partial workaround, I have found that if I set a MapTouchListener in MapView.setOnTouchListener, I reliably get the ACTION_UP MotionEvent action called - this is called before the pan listener prePointerUp (when that happens). There is no equivalent to the postPointerUp in this listener though.

Hope this helps a bit,


Ok, thanks for confirming its not just me.  We are/were using postpointerup to update a label based on the new extent of the map after a pan.  Is the workaround you suggested going to be our best option for being notified that the map extent changed?

Keith
0 Kudos
ShellyGill1
Esri Contributor
Hi Keith,

I think you may need a combination of things - you can use the MapOnTouchListener.onTouch and listen to ACTION_UP to cover normal panning, and also pinch-zooming, and rotating using a gesture (if you have that enabled). However, there's also the built-in gestures single-pointer-double-tap to zoom in, and double-finger-single-tap to zoom out, and these actions will animate the extent change after the tap event. Additionally, there's the fling gesture (mentioned in this other recent post - http://forums.arcgis.com/threads/109811-Best-way-to-figure-out-when-user-stops-panning), which also animates the map to it's eventual extent, after the gesture is done.

So I would go for a combination of updating the label after the ACTION_UP in onTouch, and then additionally at a period of time after MapOnTouchListener.onFling, onMultiPointersSingleTap, and onDoubleTap. I do not have a set time period that I know would work, but 1500 milliseconds has been used by others effectively. And then additionally if you change the map extent programmatically, bearing in mind again that map animations may be triggered by various methods (most methods that change map extent now default to using animation). We've worked to improve the documentation on what methods will be triggering animation by default, and this should be available in the next release, but hopefully before that too.

Sorry it's not a simpler answer, let me know if this helps, and if you find any other cases to consider.
0 Kudos