Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing freely by fingers on Google Map

I want to implement a custom module for free drawing on Google Map. When it comes to the implementation, I have found that the Google Map onDrag() callback and always overrides my custom onDrag() function. I am not so sure how to use my FrameLayout onDrag() to override the map click and drag motion.

Here is my working:

XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/locinfo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.example.androidmapsv2.CustomMapFragment" >
    </fragment>

    <FrameLayout
        android:id="@+id/fram_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </FrameLayout>

</LinearLayout>

CustomMapFragment.java

package com.example.androidmapsv2;

import com.google.android.gms.maps.MapFragment;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class CustomMapFragment extends MapFragment {
     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;
    }

}

MainActivity.java

package com.example.androidmapsv2;

import java.util.ArrayList;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.Projection;
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.Polygon;
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.android.gms.maps.model.PolylineOptions;

import android.app.Activity;
import android.app.FragmentManager;
import android.graphics.Color;
import android.graphics.Point;
import android.location.Location;
import android.os.Bundle;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity 
    implements OnMapClickListener {

    final int RQS_GooglePlayServices = 1;
    private GoogleMap myMap;

    Location myLocation;
    TextView tvLocInfo;
    ArrayList<LatLng> val = new ArrayList<LatLng>();  
    boolean markerClicked;
    PolygonOptions polygonOptions;
    Polygon polygon;
    FrameLayout fram_map;
    CustomMapFragment myMapFragment ;
    boolean Is_MAP_Moveable;  
    Projection projection;
    public double latitude;
    public double longitude;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvLocInfo = (TextView)findViewById(R.id.locinfo);

        FragmentManager myFragmentManager = getFragmentManager();
         myMapFragment 
            = (CustomMapFragment)myFragmentManager.findFragmentById(R.id.map);

        if (myMapFragment != null) {

            myMapFragment.getMapAsync(new OnMapReadyCallback() {
                @Override
                public void onMapReady(GoogleMap map) {
                    loadMap(map);
                }
            });


            fram_map = (FrameLayout) findViewById(R.id.fram_map);
            Is_MAP_Moveable = false; // to detect map is movable 



        } else {
            Toast.makeText(this, "Error - Map Fragment was null!!", Toast.LENGTH_SHORT).show();

        }


    }

    public void Draw_Map() {


        myMap.addPolyline(new PolylineOptions()
                .addAll(val)
                .color(Color.parseColor( "#0971b2")).width(10f));

    }


    protected void loadMap(GoogleMap map) {
        // TODO Auto-generated method stub
        myMap = map;
        myMap.setMyLocationEnabled(true);

        myMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);

        myMap.setOnMapClickListener(this);
        //myMap.setOnMapLongClickListener(this);
        //myMap.setOnMarkerClickListener(this);

        markerClicked = false;
        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 = myMap.getProjection();
                Point x_y_points = new Point(x_co, y_co);

                LatLng latLng = myMap.getProjection().fromScreenLocation(x_y_points);
                latitude = latLng.latitude;

                longitude = latLng.longitude;

                switch (event.getAction()) {
                    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:
                       v.performClick();

                        // finger leaves the screen
                         Draw_Map();
                        break;
                }

                if (Is_MAP_Moveable == true) {
                    return true;

                } else {
                    return false;
                }
            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }


    @Override
    protected void onResume() {

        super.onResume();

        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());

        if (resultCode == ConnectionResult.SUCCESS){
            Toast.makeText(getApplicationContext(), 
                    "isGooglePlayServicesAvailable SUCCESS", 
                    Toast.LENGTH_LONG).show();
        }else{
            GooglePlayServicesUtil.getErrorDialog(resultCode, this, RQS_GooglePlayServices);
        }

    }

    @Override
    public void onMapClick(LatLng point) {

        Is_MAP_Moveable = !Is_MAP_Moveable;
        Toast.makeText(getApplicationContext(), 
                Is_MAP_Moveable ? "drawing activated" : "drawing disabled", 
                Toast.LENGTH_SHORT).show();
//      tvLocInfo.setText(point.toString());
//      myMap.animateCamera(CameraUpdateFactory.newLatLng(point));
//      
//      markerClicked = false;
    }

//  @Override
//  public void onMapLongClick(LatLng point) {
//      tvLocInfo.setText("New marker added@" + point.toString());
//      myMap.addMarker(new MarkerOptions().position(point).title(point.toString()));
//      
//      markerClicked = false;
//  }
//
//  @Override
//  public boolean onMarkerClick(Marker marker) {
//      
//      if(markerClicked){
//          
//          if(polygon != null){
//              polygon.remove();
//              polygon = null;
//          }
//          
//          polygonOptions.add(marker.getPosition());
//          polygonOptions.strokeColor(Color.RED);
//          polygonOptions.fillColor(Color.BLUE);
//          polygon = myMap.addPolygon(polygonOptions);
//      }else{
//          if(polygon != null){
//              polygon.remove();
//              polygon = null;
//          }
//          
//          polygonOptions = new PolygonOptions().add(marker.getPosition());
//          markerClicked = true;
//      }
//      
//      return true;
//  }

}
like image 204
Raju yourPepe Avatar asked Aug 12 '16 09:08

Raju yourPepe


People also ask

Is there a drawing tool on Google Maps?

Add line or shape. Select a layer and click where to start drawing. A layer can have 2,000 lines, shapes or places. Click each corner or bend of your line or shape. To move the map, click and hold the mouse.

Can you draw free Google Maps?

Scribble Maps is an interesting mash-up that turns Google Maps into an online whiteboard. It adds common drawing and painting tools such as pencils, lines and colored brushes to the Google Maps interfaces so you can easily sketch freehand drawings, insert text, or even add custom shapes anywhere on the map.

How do I draw on Google Maps app?

My Maps in a browser: Plot the points > Draw a line > Add Driving Route. Use mouse to draw route. Mark current location: Create a map; type your address in the search bar. The Android My Maps app is no longer available; however, you can use My Maps in a mobile browser on your device.

Can I draw on a Google Earth map?

To draw the line or shape you want, click a start point on the map and drag. Click an endpoint. Then, enter a description and properties. Click OK.


1 Answers

One way can be to create a View over your map and create an OnTouchListener for this View to intercept map touches:

activity_maps.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.google.android.gms.maps.SupportMapFragment" />

    <View
        android:id="@+id/draggable"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true" />

</RelativeLayout>

MapsActivity.java

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
    private GoogleMap mMap;
    private View draggableView;
    private List<LatLng> polylinePoints = new ArrayList<>();
    private Polyline polyline;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        draggableView = findViewById(R.id.draggable);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        draggableView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                LatLng position = mMap.getProjection().fromScreenLocation(
                        new Point((int) motionEvent.getX(), (int) motionEvent.getY()));

                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                    if (polyline != null) {
                        polyline.remove();
                        polyline = null;
                    }
                    polyline = mMap.addPolyline(
                            new PolylineOptions().color(Color.RED).addAll(polylinePoints));
                } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE){
                    polylinePoints.add(position);
                    polyline.setPoints(polylinePoints);
                } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                    // Close the polyline?
                }
                return true;
            }
        });
    }
}
like image 189
antonio Avatar answered Oct 04 '22 10:10

antonio