2013-07-02 18 views
38

Mam następujący kod , który rysuje dla mnie polilinie i działa dobrze, Ale problem polega na tym, że nie rysuje się interaktywnych polilinii, narysowane linie brakuje niektórych pikseli!Jak narysować interaktywną Polilinię na trasie google maps v2 android

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.UnsupportedEncodingException; 
import java.util.ArrayList; 
import java.util.List; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.json.JSONArray; 
import org.json.JSONObject; 

import com.google.android.gms.maps.CameraUpdateFactory; 
import com.google.android.gms.maps.GoogleMap; 
import com.google.android.gms.maps.SupportMapFragment; 
import com.google.android.gms.maps.model.BitmapDescriptorFactory; 
import com.google.android.gms.maps.model.LatLng; 
import com.google.android.gms.maps.model.MarkerOptions; 
import com.google.android.gms.maps.model.Polyline; 
import com.google.android.gms.maps.model.PolylineOptions; 

import android.app.ProgressDialog; 
import android.content.Context; 
import android.graphics.Color; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.support.v4.app.FragmentActivity; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

public class testRoute extends FragmentActivity implements OnClickListener { 

    private GoogleMap myMap; 
    Polyline line; 
    Context context; 

    // Static LatLng 
    LatLng startLatLng = new LatLng(30.707104, 76.690749); 
    LatLng endLatLng = new LatLng(30.721419, 76.730017); 

    public void onCreate(Bundle bd) { 
     super.onCreate(bd); 
     setContentView(R.layout.passanger_home_call); 
     context = testRoute.this; 

     // Temp GetTrails Button 
     Button btntemp = (Button) findViewById(R.id.btn_pass_home_call_temp); 
     btntemp.setOnClickListener(this); 

     // GoogleMap myMap 
     myMap = ((SupportMapFragment) getSupportFragmentManager() 
       .findFragmentById(R.id.map_pass_home_call)).getMap(); 
     myMap.setMyLocationEnabled(true); 
     myMap.moveCamera(CameraUpdateFactory.newLatLng(startLatLng)); 
     myMap.animateCamera(CameraUpdateFactory.zoomTo(12)); 

     // Now auto clicking the button 
     btntemp.performClick(); 
    } 

    @Override 
    public void onClick(View v) { 

     switch (v.getId()) { 
     case R.id.btn_pass_home_call_temp: 
      String urlTopass = makeURL(startLatLng.latitude, 
        startLatLng.longitude, endLatLng.latitude, 
        endLatLng.longitude); 
      new connectAsyncTask(urlTopass).execute(); 
      break; 

     default: 
      break; 
     } 

    } 

    private class connectAsyncTask extends AsyncTask<Void, Void, String> { 
     private ProgressDialog progressDialog; 
     String url; 

     connectAsyncTask(String urlPass) { 
      url = urlPass; 
     } 

     @Override 
     protected void onPreExecute() { 
      // TODO Auto-generated method stub 
      super.onPreExecute(); 
      progressDialog = new ProgressDialog(context); 
      progressDialog.setMessage("Fetching route, Please wait..."); 
      progressDialog.setIndeterminate(true); 
      progressDialog.show(); 
     } 

     @Override 
     protected String doInBackground(Void... params) { 
      JSONParser jParser = new JSONParser(); 
      String json = jParser.getJSONFromUrl(url); 
      return json; 
     } 

     @Override 
     protected void onPostExecute(String result) { 
      super.onPostExecute(result); 
      progressDialog.hide(); 
      if (result != null) { 
       drawPath(result); 
      } 
     } 
    } 

    public String makeURL(double sourcelat, double sourcelog, double destlat, 
      double destlog) { 
     StringBuilder urlString = new StringBuilder(); 
     urlString.append("http://maps.googleapis.com/maps/api/directions/json"); 
     urlString.append("?origin=");// from 
     urlString.append(Double.toString(sourcelat)); 
     urlString.append(","); 
     urlString.append(Double.toString(sourcelog)); 
     urlString.append("&destination=");// to 
     urlString.append(Double.toString(destlat)); 
     urlString.append(","); 
     urlString.append(Double.toString(destlog)); 
     urlString.append("&sensor=false&mode=driving&alternatives=true"); 
     return urlString.toString(); 
    } 

