Comment dessiner un polygone à main levée dans Google map V2 sous Android?

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 cette Google Map V2 a Supprimer la classe de superposition ).

Bon exemple pour que Google Map V1 dessine un polygone de style libre.

Dans Map V2, nous pouvons dessiner un polygone par programmation avec l’aide de Google Official Doc, mais que doit faire un utilisateur? J’ai trouvé la réponse peu claire pour la carte V2

J’ai commencé avec un simple Google Map et dessine un polygone pour le faire par programmation et cela fonctionne correctement, mais je cherche maintenant comment un utilisateur peut dessiner? Je ne veux pas dessiner en fonction 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 trouvé le moyen idéal d’implémenter une telle chose dans Map V2.

Quelques questions

  • Comment dessiner un polygone de style libre dans Map V2 (comme on peut le faire avec Map V1)?
  • Y a-t-il une astuce ou une alternative pour y parvenir? Si oui comment?
  • Pouvons-nous obtenir un événement tactile sur la carte et dessiner un polygone?
  • Est-ce faisable dans la carte V2?
  • Est-ce possible avec un événement tactile qui renvoie un tableau de longueur de lat?
  • Comment puis-je obtenir Lat-long en fonction des coordonnées de l’écran sur setOnDragListener ?

Chaque nouvelle version a quelque chose de plus que l’ancienne, donc je m’attends à ce que je puisse réaliser la même chose dans Map v2.

Je ne vous demande pas de me donner un exemple de code ou de poster votre code, juste quelques instructions et documents appropriés.

J’ai fourni tous les documents et preuves trouvés lors de la recherche et du développement.

Après avoir passé une journée entière à tester 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 l’ alternative 2 car c’est vraiment très simple comparé à l’ alternative 1 .

En fait, j’ai trouvé l’ Alternative 1 avec l’aide de TheLittleNaruto , AndroidHacker et d’autres développeurs & Alternative 2 avec l’aide de Khan, donc merci à tous.

Alternative 1

Comment dessiner un polygone de style libre dans Map V2 (comme on peut le faire avec Map V1)? Est-ce faisable dans la carte V2?

Oui, c’est faisable mais vous ne pouvez pas obtenir directement OnTouch() et OnDraw() sur la carte. Nous devons donc réfléchir à une autre manière d’y parvenir.

Y a-t-il une astuce ou une autre manière de réaliser cette chose, si oui, comment?

Oui, Google Map V2 ne prend pas en charge OnTouch() ou OnDraw() sur une carte utilisant class="com.google.android.gms.maps.SupportMapFragment" . Nous devons donc prévoir 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 que nous l’utilisons, nous pouvons obtenir cet événement Touch ou Drag sur la carte.

Comment puis-je obtenir la base Lat-long sur les coordonnées de l’écran sur setOnDragListener?

setOnDragListener renverra les coordonnées de l’écran (x, y) . Maintenant, pour cela, il existe des techniques pour convertir (x, y) en LatLng et elles incluent Projection avec Point & LatLng .

 customMapFragment.setOnDragListener(new MapWrapperLayout.OnDragListener() {@Override public void onDrag(MotionEvent motionEvent) { Log.i("ON_DRAG", "X:" + Ssortingng.valueOf(motionEvent.getX())); Log.i("ON_DRAG", "Y:" + Ssortingng.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(Ssortingng.valueOf(Math.round(x))); // casting float to int int y_co = Integer.parseInt(Ssortingng.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é précédemment, nous devons créer une vue racine personnalisée et l’utiliser pour obtenir des événements Touch ou Drag sur la carte.

Etape 1: Nous créons MySupportMapFragment extends SupportMapFragment et nous l’utiliserons comme fichier .xml

   

Etape 2: Créer un MapWrapperLayout extends FrameLayout afin que nous puissions définir un écouteur Touch ou Drag et intégrer sa vue à la vue Map. 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; } } 

Racine_Carte.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:" + Ssortingng.valueOf(motionEvent.getX())); Log.i("ON_DRAG", "Y:" + Ssortingng.valueOf(motionEvent.getY())); float x = motionEvent.getX(); float y = motionEvent.getY(); int x_co = Integer.parseInt(Ssortingng.valueOf(Math.round(x))); int y_co = Integer.parseInt(Ssortingng.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: } }); }} 

Lien de référence1, Link2

Jusqu’à présent, je suis capable d’obtenir LatLong basé sur les coordonnées d’écran X, Y. Il ne me rest plus qu’à le stocker dans Array . Ce tableau sera utilisé pour dessiner sur la carte et finalement, il ressemblera à un polygone de forme libre.

entrer la description de l'image ici

J’espère que cela va certainement vous aider.

Mettre à jour:

Alternative 2

Comme nous le soaps, la disposition des frameworks est une mise en page transparente, ce qui m’a permis d’obtenir la mise en page des frameworks. Dans ce cas, il n’est pas nécessaire de créer un fragment personnalisé. Je viens d’utiliser la mise en page des frameworks en tant que disposition racine. Donc, fondamentalement, je vais obtenir des événements tactiles dans la structure racine et cela renverra les coordonnées de l’écran, comme nous l’avons déjà fait dans un fragment personnalisé.

Maintenant, j’ai créé un bouton à l’intérieur du “Free Draw”. Ainsi, lorsque vous cliquez sur ce bouton, vous pouvez déplacer vos doigts sur la carte et dessiner un polygone à main levée, ce qui désactive la mobilité de votre carte à l’écran. Lorsque vous cliquez à nouveau sur le même bouton, l’écran passe en mode idéal.

root_map.xml

        

Racine_Carte.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 va changer l’état de la carte

 btn_draw_State.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Is_MAP_Moveable = !Is_MAP_Moveable; } }); 

