2015-03-26 14 views
5

Nella mia applicazione è necessario visualizzare un "google" indicatore di google liscio da un punto all'altro. Io uso il seguente metodo per l'animazione:Come correggere spostando il marker 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); 
       } 
      } 
     } 
    }); 
} 

Ma come risultato di creare semplicemente un nuovo marcatore nella nuova posizione (anche se vecchio non viene rimosso):

enter image description here

+0

Penso che sia necessario dire alla vista di ridisegnarsi dopo aver cambiato una posizione e prima di iniziare ad aspettare. – kaho

+0

Intendevi un indicatore di cancellazione e ne aggiungi uno nuovo con una nuova posizione? – Rexhaif

+0

Per quanto ne so, per risparmiare risorse, Android non disegna lo schermo fino alla fine del ciclo ... quindi devi dire al sistema che vuoi ridisegnare lo schermo. Sembra che questo potrebbe aiutare: http://developer.android.com/reference/android/view/View.html#invalidate(android.graphics.Rect) – kaho

risposta

18

ho copiato parte del codice dallo project menzionato nello official video.

Ho provato a riprodurlo con questo codice e questo seems to be working for me, quindi spero che il mio codice possa aiutarti, anche per un po '.

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

grazie mille – Rexhaif

3

So che questa è una vecchia questione, ma ...

È possibile utilizzare il valore di interpolazione per questo compito:

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() 
} 

per evitare l'accumulo di errore, alla fine dell'animazione voi può impostare la nuova posizione, ma questo è sufficiente per la maggior parte dei casi.

Problemi correlati