如何通过选择带有自动完成位置的标记来绘制路线?
How to draw route by selecting a markers with places autocomplete?
当我从地点 AutoComplete
搜索栏放置目的地标记时,我想在地图上绘制路线。一旦我 select 自动完成的放置位置,我就想要路线。我看过一些绘制路径的示例,但无法通过 Places Autocomplete
找到任何示例。我的地图和地点 Autocomplete
工作正常。我该怎么做?
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (!Places.isInitialized()) {
Places.initialize(getApplicationContext(), "my_api_ke");
}
/*Map Initialisation*/
mv = findViewById(R.id.Gmapview);
mv.onCreate(savedInstanceState);
mv.getMapAsync(this);
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
provider = lm.getBestProvider(new Criteria(), false);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
checkLocationPermission();
enableMyLocationIfPermitted();
//Initialize AutoCompleteSupportFragment
//Pickup Search Bar
supportFragment = (AutocompleteSupportFragment)
getSupportFragmentManager().findFragmentById(R.id.pickup);
supportFragment1 = (AutocompleteSupportFragment) getSupportFragmentManager()
.findFragmentById(R.id.drop);
//Initialize the Fields to get Latitude and Langitude and name of the selected place.
supportFragment.setPlaceFields(Arrays.asList(Place.Field.LAT_LNG, Place.Field.NAME));
supportFragment1.setPlaceFields(Arrays.asList(Place.Field.LAT_LNG, Place.Field.NAME));
//Placing Pickup Marker
supportFragment.setOnPlaceSelectedListener(newPlaceSelectionListener(){
@Override
public void onPlaceSelected(@NonNull Place pickup) {
Log.i("PickUP", "Place: " + pickup.getName() + ", ");
String name = pickup.getName();
LatLng latLng = pickup.getLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(name);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
gm.addMarker(markerOptions);
gm.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));
}
@Override
public void onError(@NonNull Status status) {
Log.i("pickup", "An error occurred: " + status);
}
});
//Placing Drop Marker
supportFragment1.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(@NonNull Place drop) {
Log.i("Drop", "Place: " + drop.getName() + ", ");
String name = drop.getName();
LatLng latLng = drop.getLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
gm.addMarker(markerOptions);
gm.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));
}
@Override
public void onError(@NonNull Status status) {
Log.i("drop", "An error occurred: " + status);
}
});
}
假设你的LatLng
对象是正确的,你只需要绘制路线,这里你应该做什么
创建一个名为 DirectionsJSONParser
的助手 class,它稍后会解码您的折线并为您提供纬度经度对象列表。
这是 link class DirectionsJSONParser
对于 RetrofitClient
这些是导入确保你添加它们
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
将此添加到您的 build.gradle(app) 文件
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
创建改造客户端
//this is a singleton of Retrofit
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if(retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
}
//return retrofit object
return retrofit;
}
}
接下来创建一个googleAPI界面
public interface IGoogleAPI {
@GET
Call<String> getPath(@Url String url);
}
创建一个公共 class
public class Common {
public static String baseURL = "https://maps.googleapis.com/";
public static IGoogleAPI getGoogleAPI() {
return RetrofitClient.getClient(baseURL).create(IGoogleAPI.class);
}
}
最后但同样重要的是,在您的 activity
中声明一个变量
IGoogleAPI mService;
在 onCreate 中初始化该变量
mService = Common.getGoogleAPI();
创建绘制路线的方法
private void getDirection() {
String requestAPI;
try {
requestAPI = "https://maps.googleapis.com/maps/api/directions/json?" +
"mode=driving&" +
"transit_routing_preference=less_driving&" +
"origin=" + pickupMarker.getLatitude() + "," + pickupMarker.getLongitude() +
"&destination=" + dropMarker.getLatitude() + "," + dropMarker.getLongitude() + "&" +
"key=" + getResources().getString(R.string.google_direction_apis);
mService.getPath(requestAPI)
.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
try {
new ParserTask().execute(response.body().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
别忘了
- 要在 build.gradle
中添加改装依赖项
- 要在
requestString
中更改您的 API_KEY。
代码很长,如果您有任何问题,请告诉我。
在获得放置位置后调用此函数 getDirection()。
编辑
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
ProgressDialog mDialog = new ProgressDialog(NavigationTracking.this);
@Override
protected void onPreExecute() {
super.onPreExecute();
mDialog.setMessage("Executing...");
mDialog.show();
}
@Override
protected List<List<HashMap<String, String>>> doInBackground(String... strings) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(strings[0]);
DirectionJsonParser parser = new DirectionJsonParser();
routes = parser.parse(jObject);
} catch (JSONException e) {
e.printStackTrace();
}
return routes;
}
@Override
protected void onPostExecute(List<List<HashMap<String, String>>> lists) {
mDialog.dismiss();
ArrayList points = null;
PolylineOptions polylineOptions = null;
Toast.makeText(NavigationTracking.this, "" + lists.size(), Toast.LENGTH_SHORT).show();
for (int i = 0; i < lists.size(); i++) {
points = new ArrayList();
polylineOptions = new PolylineOptions();
List<HashMap<String, String>> path = lists.get(i);
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
polylineOptions.addAll(points);
polylineOptions.width(10);
polylineOptions.color(Color.RED);
// the shortest line between two points
polylineOptions.geodesic(true);
}
if (polylineOptions != null) {
direction = mMap.addPolyline(polylineOptions);
}
}
}
声明
private Polyline direction;
并在调用之前添加此测试 getDirection()
if (direction != null)
direction.remove();
编辑 2
像这样在 onCreate() 之前声明 2 个 LatLng 变量:
LatLng pickupLoc;
LatLng dropLoc;
然后当你选择地方时你的代码变成这样
//Placing Pickup Marker
supportFragment.setOnPlaceSelectedListener(newPlaceSelectionListener(){
@Override
public void onPlaceSelected(@NonNull Place pickup) {
Log.i("PickUP", "Place: " + pickup.getName() + ", ");
String name = pickup.getName();
pickupLoc = pickup.getLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(pickupLoc );
markerOptions.title(name);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
gm.addMarker(markerOptions);
gm.moveCamera(CameraUpdateFactory.newLatLngZoom(pickupLoc, 11));
}
@Override
public void onError(@NonNull Status status) {
Log.i("pickup", "An error occurred: " + status);
}
});
//Placing Drop Marker
supportFragment1.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(@NonNull Place drop) {
Log.i("Drop", "Place: " + drop.getName() + ", ");
String name = drop.getName();
dropLoc = drop.getLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(dropLoc );
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
gm.addMarker(markerOptions);
gm.moveCamera(CameraUpdateFactory.newLatLngZoom(dropLoc, 11));
//here you test if your locations aren't null call getDirection() like this
if (pickupLoc != null && dropLoc != null) {
if (direction != null)
direction.remove();
getDirection();
}
}
@Override
public void onError(@NonNull Status status) {
Log.i("drop", "An error occurred: " + status);
}
});
所以@Amine 的回答大部分是正确的,但需要进行一些细微的更改,我在这里给出:
private void getDirection() {
String requestAPI;
try {
requestAPI = "https://maps.googleapis.com/maps/api/directions/json?" +
"mode=driving&" +
"transit_routing_preference=less_driving&" +
"origin=" + pickuploc.latitude() + "," +
pickuploc.longitude() +
"&destination=" + droploc.latitude() + "," +
droploc.longitude() + "&" +
"key=" + getResources().getString(R.string.google_direction_apis);
/*If you get "PolylineOptions cannot be null" error and app crashes
while trying to draw polyline then try pasting your API
key in string directly like this "key=somekey". Though only for testing. */
mService.getPath(requestAPI)
.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String>
response) {
try {
new ParserTask().execute(response.body().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
当我从地点 AutoComplete
搜索栏放置目的地标记时,我想在地图上绘制路线。一旦我 select 自动完成的放置位置,我就想要路线。我看过一些绘制路径的示例,但无法通过 Places Autocomplete
找到任何示例。我的地图和地点 Autocomplete
工作正常。我该怎么做?
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (!Places.isInitialized()) {
Places.initialize(getApplicationContext(), "my_api_ke");
}
/*Map Initialisation*/
mv = findViewById(R.id.Gmapview);
mv.onCreate(savedInstanceState);
mv.getMapAsync(this);
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
provider = lm.getBestProvider(new Criteria(), false);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
checkLocationPermission();
enableMyLocationIfPermitted();
//Initialize AutoCompleteSupportFragment
//Pickup Search Bar
supportFragment = (AutocompleteSupportFragment)
getSupportFragmentManager().findFragmentById(R.id.pickup);
supportFragment1 = (AutocompleteSupportFragment) getSupportFragmentManager()
.findFragmentById(R.id.drop);
//Initialize the Fields to get Latitude and Langitude and name of the selected place.
supportFragment.setPlaceFields(Arrays.asList(Place.Field.LAT_LNG, Place.Field.NAME));
supportFragment1.setPlaceFields(Arrays.asList(Place.Field.LAT_LNG, Place.Field.NAME));
//Placing Pickup Marker
supportFragment.setOnPlaceSelectedListener(newPlaceSelectionListener(){
@Override
public void onPlaceSelected(@NonNull Place pickup) {
Log.i("PickUP", "Place: " + pickup.getName() + ", ");
String name = pickup.getName();
LatLng latLng = pickup.getLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(name);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
gm.addMarker(markerOptions);
gm.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));
}
@Override
public void onError(@NonNull Status status) {
Log.i("pickup", "An error occurred: " + status);
}
});
//Placing Drop Marker
supportFragment1.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(@NonNull Place drop) {
Log.i("Drop", "Place: " + drop.getName() + ", ");
String name = drop.getName();
LatLng latLng = drop.getLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
gm.addMarker(markerOptions);
gm.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));
}
@Override
public void onError(@NonNull Status status) {
Log.i("drop", "An error occurred: " + status);
}
});
}
假设你的LatLng
对象是正确的,你只需要绘制路线,这里你应该做什么
创建一个名为 DirectionsJSONParser
的助手 class,它稍后会解码您的折线并为您提供纬度经度对象列表。
这是 link class DirectionsJSONParser
对于 RetrofitClient
这些是导入确保你添加它们
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
将此添加到您的 build.gradle(app) 文件
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
创建改造客户端
//this is a singleton of Retrofit
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if(retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
}
//return retrofit object
return retrofit;
}
}
接下来创建一个googleAPI界面
public interface IGoogleAPI {
@GET
Call<String> getPath(@Url String url);
}
创建一个公共 class
public class Common {
public static String baseURL = "https://maps.googleapis.com/";
public static IGoogleAPI getGoogleAPI() {
return RetrofitClient.getClient(baseURL).create(IGoogleAPI.class);
}
}
最后但同样重要的是,在您的 activity
中声明一个变量IGoogleAPI mService;
在 onCreate 中初始化该变量
mService = Common.getGoogleAPI();
创建绘制路线的方法
private void getDirection() {
String requestAPI;
try {
requestAPI = "https://maps.googleapis.com/maps/api/directions/json?" +
"mode=driving&" +
"transit_routing_preference=less_driving&" +
"origin=" + pickupMarker.getLatitude() + "," + pickupMarker.getLongitude() +
"&destination=" + dropMarker.getLatitude() + "," + dropMarker.getLongitude() + "&" +
"key=" + getResources().getString(R.string.google_direction_apis);
mService.getPath(requestAPI)
.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
try {
new ParserTask().execute(response.body().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
别忘了
- 要在 build.gradle 中添加改装依赖项
- 要在
requestString
中更改您的 API_KEY。
代码很长,如果您有任何问题,请告诉我。
在获得放置位置后调用此函数 getDirection()。
编辑
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
ProgressDialog mDialog = new ProgressDialog(NavigationTracking.this);
@Override
protected void onPreExecute() {
super.onPreExecute();
mDialog.setMessage("Executing...");
mDialog.show();
}
@Override
protected List<List<HashMap<String, String>>> doInBackground(String... strings) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(strings[0]);
DirectionJsonParser parser = new DirectionJsonParser();
routes = parser.parse(jObject);
} catch (JSONException e) {
e.printStackTrace();
}
return routes;
}
@Override
protected void onPostExecute(List<List<HashMap<String, String>>> lists) {
mDialog.dismiss();
ArrayList points = null;
PolylineOptions polylineOptions = null;
Toast.makeText(NavigationTracking.this, "" + lists.size(), Toast.LENGTH_SHORT).show();
for (int i = 0; i < lists.size(); i++) {
points = new ArrayList();
polylineOptions = new PolylineOptions();
List<HashMap<String, String>> path = lists.get(i);
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
polylineOptions.addAll(points);
polylineOptions.width(10);
polylineOptions.color(Color.RED);
// the shortest line between two points
polylineOptions.geodesic(true);
}
if (polylineOptions != null) {
direction = mMap.addPolyline(polylineOptions);
}
}
}
声明
private Polyline direction;
并在调用之前添加此测试 getDirection()
if (direction != null)
direction.remove();
编辑 2
像这样在 onCreate() 之前声明 2 个 LatLng 变量:
LatLng pickupLoc;
LatLng dropLoc;
然后当你选择地方时你的代码变成这样
//Placing Pickup Marker
supportFragment.setOnPlaceSelectedListener(newPlaceSelectionListener(){
@Override
public void onPlaceSelected(@NonNull Place pickup) {
Log.i("PickUP", "Place: " + pickup.getName() + ", ");
String name = pickup.getName();
pickupLoc = pickup.getLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(pickupLoc );
markerOptions.title(name);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
gm.addMarker(markerOptions);
gm.moveCamera(CameraUpdateFactory.newLatLngZoom(pickupLoc, 11));
}
@Override
public void onError(@NonNull Status status) {
Log.i("pickup", "An error occurred: " + status);
}
});
//Placing Drop Marker
supportFragment1.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(@NonNull Place drop) {
Log.i("Drop", "Place: " + drop.getName() + ", ");
String name = drop.getName();
dropLoc = drop.getLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(dropLoc );
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
gm.addMarker(markerOptions);
gm.moveCamera(CameraUpdateFactory.newLatLngZoom(dropLoc, 11));
//here you test if your locations aren't null call getDirection() like this
if (pickupLoc != null && dropLoc != null) {
if (direction != null)
direction.remove();
getDirection();
}
}
@Override
public void onError(@NonNull Status status) {
Log.i("drop", "An error occurred: " + status);
}
});
所以@Amine 的回答大部分是正确的,但需要进行一些细微的更改,我在这里给出:
private void getDirection() {
String requestAPI;
try {
requestAPI = "https://maps.googleapis.com/maps/api/directions/json?" +
"mode=driving&" +
"transit_routing_preference=less_driving&" +
"origin=" + pickuploc.latitude() + "," +
pickuploc.longitude() +
"&destination=" + droploc.latitude() + "," +
droploc.longitude() + "&" +
"key=" + getResources().getString(R.string.google_direction_apis);
/*If you get "PolylineOptions cannot be null" error and app crashes
while trying to draw polyline then try pasting your API
key in string directly like this "key=somekey". Though only for testing. */
mService.getPath(requestAPI)
.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String>
response) {
try {
new ParserTask().execute(response.body().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}