Move a point of ArcGISFeatureLayer with onDragPointerMove

2965
4
06-22-2013 05:16 PM
GakuminKato
New Contributor III
Hi all,

I have been having a hard time to implement drag and drop a point of ArcGISFeatureLayer for a couple days...
I am using these listeners: onDragPointerMove and onDragPointerUp.

Ultimately, what I would like to do is,
1. grab a point from selected ArcGISFeatureLayer
2. move it with "drag and drop", which is intuitive way
3. update the location of the point with "applyEdits(...)"
(Therefore, suggestions on completely different approaches are also more than appreciated)

There are two issues I would like the forum to help me out.

Problem 1: My code works in emulator. But it does NOT on an actual device...
But, once I run a code in debugging mode line by line, then it works on my actual device... This means there might be some issues related to processing time or network communication time?

Problem 2: Once the program does not detect any point to move, I would like to overwrite listener to default, which is pan of map.
I defined that by "setDefaultTouchListener" in my code.
Current my program stays stuck in drag and drop listener forever after it failed to grab a point to move...

Here is my code.
//This method is called when "Move" button is clicked 
 public void movepoint_OnClick(View v) {
  if (!mMapView.isLoaded()) {
   return;
  }

  Toast t = Toast.makeText(getApplicationContext(),
    "Drag a point to move",
    Toast.LENGTH_LONG);
  t.show();
  
  //Start drag listener to move a point
  myTouchListener = new MyTouchListener(this, mMapView);
  mMapView.setOnTouchListener(myTouchListener);
  
 }
 // Set drag listener
 // onDragPointerMove on map causes movement of a point
 public class MyTouchListener extends MapOnTouchListener {
  
  private SimpleMarkerSymbol _simpleMarkerSymbol;
  private Point startPoint = null;
  private Point endpoint = null;
  private Proximity2DResult targetPoint_2DResult = null;
  private Point targetPoint = null;
  private HashMap<String, Object> attributes = new HashMap<String, Object>();
  private int[] number;
  private Graphic gr;

  public MyTouchListener(Context context, MapView view) {
   super(context, view);
   // TODO Auto-generated constructor stub
   _simpleMarkerSymbol = new SimpleMarkerSymbol(Color.RED, 4, STYLE.CIRCLE);
   
  }
  
  /**
   * Clears all drawing graphics.
   */
  public void clearDrawGraphicsLayer(){
   graphicsLayer.removeAll();
  }
  
  public boolean onDragPointerMove(MotionEvent from, MotionEvent to) {
     
   endpoint = mMapView.toMapPoint(to.getX(), to.getY());
   startPoint = mMapView.toMapPoint(from.getX(), from.getY());  
   number = featureLayer.getGraphicIDs(from.getX(), from.getY(), 20);

///////Currently, every time I tried to grab a point with "featureLayer.getGraphicIDs(from.getX(), from.getY(), 20)" above,
///////then the program goes to "number.length == 0" and show the toast, and stuck there forever...
///////
   
   if (number.length == 0){
    Toast.makeText(getApplicationContext(), "Please grab a point. Click 'Move' again for retry", Toast.LENGTH_SHORT).show();   
    return true;
    
   }
   
   if (number.length > 0){
    gr = featureLayer.getGraphic(number[0]);
    attributes = (HashMap<String, Object>) gr.getAttributes();
    return true;
   }
      
   return super.onDragPointerMove(from, to);
   
  }
  
  @Override
  public boolean onDragPointerUp(MotionEvent from, MotionEvent to) {
   
   /*
    * When user releases finger, add the last point to polyline.
    */
   
   if (number.length == 0){
    return true;
   }   
   if (number.length > 0){
    
    Graphic updatePoint = new Graphic(endpoint, null, attributes, null);
        
    //Conduct Update feature layer on the background
    new updateMovePoint(updatePoint).execute();
    
    //Restores the MapOnTouchListener to its default 
    setDefaultTouchListener();
    
    return true;
   }
   
   return super.onDragPointerUp(from, to);
  }
  

  /**
   * Restores the MapOnTouchListener to its default 
   */
  public void setDefaultTouchListener(){
   MapOnTouchListener ml = new MapOnTouchListener(getApplicationContext(), mMapView);
   mMapView.setOnTouchListener(ml);
  }
  
  
 }

 private class updateMovePoint extends AsyncTask<Void, Void, Void>{
  private Graphic updatePoint;
  
  public updateMovePoint(Graphic updatePoint){
   super();
   this.updatePoint = updatePoint; 
  }

  @Override
  protected Void doInBackground(Void... params) {
   // TODO Auto-generated method stub
   
   featureLayer.applyEdits(null, null, new Graphic[]{updatePoint}, 
     new CallbackListener<FeatureEditResult[][]>() {

    @Override
    public void onCallback(FeatureEditResult[][] arg0) {
     // TODO Auto-generated method stub
     Log.e(TAG, "applyEdits onCallback #obs: " 
       + arg0.length);
    }
    @Override
    public void onError(Throwable e) {
     // TODO Auto-generated method stub
     Log.e(TAG, "apply Edits onError",e); 
    }  
   });  
   //Remove all graphics
   graphicsLayer.removeAll();
   
   return null;
  }
  
  @Override
  protected void onPostExecute(Void result) {
   // TODO Auto-generated method stub
   super.onPostExecute(result);
   
   Toast.makeText(getApplicationContext(),
     getString(R.string.points_submitted),Toast.LENGTH_SHORT).show();
   
   setDefaultTapActions();

  }
 }


Any suggestions and comments are really appreciated...
Thank you in advance,
Gakumin
4 Replies
AndyGup
Esri Regular Contributor
Gakumin,

As for problem #1, I agree. If the app only runs in debugger then there is an execution timing problem. Those are very hard to troubleshoot. Here is a blog post I wrote that shows a pattern for trying to narrow down execution timing and threading issues that may help: http://www.andygup.net/troubleshooting-multi-threading-problems-related-to-androids-onresume/

Problem #2:

Double check the context that is being used in this line of code. You might change it to use getApplicationContext() rather than using "this". It's just a guess:

myTouchListener = new MyTouchListener(this, mMapView);


Also in your onDragPointerUp() method make sure it always returns to the default touch listener. It looked like it only returned to the default listener under certain circumstances.

-Andy
0 Kudos
GakuminKato
New Contributor III
Hi Andy,

Sorry for my late reply. I really appreciate your advice.
Unfortunately, I could not figure out how to use the onDragPointerMove and onDragPointerUp. They did not work for my program at an actual device... Therefore, I compromised. In order to move a point, now my program asks a user to specify a point to move first. Then, the program asks again the user to specify a destination point with single tap. This is not fancy. But, it works at least...

If possible, I would like to have a sample application which shows how to move a point of featureservice with the onDragPointerMove and onDragPointerUp.

Thank you,
Gakumin
0 Kudos
AndyGup
Esri Regular Contributor
Gakumin,

Good suggestion, I agree that would be a good sample to have. I'll pass the suggestion to the Android team.

-Andy
0 Kudos
AndyGup
Esri Regular Contributor
Gakumin, Just a quick follow-up. Your approach is a good work-around for now, as it turns out you cannot freeze/unfreeze the map in the current SDK. I've entered an enhancement request and discussed with the Android team. As part of the enhancement request I added that there should also be a sample to demonstrate the functionality.

-Andy