Comment dessiner gratuitement hand polygon dans Google map V2 dans Android?
je veux dessiner un Free Hand Polygon on the Map in Google Map V2
.
cette tâche a été possible avec Overlay
carte V1, mais Google Map a supprimé cette classe de V2. (Pour ce Google Map V2 a Supprimer la classe de superposition ).
bon exemple pour Google Map V1 pour dessiner le polygone de style libre.
dans la carte V2, nous pouvons dessiner un polygone programmatique à L'aide de Google Officiel Doc mais qu'un utilisateur? J'ai trouvé réponse imprécise pour la carte V2
J'ai commencé avec simple google Map & draw polygon pour faire ce programme et il fonctionne correctement, mais maintenant je suis à la recherche de la façon dont un utilisateur peut tirer? Je ne veux pas tirer basées sur le 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 de Développement sur ce sujet, mais n'obtient pas un moyen idéal pour implémenter une telle chose dans la carte V2.
Quelques Questions
- comment dessiner le polygone freestyle dans la carte V2 (comme on peut le faire avec la carte V1)?
- y a-t-il une astuce ou une alternative pour y parvenir? Si oui, comment?
- peut-on obtenir un événement touch sur le polygone map & draw?
- Est-il réalisable dans la Carte V2?
- est - il possible avec un événement tactile qui renvoie un tableau de lat-long?
- Comment puis-je obtenir Lat-long basé sur les coordonnées de l'écran sur
setOnDragListener
?
chaque nouvelle version a quelque chose en plus par rapport à l'ancienne donc je m'attends à pouvoir réaliser la même chose dans la carte v2 aussi.
Je ne demande pas de me donner un exemple de code ou d'afficher votre code, juste quelques directives et documents appropriés.
j'ai fourni tout documents et preuves que j'ai trouvés pendant la recherche et le développement.
4 réponses
après avoir passé toute une journée à Rnd et avoir testé quelques alternatives, j'ai trouvé une solution. En fait, j'ai trouvé deux solutions pour un même problème, mais je voudrais suggérer l'utilisation de Alternative 2 parce que c'est vraiment très facile par rapport à Variante 1 .
en fait, j'ai trouvé Alternative 1 avec l'aide de TheLittleNaruto , AndroidHacker et certains autres développeurs & Alternative 2 avec l'aide de Khan donc merci à tous.
Variante 1
Comment dessiner polygone de style libre dans la carte V2 (comme nous pouvons le faire avec la carte V1) ? Est-ce réalisable dans la carte V2 ?
Oui, c'est faisable, mais vous ne pouvez pas obtenir directement OnTouch()
& OnDraw()
sur la carte. Donc, nous devons avoir à penser à une autre façon d'atteindre cet objectif.
Est-il un truc ou une autre façon de réaliser cette chose , si oui comment ?
Oui, Google Map V2 ne supporte pas OnTouch()
ou OnDraw()
sur une carte utilisant class="com.google.android.gms.maps.SupportMapFragment"
donc nous devons planifier pour un Fragment personnalisé.
est-il possible de retourner le tableau de lat-long avec un événement tactile ?
Oui, si nous créons sur mesure fragment de carte et à l'utilisation, nous pouvons l'obtenir que Touch ou Glisser de l'événement sur la carte.
Comment puis-je obtenir Lat-base longue sur les coordonnées de l'écran sur setOnDragListener ?
setOnDragListener
renvoie les coordonnées de l'écran (x,y) . Et maintenant, il y a quelques techniques pour convertir (x,y) en LatLng et ils comprennent Projection avec Point et 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é, nous devons créer un custom root view et en utilisant que nous pouvons obtenir Touch ou Glisser des Événements sur la carte.
Étape 1: Créer les 1519160920" et nous allons l'utiliser comme notre .fichier xml
<fragment
android:id="@+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="pkg_name.MySupportMapFragment" />
Etape 2: Créer un MapWrapperLayout extends FrameLayout
de sorte que nous puissions définir un Touch or Drag listener à l'intérieur et intégrer sa vue avec vue de carte. Nous avons donc 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'à Ici je suis en mesure d'obtenir LatLong basé sur X,Y coordonnées de l'écran . Maintenant je dois juste stocker dans Array . Ce tableau sera utilisé pour dessiner sur la carte et finalement il ressemblera à un polygone de forme libre.
j'espère que cela va certainement vous aider.
mise à jour:
Alternative 2
comme nous le savons, Frame layout est un mise en page transparente j'ai donc réalisé ceci en utilisant la mise en page de cadre. Dans ce cas, il n'est pas nécessaire de créer un custom fragment. Je viens d'utiliser Frame Layout comme layout racine. Donc en gros, je vais obtenir Touch Events dans la disposition de racine et qui va retourner les coordonnées de l'écran, comme nous avons obtenu dans le fragment personnalisé précédemment.
maintenant, j'ai créé un bouton dans le "Free Draw". Donc quand tu cliques sur ça tu peux bouger tes doigts sur la carte et dessiner un polygone main libre et qui va désactiver votre carte étant mobile à l'écran. Lorsque vous re-cliquez 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
// Bouton pour changer de Carte et mobiliers de l'etat
btn_draw_State.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Is_MAP_Moveable = !Is_MAP_Moveable;
}
});
clic de touche de la disposition du cadre et avec l'aide de le faire certaines tâches
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;
}
});
/ / dessinez votre 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 que vous dessinez, vous devez effacer votre liste précédente des données.
regardez ça .. Je crois que vous êtes en mesure de montrer la carte de Google v2
Check out "decodePoly" et "drawPath" méthode AsyncTask
principal Imphasis in "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 à titre de 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 aidera. Acclamations!
mise à JOUR
regardez ça .. la Création d' OnDragListener pour Google Map V2 Fragment
vérifiez aussi celui-ci .. Comment dessiner une forme sur le fragment de carte en la touchant en utilisant google map V2
encore une référence .. Comment obtenir les coordonnées d'écran de marqueur dans google maps v2 android
donc nous avons une solution pour la main libre dessinez sur la carte v2.
Implémentez GoogleMap.OnMarkerDragListener
dans votre activité map. Ça annulera 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 hack pour main libre comme dès que l'utilisateur touchera la carte, vous aurez à détecter ces coordonnées et le passer à l'onMarkerDrag . Comme vous aurez à utiliser les informations de la zone pour la suite du processus. Pour l'événement touch vous pouvez implémenter GoogleMap.OnMapClickListener
et obtenir le les coordonnées de ce paramètre.
Espérons que cela aidera :)
c'est Google maps API V2 tutorial:
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 /