Подтвердить что ты не робот

Как нарисовать свободный полигон в карте Google V2 в Android?

Я хочу нарисовать a Free Hand Polygon on the Map in Google Map V2.

Эта задача была возможна с помощью Overlay Map V1, но карта Google удалила этот класс из V2. (Для этого Google Map V2 удаляет класс Overlay).

Хороший пример для Google Map V1 для рисования свободного полигона стиля.

В Map V2 мы можем программно сделать полигон с помощью Официального документа Google, но что должен делать пользователь? Я нашел Непонятный ответ для карты V2

Я начал с простой карты Google и нарисовал полигон, чтобы сделать это программно, и он работает правильно, но теперь я ищу, как пользователь может рисовать? Я не хочу рисовать на основе маркера на многоугольнике.

// 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);

Я провел много исследований и разработок по этой теме, но не получил идеального способа реализовать такую ​​вещь в Map V2.

Некоторые вопросы

  • Как нарисовать многогранный многоугольник в Map V2 (как мы можем сделать с Map V1)?
  • Есть ли какой-либо трюк или альтернатива для достижения этого? Если да, то как?
  • Можем ли мы получить событие касания на карте и нарисовать полигон?
  • Возможно ли это в Map V2?
  • Возможно ли с событием касания, которое возвращает массив lat-long?
  • Как я могу получить Lat-long на основе экранных координат на setOnDragListener?

В каждой новой версии есть что-то дополнительное по сравнению со старым, поэтому я ожидаю, что я тоже смогу добиться того же самого в Map v2.

Я не прошу дать мне пример кода или оставить свой код, просто правильное руководство и документацию.

Я представил все документы и доказательства, которые я нашел во время исследований и разработок.

4b9b3361

Ответ 1

Проведя целый день в Rnd и тестируя некоторые альтернативы, я нашел решение. На самом деле я нашел две альтернативы для одной и той же проблемы, но я хотел бы предложить использовать Альтернатива 2, потому что это действительно очень легко по сравнению с Альтернатива 1.

На самом деле я нашел Альтернативу 1 с помощью TheLittleNaruto, AndroidHacker и некоторые другие разработчики и Альтернатива 2 с помощью Khan, поэтому благодаря всем.

Альтернатива 1

Как рисовать свободный многоугольник стиля в Map V2 (как мы можем сделать с Map V1)? Возможно ли это в Map V2?

Да, это возможно, но вы не можете получить непосредственно OnTouch() и OnDraw() на карте. Поэтому нам нужно подумать о другом способе достижения этого.

Есть ли какой-либо трюк или альтернативный способ достижения этой цели, если да, то как?

Да, Google Map V2 не поддерживает OnTouch() или OnDraw() на Карте с помощью class="com.google.android.gms.maps.SupportMapFragment", поэтому нам нужно планировать настраиваемый фрагмент.

Можно ли вернуть массив lat-long с событием touch?

Да, если мы создадим какой-либо пользовательский фрагмент карты и используем его, мы можем получить это событие Прикоснуться или Перетащить по карте.

Как я могу получить Lat-long base на экранных координатах на setOnDragListener?

setOnDragListener вернет координаты экрана (x, y). Теперь для этого есть несколько методов преобразования (x, y) в LatLng, и они включают Projection вместе с 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:
    }
});

Как это работает?

Как я уже упоминал ранее, мы должны создать пользовательский корневой вид и используя это, мы можем получить Touch или Перетащить События за карту.

Шаг 1: Мы создаем MySupportMapFragment extends SupportMapFragment, и мы будем использовать это как наш .xml файл

 <fragment
        android:id="@+id/map"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        class="pkg_name.MySupportMapFragment" /> 

Шаг 2. Создайте MapWrapperLayout extends FrameLayout, чтобы мы могли установить внутри Touch или Drag listener внутри и встроить его представление с видом карты. Итак, нам нужен один интерфейс, который мы будем использовать в 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:
            }
        });
    }}

Ссылка Link1, Ссылка2

До сих пор я могу получить LatLong на основе X, Y экранных координат. Теперь мне просто нужно сохранить его в Массив. Этот массив будет использоваться для рисования на карте и, наконец, он будет выглядеть как многоугольник свободной формы.

enter image description here

Надеюсь, это определенно поможет вам.

Update:

Альтернатива 2

Как известно, Рамка макета - это прозрачный макет, поэтому я достиг этого с помощью макета кадра. В этом случае нет необходимости создавать пользовательский фрагмент. Я только что использовал Макет кадра как корневой макет. Таким образом, в основном я получаю Touch Events в корневом макете, и это вернет координаты экрана, поскольку мы получили ранее выполненный фрагмент.

Теперь я создал кнопку внутри "Free Draw". Поэтому, когда вы нажимаете на это, вы можете переместить пальцы на карту и нарисовать свободный полигон, и это отключит вашу карту, перемещаемую на экране. При повторном нажатии одной и той же кнопки экран переходит в идеальный режим.

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 

//Кнопка изменяет состояние перемещения карты

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

Нажмите "Нажатие макета кадра" и с помощью выполнения некоторой задачи

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;

    }
});

//Нарисуйте карту

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

Тем не менее, теперь вам нужно сохранить свой список во время рисования, поэтому вам нужно очистить предыдущие данные списка.

Ответ 2

Проверьте это. Я считаю, что U способны показывать Google Map v2

Проверьте метод decodePoly и drawPath в AsyncTask

Основное значение в "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);

Полный класс для справки.

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

    }
}

Надеюсь, это поможет. Ура!

UPDATE

ознакомьтесь с этим. Создание OnDragListener для Google Map v2 Fragment

Также проверьте это. Как нарисовать фигуру на фрагменте карты, коснувшись ее с помощью карты Google V2

Дополнительная информация.. Как получить координаты экрана с маркера в google maps v2 android

Ответ 3

Итак, у нас есть некоторое решение для розыгрыша свободной руки на карте v2. Внесите GoogleMap.OnMarkerDragListener в свою активность на карте. Он переопределит функцию onMarkerDrag.

@Override
public void onMarkerDrag(Marker marker) {

   //add the marker 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));
    }
    }

вы можете передать какой-то взлом для свободной руки, как только пользователь коснется карты, вам придется обнаружить эти координаты и передать их в onMarkerDrag. Поскольку вам придется использовать информацию о зоне для дальнейшего процесса. Для события касания вы можете реализовать GoogleMap.OnMapClickListener и получить координаты из этого параметра. Надеюсь, это поможет:)

Ответ 4

это 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
        );
    }
}

ссылка: https://developers.google.com/maps/documentation/android/