Je veux dessiner un Free Hand Polygon on the Map in Google Map V2
.
Cette tâche était possible avec Overlay
Map V1 mais Google Map a supprimé cette classe de V2. (Par ceci Google Map V2 a Remove Overlay Class ).
Bon exemple pour Google Map V1 pour dessiner un polygone de style libre.
Dans la carte V2, nous pouvons dessiner un polygone par programmation à l'aide de Google Official Doc mais que doit faire un utilisateur? J'ai trouvé réponse peu claire pour la carte V2
J'ai commencé avec Google Map simple et dessiner un polygone pour le faire par programme et cela fonctionne correctement, mais maintenant je cherche comment un utilisateur peut dessiner? Je ne veux pas dessiner sur la base du marqueur sur le polygone.
// Instantiates a new Polygon object and adds points to define a rectangle
PolygonOptions rectOptions = new PolygonOptions()
.add(new LatLng(37.35, -122.0),
new LatLng(37.45, -122.0),
new LatLng(37.45, -122.2),
new LatLng(37.35, -122.2),
new LatLng(37.35, -122.0));
// Get back the mutable Polygon
Polygon polygon = myMap.addPolygon(rectOptions);
J'ai fait beaucoup de recherche et développement sur ce sujet, mais je n'ai pas réussi à implémenter une telle chose dans Map V2.
Quelques questions
setOnDragListener
?Chaque nouvelle version a quelque chose de plus par rapport à l'ancienne, donc je m'attends à ce que je puisse réaliser la même chose dans Map v2 également.
Je ne demande pas de me donner un exemple de code ou de poster votre code, juste une bonne direction et documentation.
J'ai fourni tous les documents et preuves que j'ai trouvés pendant la recherche et le développement.
Après avoir passé une journée entière dans Rnd et testé quelques alternatives, j'ai trouvé une solution. En fait, j'ai trouvé deux alternatives pour le même problème, mais je voudrais suggérer l'utilisation de Alternative 2 car c'est vraiment très facile par rapport à Alternative 1 .
En fait, j'ai trouvé Alternative 1 avec l'aide de TheLittleNaruto , AndroidHacker et d'autres développeurs et Alternative 2 avec l'aide de Khan donc merci à tous.
Alternative 1
Comment dessiner un polygone de style libre dans la carte V2 (comme nous pouvons le faire avec la carte V1)? Est-ce faisable dans la carte V2?
Oui, c'est faisable mais vous ne pouvez pas obtenir directement OnTouch()
& OnDraw()
sur la carte. Nous devons donc penser à un autre moyen d'y parvenir.
Existe-t-il une astuce ou un moyen alternatif pour y parvenir, si oui comment?
Oui, Google Map V2 ne prend pas en charge OnTouch()
ou OnDraw()
sur une carte à l'aide de class="com.google.Android.gms.maps.SupportMapFragment"
nous devons donc planifier un fragment personnalisé.
Est-il possible de retourner un tableau de lat-long avec un événement tactile?
Oui, si nous créons un fragment de carte personnalisé et l'utilisons, nous pouvons obtenir que Appuyez sur ou Faites glisser événement sur la carte.
Comment obtenir une base de lat sur les coordonnées d'écran sur setOnDragListener?
setOnDragListener
renverra les coordonnées de l'écran (x, y) . Maintenant, pour cela, il existe quelques techniques pour convertir (x, y) en LatLng et ils incluent Projection avec Point & LatLng .
customMapFragment.setOnDragListener(new MapWrapperLayout.OnDragListener() {@Override
public void onDrag(MotionEvent motionEvent) {
Log.i("ON_DRAG", "X:" + String.valueOf(motionEvent.getX()));
Log.i("ON_DRAG", "Y:" + String.valueOf(motionEvent.getY()));
float x = motionEvent.getX(); // get screen x position or coordinate
float y = motionEvent.getY(); // get screen y position or coordinate
int x_co = Integer.parseInt(String.valueOf(Math.round(x))); // casting float to int
int y_co = Integer.parseInt(String.valueOf(Math.round(y))); // casting float to int
projection = mMap.getProjection(); // Will convert your x,y to LatLng
Point x_y_points = new Point(x_co, y_co);// accept int x,y value
LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points); // convert x,y to LatLng
latitude = latLng.latitude; // your latitude
longitude = latLng.longitude; // your longitude
Log.i("ON_DRAG", "lat:" + latitude);
Log.i("ON_DRAG", "long:" + longitude);
// Handle motion event:
}
});
Comment ça marche ?
Comme je l'ai déjà mentionné auparavant, nous devons créer une vue racine personnalisée et en utilisant cela, nous pouvons obtenir Touch ou Faites glisser les événements sur la carte.
Étape 1: nous créons MySupportMapFragment extends SupportMapFragment
et nous l'utiliserons comme fichier .xml
<fragment
Android:id="@+id/map"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
class="pkg_name.MySupportMapFragment" />
Étape 2: créer un MapWrapperLayout extends FrameLayout
afin que nous puissions définir un écouteur tactile ou glisser à l'intérieur et incorporer sa vue avec la vue de la carte. Donc, nous avons besoin d'une interface que nous utiliserons dans Root_Map.Java
MySupportMapFragment.Java
public class MySupportMapFragment extends SupportMapFragment {
public View mOriginalContentView;
public MapWrapperLayout mMapWrapperLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
mOriginalContentView = super.onCreateView(inflater, parent, savedInstanceState);
mMapWrapperLayout = new MapWrapperLayout(getActivity());
mMapWrapperLayout.addView(mOriginalContentView);
return mMapWrapperLayout;
}
@Override
public View getView() {
return mOriginalContentView;
}
public void setOnDragListener(MapWrapperLayout.OnDragListener onDragListener) {
mMapWrapperLayout.setOnDragListener(onDragListener);
}
}
MapWrapperLayout.Java
public class MapWrapperLayout extends FrameLayout {
private OnDragListener mOnDragListener;
public MapWrapperLayout(Context context) {
super(context);
}
public interface OnDragListener {
public void onDrag(MotionEvent motionEvent);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mOnDragListener != null) {
mOnDragListener.onDrag(ev);
}
return super.dispatchTouchEvent(ev);
}
public void setOnDragListener(OnDragListener mOnDragListener) {
this.mOnDragListener = mOnDragListener;
}
}
Root_Map.Java
public class Root_Map extends FragmentActivity {
private GoogleMap mMap;
public static boolean mMapIsTouched = false;
MySupportMapFragment customMapFragment;
Projection projection;
public double latitude;
public double longitude;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.root_map);
MySupportMapFragment customMapFragment = ((MySupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
mMap = customMapFragment.getMap();
customMapFragment.setOnDragListener(new MapWrapperLayout.OnDragListener() { @Override
public void onDrag(MotionEvent motionEvent) {
Log.i("ON_DRAG", "X:" + String.valueOf(motionEvent.getX()));
Log.i("ON_DRAG", "Y:" + String.valueOf(motionEvent.getY()));
float x = motionEvent.getX();
float y = motionEvent.getY();
int x_co = Integer.parseInt(String.valueOf(Math.round(x)));
int y_co = Integer.parseInt(String.valueOf(Math.round(y)));
projection = mMap.getProjection();
Point x_y_points = new Point(x_co, y_co);
LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points);
latitude = latLng.latitude;
longitude = latLng.longitude;
Log.i("ON_DRAG", "lat:" + latitude);
Log.i("ON_DRAG", "long:" + longitude);
// Handle motion event:
}
});
}}
Jusqu'à présent, je peux obtenir LatLong basé sur les coordonnées d'écran X, Y . Il ne me reste plus qu'à le stocker dans Array . Ce tableau sera utilisé pour dessiner sur la carte et, enfin, il ressemblera à un polygone de forme libre.
J'espère que cela vous aidera certainement.
Alternative 2
Comme nous le savons, La disposition des cadres est une disposition transparente, j'ai donc réalisé cela en utilisant la disposition des cadres. Dans ce cas, il n'est pas nécessaire de créer un fragment personnalisé. Je viens d'utiliser la disposition des cadres comme disposition racine. Donc, fondamentalement, j'obtiendrai les événements tactiles dans la disposition racine et cela renverra les coordonnées de l'écran, comme nous l'avons obtenu dans le fragment personnalisé précédemment.
Maintenant, j'ai créé un bouton dans le "Free Draw". Ainsi, lorsque vous cliquez dessus, vous pouvez déplacer vos doigts sur la carte et dessiner un polygone à main libre, ce qui désactivera le déplacement de votre carte à l'écran. Lorsque vous cliquez à nouveau sur le même bouton, l'écran passe en mode idéal.
root_map.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent" >
<fragment
Android:id="@+id/map"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
class="com.google.Android.gms.maps.SupportMapFragment" />
<FrameLayout
Android:id="@+id/fram_map"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent" >
<Button
Android:id="@+id/btn_draw_State"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="Free Draw" />
</FrameLayout>
</FrameLayout>
Root_Map.Java
FrameLayout fram_map = (FrameLayout) findViewById(R.id.fram_map);
Button btn_draw_State = (Button) findViewById(R.id.btn_draw_State);
Boolean Is_MAP_Moveable = false; // to detect map is movable
// Le bouton changera l'état mobile de la carte
btn_draw_State.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Is_MAP_Moveable = !Is_MAP_Moveable;
}
});
Appuyez sur Click of Frame Layout et à l'aide de la tâche
fram_map.setOnTouchListener(new View.OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
int x_co = Math.round(x);
int y_co = Math.round(y);
projection = mMap.getProjection();
Point x_y_points = new Point(x_co, y_co);
LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points);
latitude = latLng.latitude;
longitude = latLng.longitude;
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
// finger touches the screen
val.add(new LatLng(latitude, longitude));
case MotionEvent.ACTION_MOVE:
// finger moves on the screen
val.add(new LatLng(latitude, longitude));
case MotionEvent.ACTION_UP:
// finger leaves the screen
Draw_Map();
break;
}
return Is_MAP_Moveable;
}
});
// Dessine ta carte
public void Draw_Map() {
rectOptions = new PolygonOptions();
rectOptions.addAll(val);
rectOptions.strokeColor(Color.BLUE);
rectOptions.strokeWidth(7);
rectOptions.fillColor(Color.CYAN);
polygon = mMap.addPolygon(rectOptions);
}
Pourtant, maintenant vous devez maintenir votre liste pendant que vous dessinez, vous devez donc effacer les données de votre liste précédente.
Vérifiez ceci .. Je crois que U est capable d'afficher Google Map v2
Découvrez la méthode "decodePoly" et "drawPath" dans AsyncTask
Impulsion principale dans "drawPath" ..
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);
Classe complète pour votre référence ..
package com.example.androidhackergooglemap;
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.Marker;
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.content.Intent;
import Android.graphics.Color;
import Android.location.Location;
import Android.location.LocationManager;
import Android.os.AsyncTask;
import Android.os.Bundle;
import Android.provider.Settings;
import Android.support.v4.app.FragmentActivity;
import Android.util.Log;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.widget.Toast;
public class MainActivity extends FragmentActivity implements OnClickListener {
private GoogleMap myMap;
Polyline line;
Context context;
Location location;
boolean check_provider_enabled = false;
// 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.activity_main);
context = MainActivity.this;
// GoogleMap myMap
myMap = ((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map)).getMap();
myMap.setMyLocationEnabled(true);
myMap.moveCamera(CameraUpdateFactory.newLatLng(startLatLng));
myMap.animateCamera(CameraUpdateFactory.zoomTo(12));
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
location = service.getLastKnownLocation(LocationManager.GPS_PROVIDER);
// check if enabled and if not send user to the GSP settings
// Better solution would be to display a dialog and suggesting to
// go to the settings
if (!enabled) {
/*Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);*/
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
Toast.makeText(getApplicationContext(), "Enable GPS servcies to use this app.", Toast.LENGTH_LONG).show();
} else {
try {
String urlTopass = makeURL(startLatLng.latitude,
startLatLng.longitude, endLatLng.latitude,
endLatLng.longitude);
new connectAsyncTask(urlTopass).execute();
} catch (Exception e) {
e.printStackTrace();
}
}
// Now auto clicking the button
// btntemp.performClick();
}
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.ic_launcher)));
myMap.addMarker(new MarkerOptions().position(startLatLng).icon(
BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));
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);
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);
/*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;
}
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}
}
J'espère que ça aide. À votre santé!
[~ # ~] mise à jour [~ # ~]
consultez ceci .. Création de OnDragListener pour Google Map v2 Fragment
Vérifiez également celui-ci .. Comment dessiner une forme sur le fragment de carte en le touchant en utilisant google map V2
Un peu plus de référence .. Comment obtenir les coordonnées d'écran du marqueur dans google maps v2 Android
Nous avons donc une solution pour dessiner à main levée sur la carte v2. Mettre en place GoogleMap.OnMarkerDragListener
dans votre activité sur la carte. Il remplacera la fonction onMarkerDrag.
@Override
public void onMarkerDrag(Marker marker) {
//add the marker's latlng in a arraylist of LatLng and pass it to the loop
for (int i = 0; i < arraylistoflatlng.size(); i++) {
myMap.addPolyline(new PolylineOptions()
.addAll(arraylistoflatlng)
.width(5)
.color(Color.RED));
}
}
vous pouvez passer une sorte de piratage à main levée comme dès que l'utilisateur touchera la carte, vous devrez détecter ces coordonnées et les transmettre au onMarkerDrag. Comme vous devrez utiliser les informations de la zone pour poursuivre le processus. Pour l'événement tactile, vous pouvez implémenter GoogleMap.OnMapClickListener
et obtenir les coordonnées de son paramètre. J'espère que cela vous aidera :)
voici le tutoriel google maps API V2:
public class MapPane extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_activity);
GoogleMap map = ((MapFragment) getFragmentManager()
.findFragmentById(R.id.map)).getMap();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(-18.142, 178.431), 2));
// Polylines are useful for marking paths and routes on the map.
map.addPolyline(new PolylineOptions().geodesic(true)
.add(new LatLng(-33.866, 151.195)) // Sydney
.add(new LatLng(-18.142, 178.431)) // Fiji
.add(new LatLng(21.291, -157.821)) // Hawaii
.add(new LatLng(37.423, -122.091)) // Mountain View
);
}
}
lien: https://developers.google.com/maps/documentation/Android/