用于地图的Mapbox touchlistner

时间:2016-09-28 06:10:05

标签: android mapbox

您好我正在使用mapbox在Android应用中显示地图。我陷入了需要获得用户可见的地图半径的情况。如果用户放大或缩小地图的半径会发生变化。任何人都可以告诉我该怎么做或建议我任何有关此

的参考链接

2 个答案:

答案 0 :(得分:1)

要检测地图比例何时发生变化,您需要向MapboxMap添加一个监听器。这是一个扩展MapView的类的示例,它在底部添加一个缩放栏,在地图缩放或平移时动态调整大小(平移将改变距离的比例,但不会以度为单位。)这就是它看起来像:

example of scale bar on Mapbox

有几点:从MapboxMap获取MapView的唯一方法是异步请求它。托管地图的活动或片段应该这样做。此类会覆盖getMapAsync()以允许它获取对MapboxMap的引用,但托管活动仍需要调用该方法。

向监听器报告摄像机更改事件,并且MapboxMap上只能设置一个摄像机更改事件,因此如果托管活动有监听器,则应该在该监听器中调用ScaledMapView#onCameraChange()方法

MapView本身必须包含在FrameLayout中,才能添加比例视图。

显然,您可以在Activity或Fragment中简单地包含相同的基本代码,并在布局中包含缩放TextView,而不是以编程方式添加它。

扩展类:

package com.controlj.test;

import android.content.Context;
import android.location.Location;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;

import java.util.Locale;

/**
 * Created by clyde on 2/10/2016.
 * This class extends the Mapbox Mapview to add a scale at the bottom
 */

public class ScaledMapview extends MapView implements MapboxMap.OnCameraChangeListener, OnMapReadyCallback {
    private TextView scaleText;
    private MapboxMap mapboxMap;
    private OnMapReadyCallback callback;
    private ScaleUnit scaleUnit = ScaleUnit.KM;
    private float labelWidth = 0.33f;

    public float getLabelWidth() {
        return labelWidth;
    }

    public void setLabelWidth(float labelWidth) {
        if(labelWidth > 1f)
            labelWidth = 1f;
        else if(labelWidth < 0.1f)
            labelWidth = 0.1f;
        this.labelWidth = labelWidth;
    }

    public ScaleUnit getScaleUnit() {
        return scaleUnit;
    }

    public void setScaleUnit(ScaleUnit scaleUnit) {
        this.scaleUnit = scaleUnit;
    }

    enum ScaleUnit {
        MILE("mile", 1609.344f),
        NM("nm", 1852.0f),
        KM("km", 1000.0f);

        ScaleUnit(String unit, float ratio) {
            this.unit = unit;
            this.ratio = ratio;
        }

        String unit;
        float ratio;
    }

    public ScaledMapview(@NonNull Context context) {
        super(context);
    }

