android - 按照设备屏幕上的手指运动路径在 map 上绘制路径

标签 android google-maps overlay google-maps-api-2

1)我想根据我在 map 区域上的手指触摸点在谷歌地图上绘制一条运动路径。 2)从位于路径内的 map 中获取所选区域。

任何人都知道如何实现它。

作为引用想做一些类似的事情:-

enter image description here

最佳答案

我已经为我的一个应用程序实现了相同的功能,希望对您有所帮助,我是在折线和多边形的帮助下完成的。

activity_main.xml

 <RelativeLayout 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" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <fragment
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/map"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            class="com.google.android.gms.maps.SupportMapFragment" />

        <View
            android:id="@+id/drawer_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent" />

        <Button
            android:id="@+id/draw_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="drawZone"
            android:padding="10dp"
            android:text="Draw" />
    </RelativeLayout>

</RelativeLayout>

下面的类将涵盖在 Google map v2 中绘制自定义区域的完整代码

MainActivity.java

    import java.util.ArrayList;
    import android.graphics.Color;
    import android.graphics.Point;
    import android.os.Bundle;
    import android.support.v4.app.FragmentActivity;
    import android.util.Log;
    import android.view.GestureDetector;
    import android.view.GestureDetector.SimpleOnGestureListener;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnTouchListener;
    import android.widget.Toast;

    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.SupportMapFragment;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.PolygonOptions;
    import com.google.android.gms.maps.model.PolylineOptions;

    public class MainActivity extends FragmentActivity implements OnTouchListener {

        private static final String TAG = "polygon";
        private GoogleMap mGoogleMap;
        private View mMapShelterView;
        private GestureDetector mGestureDetector;
        private ArrayList<LatLng> mLatlngs = new ArrayList<LatLng>();
        private PolylineOptions mPolylineOptions;
        private PolygonOptions mPolygonOptions;
        // flag to differentiate whether user is touching to draw or not
        private boolean mDrawFinished = false;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mMapShelterView = (View) findViewById(R.id.drawer_view);
            mGestureDetector = new GestureDetector(this, new GestureListener());
            mMapShelterView.setOnTouchListener(this);
            initilizeMap();
        }

        private final class GestureListener extends SimpleOnGestureListener {
            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                    float velocityY) {
                return false;
            }
        }

        /**
         * Ontouch event will draw poly line along the touch points
         * 
         */
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int X1 = (int) event.getX();
            int Y1 = (int) event.getY();
            Point point = new Point();
            point.x = X1;
            point.y = Y1;
            LatLng firstGeoPoint = mGoogleMap.getProjection().fromScreenLocation(
                    point);
            switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                break;

            case MotionEvent.ACTION_MOVE:
                if (mDrawFinished) {
                    X1 = (int) event.getX();
                    Y1 = (int) event.getY();
                    point = new Point();
                    point.x = X1;
                    point.y = Y1;
                    LatLng geoPoint = mGoogleMap.getProjection()
                            .fromScreenLocation(point);
                    mLatlngs.add(geoPoint);
                    mPolylineOptions = new PolylineOptions();
                    mPolylineOptions.color(Color.RED);
                    mPolylineOptions.width(3);
                    mPolylineOptions.addAll(mLatlngs);
                    mGoogleMap.addPolyline(mPolylineOptions);
                }
                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "Poinnts array size " + mLatlngs.size());
                mLatlngs.add(firstGeoPoint);
                mGoogleMap.clear();
                mPolylineOptions = null;
                mMapShelterView.setVisibility(View.GONE);
                mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
                mGoogleMap.getUiSettings().setAllGesturesEnabled(true);
                mPolygonOptions = new PolygonOptions();
                mPolygonOptions.fillColor(Color.GRAY);
                mPolygonOptions.strokeColor(Color.RED);
                mPolygonOptions.strokeWidth(5);
                mPolygonOptions.addAll(mLatlngs);
                mGoogleMap.addPolygon(mPolygonOptions);
                mDrawFinished = false;
                break;
            }
            return mGestureDetector.onTouchEvent(event);
        }

        /**
         * Setting up map
         * 
         */

        private void initilizeMap() {
            int status = GooglePlayServicesUtil
                    .isGooglePlayServicesAvailable(getApplicationContext());
            if (status == ConnectionResult.SUCCESS) {
                if (mGoogleMap == null) {
                    mGoogleMap = ((SupportMapFragment) getSupportFragmentManager()
                            .findFragmentById(R.id.map)).getMap();
                    mGoogleMap.setMyLocationEnabled(true);

                }

            } else if (GooglePlayServicesUtil.isUserRecoverableError(status)) {
                // showErrorDialog(status);
            } else {
                Toast.makeText(this, "No Support for Google Play Service",
                        Toast.LENGTH_LONG).show();
            }
        }

        /**
         * Method gets called on tap of draw button, It prepares the screen to draw
         * the polygon
         * 
         * @param view
         */

        public void drawZone(View view) {
            mGoogleMap.clear();
            mLatlngs.clear();
            mPolylineOptions = null;
            mPolygonOptions = null;
            mDrawFinished = true;
            mMapShelterView.setVisibility(View.VISIBLE);
            mGoogleMap.getUiSettings().setScrollGesturesEnabled(false);
        }

    }

