您好我正在使用mapbox在Android应用中显示地图。我陷入了需要获得用户可见的地图半径的情况。如果用户放大或缩小地图的半径会发生变化。任何人都可以告诉我该怎么做或建议我任何有关此
的参考链接答案 0 :(得分:1)
要检测地图比例何时发生变化,您需要向MapboxMap
添加一个监听器。这是一个扩展MapView
的类的示例,它在底部添加一个缩放栏,在地图缩放或平移时动态调整大小(平移将改变距离的比例,但不会以度为单位。)这就是它看起来像:
有几点:从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();
如果这不是你想要的,请告诉我。