2015-03-26 4 views
5

In meiner Anwendung muss eine reibungslose "verschieben" Google Maps-Marker von einem Punkt zum anderen zeigen. Ich verwende die folgende Methode für die Animation:Wie korrigieren Sie das Verschieben des Markers in Google Maps v2?

public void animateMarker(final Marker marker, final LatLng toPosition, 
          final boolean hideMarker) { 
    final Handler handler = new Handler(); 
    final long start = SystemClock.uptimeMillis(); 
    Projection proj = mMap.getProjection(); 
    Point startPoint = proj.toScreenLocation(marker.getPosition()); 
    final LatLng startLatLng = proj.fromScreenLocation(startPoint); 
    final long duration = 500; 

    final Interpolator interpolator = new LinearInterpolator(); 

    handler.post(new Runnable() { 
     @Override 
     public void run() { 
      long elapsed = SystemClock.uptimeMillis() - start; 
      float t = interpolator.getInterpolation((float) elapsed 
        /duration); 
      double lng = t * toPosition.longitude + (1 - t) 
        * startLatLng.longitude; 
      double lat = t * toPosition.latitude + (1 - t) 
        * startLatLng.latitude; 
      marker.setPosition(new LatLng(lat, lng)); 

      if (t < 1.0) { 
       // Post again 16ms later. 
       handler.postDelayed(this, 16); 
      } else { 
       if (hideMarker) { 
        marker.setVisible(false); 
       } else { 
        marker.setVisible(true); 
       } 
      } 
     } 
    }); 
} 

Aber als Ergebnis einfach einen neuen Marker an den neuen Standort zu schaffen (wenn auch alten nicht entfernt wird):

enter image description here

+0

Ich denke, Sie müssen die Ansicht neu zu zeichnen, nachdem Sie eine Position ändern, und bevor Sie zu warten beginnen. – kaho

+0

Meinen Sie einen Löschmarker und fügen Sie einen neuen mit neuer Position hinzu? – Rexhaif

+0

Soweit ich weiß, zeichnet Android den Bildschirm erst ab, wenn die Schleife beendet ist, um Ressourcen zu sparen. Sie müssen also dem System mitteilen, dass Sie den Bildschirm neu zeichnen möchten. Scheint so, als würde das helfen: http://developer.android.com/reference/android/view/View.html#invalidate(android.graphics.Rect) – kaho

Antwort

18

I kopiert einige der Code aus der project in der official video erwähnt.

Ich habe versucht, es mit diesem Code und dieser seems to be working for me zu reproduzieren, so hoffentlich würde mein Code Ihnen helfen, auch nur für ein bisschen.

static final LatLng SomePos = new LatLng(37.7796354, -122.4159606); 

    try { 
     if (googleMap == null) { 
      googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); 
     } 
     googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); 
     googleMap.setMyLocationEnabled(true); 
     googleMap.setTrafficEnabled(false); 
     googleMap.setIndoorEnabled(false); 
     googleMap.setBuildingsEnabled(true); 
     googleMap.getUiSettings().setZoomControlsEnabled(true); 
     googleMap.moveCamera(CameraUpdateFactory.newLatLng(SomePos)); 
     googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder() 
       .target(googleMap.getCameraPosition().target) 
       .zoom(17) 
       .bearing(30) 
       .tilt(45) 
       .build())); 

     myMarker = googleMap.addMarker(new MarkerOptions() 
       .position(SomePos) 
       .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher)) 
       .title("Hello world")); 


     googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() 
     { 
      @Override 
      public boolean onMarkerClick(Marker arg0) { 

       final LatLng startPosition = myMarker.getPosition(); 
       final LatLng finalPosition = new LatLng(37.7801569,-122.4148528); 
       final Handler handler = new Handler(); 
       final long start = SystemClock.uptimeMillis(); 
       final Interpolator interpolator = new AccelerateDecelerateInterpolator(); 
       final float durationInMs = 3000; 
       final boolean hideMarker = false; 

       handler.post(new Runnable() { 
        long elapsed; 
        float t; 
        float v; 

        @Override 
        public void run() { 
         // Calculate progress using interpolator 
         elapsed = SystemClock.uptimeMillis() - start; 
         t = elapsed/durationInMs; 
         v = interpolator.getInterpolation(t); 

         LatLng currentPosition = new LatLng(
           startPosition.latitude*(1-t)+finalPosition.latitude*t, 
           startPosition.longitude*(1-t)+finalPosition.longitude*t); 

         myMarker.setPosition(currentPosition); 

         // Repeat till progress is complete. 
         if (t < 1) { 
          // Post again 16ms later. 
          handler.postDelayed(this, 16); 
         } else { 
          if (hideMarker) { 
           myMarker.setVisible(false); 
          } else { 
           myMarker.setVisible(true); 
          } 
         } 
        } 
       }); 

       return true; 

      } 

     }); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
+0

vielen Dank – Rexhaif

3

Ich weiß, das ist eine alte Frage, aber ...

Sie Wert Interpolator für diese Aufgabe verwenden können:

fun changePositionSmoothly(marker:Marker?, newLatLng: LatLng){ 
    if(marker == null){ 
     return; 
    } 
    val animation = ValueAnimator.ofFloat(0f, 100f) 
    var previousStep = 0f 
    val deltaLatitude = newLatLng.latitude - marker.position.latitude 
    val deltaLongitude = newLatLng.longitude - marker.position.longitude 
    animation.setDuration(1500) 
    animation.addUpdateListener { updatedAnimation -> 
     val deltaStep = updatedAnimation.getAnimatedValue() as Float - previousStep 
     previousStep = updatedAnimation.getAnimatedValue() as Float 
     marker.position = LatLng(marker.position.latitude + deltaLatitude * deltaStep * 1/100, marker.position.longitude + deltaStep * deltaLongitude * 1/100) 
    } 
    animation.start() 
} 

Um Fehlerakkumulation am Ende der Animation zu verhindern Sie kann die neue Position einstellen, aber das reicht für die meisten Fälle.

Verwandte Themen