希望上面的代码足以在 map v2 中绘制自定义区域。 为了检测特定点是否在自定义区域内,我们可以使用以下代码 fragment ,

public synchronized boolean Contains(Location location) {
        boolean isInside = false;
        if (mLatlngs.size() > 0) {
            LatLng lastPoint = mLatlngs.get(mLatlngs.size() - 1);

            double x = location.getLongitude();

            for (LatLng point : mLatlngs) {
                double x1 = lastPoint.longitude;
                double x2 = point.longitude;
                double dx = x2 - x1;

                if (Math.abs(dx) > 180.0) {
                    if (x > 0) {
                        while (x1 < 0)
                            x1 += 360;
                        while (x2 < 0)
                            x2 += 360;
                    } else {
                        while (x1 > 0)
                            x1 -= 360;
                        while (x2 > 0)
                            x2 -= 360;
                    }
                    dx = x2 - x1;
                }

                if ((x1 <= x && x2 > x) || (x1 >= x && x2 < x)) {
                    double grad = (point.latitude - lastPoint.latitude) / dx;
                    double intersectAtLat = lastPoint.latitude
                            + ((x - x1) * grad);

                    if (intersectAtLat > location.getLatitude())
                        isInside = !isInside;
                }
                lastPoint = point;
            }
        }

        return isInside;
    }

您可以将location参数传递给该方法,它会返回该位置是否在自定义区域内。

list .xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.testdraw"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

    <permission
        android:name=".permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="in.wptrafficanalyzer.locationingooglemapv2.permission.MAPS_RECEIVE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="AIzaSyDkYvXC1pmSiBrt5Ja3F6gk-wBwIMuDNwo" />
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
    </application>

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

</manifest>

关于android - 按照设备屏幕上的手指运动路径在 map 上绘制路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26601425/

相关文章:

image - 如何使输出 gif 与 ffmpeg 中的输入 gif 长度相同

java - Android findViewById 时出现 NullPointerException

java - Firebase 填充 recyclerview 错误 : com. firebase.client.FirebaseException: Failed to bounce to type

android - SupportMapFragment 中如何使用深色模式?

javascript - 来自 JSON 数据的 Google map 标记未呈现标记

iphone - 有没有办法可以在 iPhone SDK 上制作叠加 View ?

javascript - 关闭滚动覆盖

java - 如何实现 android fab 快速拨号选择器?

android - BroadcastReceiver 仅触发第二次

ios - 异常 :Google Maps SDK for iOS must be initialized via [GMSServices provideAPIKey:. ..] 使用前