如何在路线谷歌地图v2 android上绘制交互式折线
Posted
技术标签:
【中文标题】如何在路线谷歌地图v2 android上绘制交互式折线【英文标题】:How to draw interactive Polyline on route google maps v2 android 【发布时间】:2013-06-29 19:34:13 【问题描述】:我有以下 代码为我绘制折线并且工作正常,但问题是它没有绘制交互式折线,绘制的线缺少一些像素!
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;
代码工作正常,绘制从一个地方到另一个地方的路线,但没有绘制交互式路线
屏幕截图:-
我认为问题在于我的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();
忽略标记只是建议我添加交互式折线?
【问题讨论】:
交互式折线/路线是什么意思? @MaciejGórski 感谢您的回复!我的意思是在地图上绘制的蓝线不是交互式的,蓝线缺少一些像素!请看屏幕截图! @Tarsem 我正在为人们创建一个样板类以轻松实现 GDirection/折线,并且我借用了您的一些代码。如果您不介意我使用它,请告诉我,我当然会感谢您。如果您需要,可以在 Twitter 上与我联系:beckahsheeler 谢谢! github.com/amalChandran/trail-android 您可以使用投影 API 将其绘制为叠加层。 感谢 decodepoly 方法帮助我解决了我的问题。 【参考方案1】:与其创建太多简短的Polyline
s,不如创建一个像这里这样的:
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);
我也不确定您是否应该使用geodesic
,因为您的点彼此如此接近。
【讨论】:
是否可以检测到对折线的点击? 我认为答案可能是Yes
或No
。从来没有一个好主意会提出新问题。
@MuhammadBabar 那么我的答案是Yes
。
这只会绘制一条路径。如果你想让你的道路坚持道路使用谷歌方向 API。
您可以通过执行此 new PolylineOptions() .addAll(list).width(5).color(Color.BLUE).geodesic(true); 来缩小此代码;【参考方案2】:
我创建了几个地图教程,可以满足您的需求
Animating the map 描述了如何基于一组 LatLngs 创建折线。 Using Google APIs on your map : Directions and Places 描述了如何使用 Directions API 并沿路径为标记设置动画。
看看这 2 个教程和包含示例应用程序的 Github project。
它包含一些让您的代码更简洁、更高效的提示:
使用 Google HTTP 库实现更高效的 API 访问和轻松的 JSON 处理。 将 google-map-utils 库用于地图相关功能(如解码折线) 动画标记【讨论】:
【参考方案3】:您可以使用此方法在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);
如果没有,您需要在 gradle 中添加这一行。
compile 'com.google.android.gms:play-services-maps:8.4.0'
【讨论】:
【参考方案4】:您应该使用options.addAll(allPoints);
而不是options.add(point);
【讨论】:
【参考方案5】:使用 google maps 投影 api 在叠加视图上绘制折线使我们能够做很多事情。检查这个有例子的repo。
【讨论】:
以上是关于如何在路线谷歌地图v2 android上绘制交互式折线的主要内容,如果未能解决你的问题,请参考以下文章
如何在android中的谷歌地图上绘制路线并计算多个标记之间的距离