如何在Android中的Google地图V2中绘制自由手多边形?

Chi*_*iya 56 android google-maps overlay polygon draw

我想画一个Free Hand Polygon on the Map in Google Map V2.

OverlayMap V1 可以执行此任务,但Google Map已从V2中删除该类.(根据此Google Map V2已删除重叠类).

Google Map V1绘制自由样式多边形的好例子.

在Map V2中,我们可以在Google Official Doc的帮助下以编程方式绘制多边形,但用户应该怎么做?我发现Map V2的答案不明确

我从简单的谷歌地图和绘制多边形开始以编程方式执行此操作并且它正常工作但现在我正在寻找用户可以绘制的方式?我不想根据多边形上的标记绘制.

// 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);
Run Code Online (Sandbox Code Playgroud)

我已就此主题进行了大量的研究和开发,但没有在Map V2中实现这样的完美方法.

一些问题

  • 如何在Map V2中绘制自由式多边形(我们可以使用Map V1)?
  • 有没有任何技巧或替代方案来实现这一目标?如果有,怎么样?
  • 我们可以在地图上获得触摸事件并绘制多边形吗?
  • 在Map V2中可行吗?
  • 触摸事件是否可以返回lat-long数组?
  • 如何根据屏幕坐标获取Lat-long setOnDragListener

与旧版本相比,每个新版本都有额外的东西,所以我希望我也可以在Map v2中实现相同的功能.

我不是要求给我一些示例代码或发布您的代码,只是一些正确的方向和文档.

我提供了我在研究和开发过程中发现的所有文件和证据.

Chi*_*iya 77

在Rnd度过了一整天并测试了一些替代方案后,我找到了解决方案.实际上我已经为同一个问题找到了两个替代方案,但我想建议使用替代方案2,因为与替代方案1相比,这实际上非常容易.

实际上我已经在TheLittleNaruto,AndroidHacker和其他一些开发者和替代2的帮助下在Khan的帮助下找到了替代品1,感谢所有人.

备选方案1

如何在Map V2中绘制自由样式多边形(我们可以使用Map V1)?在Map V2中可行吗?

是的,这是可行的,但你不能直接获得OnTouch()OnDraw()在地图上.因此,我们必须考虑其他方式来实现这一目标.

是否有任何技巧或替代方法来实现这一点,如果是的话如何?

是的,谷歌地图V2不支持OnTouch()OnDraw()使用地图,class="com.google.android.gms.maps.SupportMapFragment"所以我们必须计划自定义片段.

是否可以通过触摸事件返回lat-long数组?

是的,如果我们创建任何自定义地图片段并使用它,我们可以在地图上获得TouchDrag事件.

如何在setOnDragListener的屏幕坐标上获得Lat-long基础?

setOnDragListener将返回屏幕坐标(x,y).现在,有一些技术可以将(x,y)转换为LatLng,它们包括Projection以及PointLatLng.

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:
    }
});
Run Code Online (Sandbox Code Playgroud)

它是如何工作的 ?

正如我之前已经提到的,我们必须创建一个自定义的根视图,并使用它可以在地图上触摸拖动事件.

第1步:我们创建MySupportMapFragment extends SupportMapFragment,我们将其用作我们的.xml文件

 <fragment
        android:id="@+id/map"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        class="pkg_name.MySupportMapFragment" /> 
Run Code Online (Sandbox Code Playgroud)

第2步:创建一个,MapWrapperLayout extends FrameLayout以便我们可以在里面设置Touch或Drag监听器,并使用地图视图嵌入其视图.因此,我们需要一个我们将在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

 }
Run Code Online (Sandbox Code Playgroud)

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:
            }
        });
    }}
Run Code Online (Sandbox Code Playgroud)

参考Link1,Link2

到此为止,我可以根据X,Y屏幕坐标获得LatLong.现在我只需要将它存储在Array中.该数组将用于在地图上绘制,最后它将看起来像一个自由形状的多边形.

在此输入图像描述

我希望这肯定会对你有所帮助.

更新:

备选方案2

我们知道,Frame布局是一个透明的布局,所以我使用Frame Layout实现了这一点.在这种情况下,无需创建自定义片段.我刚刚使用Frame Layout作为根布局.所以基本上我将在根布局中获得触摸事件,这将返回屏幕坐标,因为我们之前已经获得了自定义片段.

现在,我在"Free Draw"中创建了一个Button.因此,当您单击它时,您可以在地图上移动手指并绘制一个自由手多边形,这将禁止您的地图在屏幕上移动.当您重新单击相同按钮时,屏幕将进入理想模式.

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>
Run Code Online (Sandbox Code Playgroud)

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 
Run Code Online (Sandbox Code Playgroud)

//按钮将更改Map可移动状态

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

触摸单击框架布局并执行一些任务

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;

    }
});
Run Code Online (Sandbox Code Playgroud)

//绘制地图

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);
}
Run Code Online (Sandbox Code Playgroud)

但是,现在您必须在绘制时维护列表,因此必须清除以前的列表数据.