    public class JSONParser { 

     InputStream is = null; 
     JSONObject jObj = null; 
     String json = ""; 

     // constructor 
     public JSONParser() { 
     } 

     public String getJSONFromUrl(String url) { 

      // Making HTTP request 
      try { 
       // defaultHttpClient 
       DefaultHttpClient httpClient = new DefaultHttpClient(); 
       HttpPost httpPost = new HttpPost(url); 

       HttpResponse httpResponse = httpClient.execute(httpPost); 
       HttpEntity httpEntity = httpResponse.getEntity(); 
       is = httpEntity.getContent(); 

      } catch (UnsupportedEncodingException e) { 
       e.printStackTrace(); 
      } catch (ClientProtocolException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      try { 
       BufferedReader reader = new BufferedReader(
         new InputStreamReader(is, "iso-8859-1"), 8); 
       StringBuilder sb = new StringBuilder(); 
       String line = null; 
       while ((line = reader.readLine()) != null) { 
        sb.append(line + "\n"); 
       } 

       json = sb.toString(); 
       is.close(); 
      } catch (Exception e) { 
       Log.e("Buffer Error", "Error converting result " + e.toString()); 
      } 
      return json; 

     } 
    } 

    public void drawPath(String result) { 
     if (line != null) { 
      myMap.clear(); 
     } 
     myMap.addMarker(new MarkerOptions().position(endLatLng).icon(
       BitmapDescriptorFactory.fromResource(R.drawable.redpin_marker))); 
     myMap.addMarker(new MarkerOptions().position(startLatLng).icon(
       BitmapDescriptorFactory.fromResource(R.drawable.redpin_marker))); 
     try { 
      // Tranform the string into a json object 
      final JSONObject json = new JSONObject(result); 
      JSONArray routeArray = json.getJSONArray("routes"); 
      JSONObject routes = routeArray.getJSONObject(0); 
      JSONObject overviewPolylines = routes 
        .getJSONObject("overview_polyline"); 
      String encodedString = overviewPolylines.getString("points"); 
      List<LatLng> list = decodePoly(encodedString); 

      for (int z = 0; z < list.size() - 1; z++) { 
       LatLng src = list.get(z); 
       LatLng dest = list.get(z + 1); 
       line = myMap.addPolyline(new PolylineOptions() 
         .add(new LatLng(src.latitude, src.longitude), 
           new LatLng(dest.latitude, dest.longitude)) 
         .width(5).color(Color.BLUE).geodesic(true)); 
      } 

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

    private List<LatLng> decodePoly(String encoded) { 

     List<LatLng> poly = new ArrayList<LatLng>(); 
     int index = 0, len = encoded.length(); 
     int lat = 0, lng = 0; 

     while (index < len) { 
      int b, shift = 0, result = 0; 
      do { 
       b = encoded.charAt(index++) - 63; 
       result |= (b & 0x1f) << shift; 
       shift += 5; 
      } while (b >= 0x20); 
      int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
      lat += dlat; 

      shift = 0; 
      result = 0; 
      do { 
       b = encoded.charAt(index++) - 63; 
       result |= (b & 0x1f) << shift; 
       shift += 5; 
      } while (b >= 0x20); 
      int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
      lng += dlng; 

      LatLng p = new LatLng((((double) lat/1E5)), 
        (((double) lng/1E5))); 
      poly.add(p); 
     } 

     return poly; 
    } 
} 

Kod działa poprawnie i rysowania trasy z jednego miejsca do drugiego ale nie rysunek interaktywnych Trasy

Screent Ujęcie: - enter image description here

Myślę problem jest z mojej metody drawPath():

public void drawPath(String result) { 
     if (line != null) { 
      myMap.clear(); 
     } 
     myMap.addMarker(new MarkerOptions().position(endLatLng).icon(
       BitmapDescriptorFactory.fromResource(R.drawable.redpin_marker))); 
     myMap.addMarker(new MarkerOptions().position(startLatLng).icon(
       BitmapDescriptorFactory.fromResource(R.drawable.redpin_marker))); 
     try { 
      // Tranform the string into a json object 
      final JSONObject json = new JSONObject(result); 
      JSONArray routeArray = json.getJSONArray("routes"); 
      JSONObject routes = routeArray.getJSONObject(0); 
      JSONObject overviewPolylines = routes 
        .getJSONObject("overview_polyline"); 
      String encodedString = overviewPolylines.getString("points"); 
      List<LatLng> list = decodePoly(encodedString); 

      for (int z = 0; z < list.size() - 1; z++) { 
       LatLng src = list.get(z); 
       LatLng dest = list.get(z + 1); 
       line = myMap.addPolyline(new PolylineOptions() 
         .add(new LatLng(src.latitude, src.longitude), 
           new LatLng(dest.latitude, dest.longitude)) 
         .width(5).color(Color.BLUE).geodesic(true)); 
      } 

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

Zignoruj ​​znaczniki tylko sugerują mi dodanie interaktywnej polilinii?

+2

Co masz na myśli mówiąc: interaktywne polilinie/trasy? –

+0

@ MaciejGórski dzięki za odpowiedź! mam na myśli, że niebieska linia, która jest rysowana na mapie, nie jest interaktywna, niebieska linia brakuje niektórych pikseli! proszę spójrz na zrzut ekranu! –

+0

@ Tarsem Jestem w trakcie tworzenia klasy płyty kotła dla ludzi, aby łatwo zaimplementować GDirection/polyline i pożyczyłem trochę kodu. Daj mi znać, jeśli nie miałbyś nic przeciwko, gdybym go użył, oczywiście zakwalifikuję cię. Jeśli potrzebujesz, możesz skontaktować się ze mną na Twitterze: beckahsheeler Dziękuję! – beckah

Odpowiedz

58

Zamiast tworzyć zbyt wiele krótkich Polyline prostu utworzyć jak tutaj:

PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true); 
for (int z = 0; z < list.size(); z++) { 
    LatLng point = list.get(z); 
    options.add(point); 
} 
line = myMap.addPolyline(options); 

Nie jestem również pewien, czy powinieneś używać geodesic, gdy twoje punkty są tak blisko siebie.

+2

czy można wykryć kliknięcie polilinii? –

+3

Myślę, że dla odpowiedzi, które mogłyby być "Tak" lub "Nie". Nigdy dobry pomysł nie tworzy nowego pytania. –

+4

@MuhammadBabar Następnie moja odpowiedź brzmi "Tak". –

25

Utworzyłem kilka map tutoriale, które obejmie co trzeba

Animating the map opisuje jak stworzyć polilinie w oparciu o zestaw LatLngs. Using Google APIs on your map : Directions and Places opisuje, jak korzystać z interfejsu API wskazówek i animować znacznik wzdłuż ścieżki.

Spójrz na te 2 samouczki i Github project zawierające przykładową aplikację.

Zawiera ona kilka wskazówek, aby twój kod czystsze i bardziej wydajne:

  • z wykorzystaniem biblioteki HTTP Google dla bardziej skutecznego dostępu API i łatwą obsługę JSON.
  • pomocą Google-Map-utils biblioteki dla funkcji związanych z mapami-(jak dekodowanie polilinie)
  • markery animowanie
5

Należy użyć options.addAll(allPoints); zamiast options.add(point);

6

Można użyć tej metody, aby narysować łamaną na GoogleMap

// Draw polyline on map 
public void drawPolyLineOnMap(List<LatLng> list) { 
    PolylineOptions polyOptions = new PolylineOptions(); 
    polyOptions.color(Color.RED); 
    polyOptions.width(5); 
    polyOptions.addAll(list); 

    googleMap.clear(); 
    googleMap.addPolyline(polyOptions); 

    LatLngBounds.Builder builder = new LatLngBounds.Builder(); 
    for (LatLng latLng : list) { 
     builder.include(latLng); 
    } 

    final LatLngBounds bounds = builder.build(); 

    //BOUND_PADDING is an int to specify padding of bound.. try 100. 
    CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, BOUND_PADDING); 
    googleMap.animateCamera(cu); 
} 

Trzeba dodać ten wiersz w Gradle w przypadku, gdy nie mają.

compile 'com.google.android.gms:play-services-maps:8.4.0' 
Powiązane problemy