Touchez 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); } 

Cependant, vous devez maintenant maintenir votre liste pendant que vous dessinez, vous devez donc effacer vos données de liste précédentes.

Check it out .. Je crois que U sont capables de montrer Google Map v2

Découvrez la méthode “decodePoly” et “drawPath” dans AsyncTask

Main Imphasis 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{ Ssortingng 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 { private ProgressDialog progressDialog; Ssortingng url; connectAsyncTask(Ssortingng 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 Ssortingng doInBackground(Void... params) { JSONParser jParser = new JSONParser(); Ssortingng json = jParser.getJSONFromUrl(url); return json; } @Override protected void onPostExecute(Ssortingng result) { super.onPostExecute(result); progressDialog.hide(); if (result != null) { drawPath(result); } } } public Ssortingng makeURL(double sourcelat, double sourcelog, double destlat, double destlog) { SsortingngBuilder urlSsortingng = new SsortingngBuilder(); urlSsortingng.append("http://maps.googleapis.com/maps/api/directions/json"); urlSsortingng.append("?origin=");// from urlSsortingng.append(Double.toSsortingng(sourcelat)); urlSsortingng.append(","); urlSsortingng.append(Double.toSsortingng(sourcelog)); urlSsortingng.append("&destination=");// to urlSsortingng.append(Double.toSsortingng(destlat)); urlSsortingng.append(","); urlSsortingng.append(Double.toSsortingng(destlog)); urlSsortingng.append("&sensor=false&mode=driving&alternatives=true"); return urlSsortingng.toSsortingng(); } public class JSONParser { InputStream is = null; JSONObject jObj = null; Ssortingng json = ""; // constructor public JSONParser() { } public Ssortingng getJSONFromUrl(Ssortingng 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); SsortingngBuilder sb = new SsortingngBuilder(); Ssortingng line = null; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } json = sb.toSsortingng(); is.close(); } catch (Exception e) { Log.e("Buffer Error", "Error converting result " + e.toSsortingng()); } return json; } } public void drawPath(Ssortingng 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 ssortingng 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"); Ssortingng encodedSsortingng = overviewPolylines.getSsortingng("points"); List list = decodePoly(encodedSsortingng); 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 decodePoly(Ssortingng encoded) { List poly = new ArrayList(); 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 cela aide. À votre santé!

METTRE À JOUR

consultez ceci .. Créer OnDragListener pour Google Map v2 Fragment

Vérifiez également celle-ci .. Comment dessiner une forme sur le fragment de carte en la touchant avec google map V2

Un peu plus de référence .. Comment obtenir les coordonnées de l'écran à partir du marqueur dans google maps v2 android

Nous avons donc une solution pour dessiner à main levée sur la carte v2. Implémentez GoogleMap.OnMarkerDragListener dans votre activité de 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 les événements tactiles, vous pouvez implémenter GoogleMap.OnMapClickListener et obtenir les coordonnées de son paramètre. J'espère que cela aidera 🙂

c’est google maps API V2 tutoriel:

 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/