    public ScaledMapview(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ScaledMapview(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public ScaledMapview(@NonNull Context context, @Nullable MapboxMapOptions options) {
        super(context, options);
    }

    @Override
    public void getMapAsync(OnMapReadyCallback callback) {
        this.callback = callback;
        super.getMapAsync(this);
    }

    /**
     * To ensure this is called when the camera changes, either this ScaledMapview must be passed
     * to mapboxMap.setOnCameraChangeListener() or whatever is listening must also call this method
     * when it is called.
     *
     * @param position The CameraPosition at the end of the last camera change.
     */
    @Override
    public void onCameraChange(CameraPosition position) {
        if (scaleText == null) {
            ViewParent v = getParent();
            if (v instanceof FrameLayout) {
                scaleText = (TextView)inflate(getContext(), R.layout.mapscale, null);
                ((FrameLayout)v).addView(scaleText);
            }
        }
        if (scaleText != null) {
            // compute the horizontal span in metres of the bottom of the map
            LatLngBounds latLngBounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds;
            float span[] = new float[1];
            Location.distanceBetween(latLngBounds.getLatSouth(), latLngBounds.getLonEast(),
                    latLngBounds.getLatSouth(), latLngBounds.getLonWest(), span);

            float totalWidth = span[0] / scaleUnit.ratio;
            // calculate an initial guess at step size
            float tempStep = totalWidth * labelWidth;

            // get the magnitude of the step size
            float mag = (float)Math.floor(Math.log10(tempStep));
            float magPow = (float)Math.pow(10, mag);

            // calculate most significant digit of the new step size
            float magMsd = (int)(tempStep / magPow + 0.5);

            // promote the MSD to either 1, 2, or 5
            if (magMsd > 5.0f)
                magMsd = 10.0f;
            else if (magMsd > 2.0f)
                magMsd = 5.0f;
            else if (magMsd > 1.0f)
                magMsd = 2.0f;
            float length = magMsd * magPow;
            if (length >= 1f)
                scaleText.setText(String.format(Locale.US, "%.0f %s", length, scaleUnit.unit));
            else
                scaleText.setText(String.format(Locale.US, "%.2f %s", length, scaleUnit.unit));
            // set the total width to the appropriate fraction of the display
            int width = Math.round(getWidth() * length / totalWidth);
            LayoutParams layoutParams =
                    new LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
            layoutParams.bottomMargin = 4;
            scaleText.setLayoutParams(layoutParams);
        }
    }

    @Override
    public void onMapReady(MapboxMap mapboxMap) {
        this.mapboxMap = mapboxMap;
        // if the owner of this view is listening for the map, pass it through. If not, we must
        // listen for camera events ourselves.
        if (callback != null)
            callback.onMapReady(mapboxMap);
        else
            mapboxMap.setOnCameraChangeListener(this);
        onCameraChange(null);
    }
}

活动:

package com.controlj.test;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.mapbox.mapboxsdk.MapboxAccountManager;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();
    ScaledMapview mapView;

    @Override
    protected void onStart() {
        Log.d(TAG, "OnStart()");
        super.onStart();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "OnCreate()");
        MapboxAccountManager.start(this, getString(R.string.mapbox_access_token));
        setContentView(R.layout.activity_main);
        mapView = (ScaledMapview)findViewById(R.id.mapview);
        mapView.onCreate(savedInstanceState);
        mapView.getMapAsync(null);
    }
    @Override
    public void onDestroy() {
        Log.d(TAG, "OnDestroy()");
        super.onDestroy();
        mapView.onDestroy();

    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }

    @Override
    public void onPause() {
        Log.d(TAG, "OnPause()");
        mapView.onPause();
        super.onPause();
    }

    @Override
    public void onResume() {
        Log.d(TAG, "OnResume()");
        super.onResume();
        mapView.onResume();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        Log.d(TAG, "OnSaveInstanceState()");
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }
}

活动布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    android:id="@+id/activity_main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.controlj.test.MainActivity">

        <com.controlj.test.ScaledMapview
            android:id="@+id/mapview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            mapbox:access_token="@string/mapbox_access_token"
            mapbox:center_latitude="-31.42166667"
            mapbox:center_longitude="152.75833333"
            mapbox:style_url="@string/mapbox_style"
            mapbox:zoom="4"/>
</FrameLayout>

缩放小部件本身的布局。图像资源@drawable/scale是9补丁图像文件。

<?xml version="1.0" encoding="utf-8"?>
<TextView
    android:id="@+id/scale_text"

    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center|bottom"
    android:textAlignment="center"
    android:background="@drawable/scale"
    android:paddingBottom="2dp"
    android:layout_marginBottom="6dp"
    android:layout_marginTop="0dp"
    android:paddingTop="0dp"
    android:text="100km"/>

答案 1 :(得分:0)

我将假设半径是指当前用户可见的地图距离?如果是这种情况,您可以获得西边界和东边界之间的绝对距离(以度为单位)。

LatLngBounds latLngBounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds;
latLngBounds.getLongitudeSpan();

如果这不是你想要的,请告诉我。