在 Mapbox 地图上自定义绘图 Canvas
Custom Drawing on Mapbox Map Canvas
我希望能够使用 android SDK 在 mapbox 地图上手动绘制复杂的形状。我继承了地图视图 class 并覆盖了 ondraw 事件,但不幸的是,无论我绘制什么,都会被地图本身绘制。
例如,我需要能够在其他复杂形状中绘制具有菱形边框的多边形。这在 GoogleMaps 中使用自定义图块提供程序并覆盖 ondraw 没有问题。
这是我目前唯一的 mapbox 代码:
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint stroke = new Paint();
stroke.setColor(Color.BLACK);
stroke.setStyle(Paint.Style.STROKE);
stroke.setStrokeWidth(5);
stroke.setAntiAlias(true);
canvas.drawLine(0f,0f,1440f,2464f,stroke);
}
如果我没理解错的话,您是想在地图上添加菱形(用户并未绘制该形状)?如果是这种情况,您有几个选择:
使用多边形,只需添加点列表即可绘制形状(在本例中为菱形)。这将是最简单的,但我假设您已经尝试过并且它不适合您。
List<LatLng> polygon = new ArrayList<>();
polygon.add(<LatLng Point 1>);
polygon.add(<LatLng Point 2>);
...
mapboxMap.addPolygon(new PolygonOptions()
.addAll(polygon)
.fillColor(Color.parseColor("#3bb2d0")));
使用 4.2.0(仍处于测试阶段)中引入的新样式 API 添加填充图层。这样做首先需要您创建一个带有点的 GeoJSON 对象,然后将其添加到地图中。我必须这样做的最接近的例子是 this example,在演示应用程序中找到。
使用 onDraw,它只需要将 canvas 转换为 GeoJSON 对象并添加为图层,如第 2 步中所述。我只在您有用户时才推荐这样做在运行时绘制形状,在这种情况下坐标是不确定的。
如果您正在寻找不同的东西,我会编辑这个答案。
你可以通过两种方式做你想做的事:
1) 正如您所建议的:"inherit the MapView
class and overridden the onDraw()
event". 但是 MapView
扩展了 FrameLayout
即 ViewGroup
,所以您应该覆盖 dispatchDraw()
而不是 onDraw()
.
此方法需要自定义视图,它扩展了 MapView
并实现了:
画过MapView
;
自定义线条样式("diamonds instead of a simple line");
到 MapView
的 Lat/Lon
坐标的绑定路径。
为了覆盖 MapView
你应该覆盖 dispatchDraw()
,例如像这样:
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawDiamondsPath(canvas);
canvas.restore();
}
自定义线条样式可以使用Paint
class的setPathEffect()方法。为此,您应该为 "diamond stamp"(以像素为单位)创建路径,该路径将每隔 "advance"(也以像素为单位)重复:
mPathDiamondStamp = new Path();
mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2, 0);
mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2);
mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2, 0);
mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2);
mPathDiamondStamp.close();
mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2 + DIAMOND_BORDER_WIDTH, 0);
mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2 + DIAMOND_BORDER_WIDTH / 2);
mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2 - DIAMOND_BORDER_WIDTH, 0);
mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2 - DIAMOND_BORDER_WIDTH / 2);
mPathDiamondStamp.close();
mPathDiamondStamp.setFillType(Path.FillType.EVEN_ODD);
mDiamondPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDiamondPaint.setColor(Color.BLUE);
mDiamondPaint.setStrokeWidth(2);
mDiamondPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mDiamondPaint.setStyle(Paint.Style.STROKE);
mDiamondPaint.setPathEffect(new PathDashPathEffect(mPathDiamondStamp, DIAMOND_ADVANCE, DIAMOND_PHASE, PathDashPathEffect.Style.ROTATE));
(在这种情况下,有 2 个 Path
- 第一个(顺时针)用于外边框,第二个(逆时针)用于 "diamond" 透明 "hole" 的内边框)。
为了将屏幕上的路径绑定到 MapView
的 Lat/Lon
坐标,您应该具有 MapView
的 MapboxMap
对象 - 对于 getMapAsync()
和 onMapReady()
应该被覆盖:
@Override
public void getMapAsync(OnMapReadyCallback callback) {
mMapReadyCallback = callback;
super.getMapAsync(this);
}
@Override
public void onMapReady(MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
if (mMapReadyCallback != null) {
mMapReadyCallback.onMapReady(mapboxMap);
}
}
你可以在 "lat/lon-to-screen" 转换中使用它:
mBorderPath = new Path();
LatLng firstBorderPoint = mBorderPoints.get(0);
PointF firstScreenPoint = mMapboxMap.getProjection().toScreenLocation(firstBorderPoint);
mBorderPath.moveTo(firstScreenPoint.x, firstScreenPoint.y);
for (int ixPoint = 1; ixPoint < mBorderPoints.size(); ixPoint++) {
PointF currentScreenPoint = mMapboxMap.getProjection().toScreenLocation(mBorderPoints.get(ixPoint));
mBorderPath.lineTo(currentScreenPoint.x, currentScreenPoint.y);
}
完整源代码:
自定义DrawMapView.java
public class DrawMapView extends MapView implements OnMapReadyCallback{
private float DIAMOND_WIDTH = 42;
private float DIAMOND_HEIGHT = 18;
private float DIAMOND_ADVANCE = 1.5f * DIAMOND_WIDTH; // spacing between each stamp of shape
private float DIAMOND_PHASE = DIAMOND_WIDTH / 2; // amount to offset before the first shape is stamped
private float DIAMOND_BORDER_WIDTH = 6; // width of diamond border
private Path mBorderPath;
private Path mPathDiamondStamp;
private Paint mDiamondPaint;
private OnMapReadyCallback mMapReadyCallback;
private MapboxMap mMapboxMap = null;
private List<LatLng> mBorderPoints;
public DrawMapView(@NonNull Context context) {
super(context);
init();
}
public DrawMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public DrawMapView(@NonNull Context context, @Nullable MapboxMapOptions options) {
super(context, options);
init();
}
public void setBorderPoints(List<LatLng> borderPoints) {
mBorderPoints = borderPoints;
}
@Override
public void getMapAsync(OnMapReadyCallback callback) {
mMapReadyCallback = callback;
super.getMapAsync(this);
}
@Override
public void onMapReady(MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
if (mMapReadyCallback != null) {
mMapReadyCallback.onMapReady(mapboxMap);
}
}
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawDiamondsPath(canvas);
canvas.restore();
}
private void drawDiamondsPath(Canvas canvas) {
if (mBorderPoints == null || mBorderPoints.size() == 0) {
return;
}
mBorderPath = new Path();
LatLng firstBorderPoint = mBorderPoints.get(0);
PointF firstScreenPoint = mMapboxMap.getProjection().toScreenLocation(firstBorderPoint);
mBorderPath.moveTo(firstScreenPoint.x, firstScreenPoint.y);
for (int ixPoint = 1; ixPoint < mBorderPoints.size(); ixPoint++) {
PointF currentScreenPoint = mMapboxMap.getProjection().toScreenLocation(mBorderPoints.get(ixPoint));
mBorderPath.lineTo(currentScreenPoint.x, currentScreenPoint.y);
}
mPathDiamondStamp = new Path();
mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2, 0);
mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2);
mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2, 0);
mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2);
mPathDiamondStamp.close();
mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2 + DIAMOND_BORDER_WIDTH, 0);
mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2 + DIAMOND_BORDER_WIDTH / 2);
mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2 - DIAMOND_BORDER_WIDTH, 0);
mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2 - DIAMOND_BORDER_WIDTH / 2);
mPathDiamondStamp.close();
mPathDiamondStamp.setFillType(Path.FillType.EVEN_ODD);
mDiamondPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDiamondPaint.setColor(Color.BLUE);
mDiamondPaint.setStrokeWidth(2);
mDiamondPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mDiamondPaint.setStyle(Paint.Style.STROKE);
mDiamondPaint.setPathEffect(new PathDashPathEffect(mPathDiamondStamp, DIAMOND_ADVANCE, DIAMOND_PHASE, PathDashPathEffect.Style.ROTATE));
canvas.drawPath(mBorderPath, mDiamondPaint);
}
private void init() {
mBorderPath = new Path();
mPathDiamondStamp = new Path();
}
}
ActivityMain.java
public class MainActivity extends AppCompatActivity {
private DrawMapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MapboxAccountManager.start(this, getString(R.string.access_token));
setContentView(R.layout.activity_main);
mapView = (DrawMapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
mapView.setBorderPoints(Arrays.asList(new LatLng(-36.930129, 174.958843),
new LatLng(-36.877860, 174.978108),
new LatLng(-36.846373, 174.901841),
new LatLng(-36.829215, 174.814659),
new LatLng(-36.791326, 174.779337),
new LatLng(-36.767680, 174.823242)));
}
});
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context="ua.com.omelchenko.mapboxlines.MainActivity">
<ua.com.omelchenko.mapboxlines.DrawMapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:center_latitude="-36.841362"
mapbox:center_longitude="174.851110"
mapbox:style_url="@string/style_mapbox_streets"
mapbox:zoom="10"/>
</RelativeLayout>
最后,结果,你应该得到这样的东西:
并且你应该考虑一些"special cases",例如,如果路径的所有点都在当前地图视图之外,则上面没有线,甚至线应该穿过地图视图并且应该是可见的.
2)(更好的方法)创建并发布带有您的额外线路的地图,并为此 custom style for them (especially take a look at "Line patterns with Images" sections). You can use Mapbox Studio。在这种方法中,所有 "special cases" 和性能问题都在 Mabpox 端得到解决。
我希望能够使用 android SDK 在 mapbox 地图上手动绘制复杂的形状。我继承了地图视图 class 并覆盖了 ondraw 事件,但不幸的是,无论我绘制什么,都会被地图本身绘制。
例如,我需要能够在其他复杂形状中绘制具有菱形边框的多边形。这在 GoogleMaps 中使用自定义图块提供程序并覆盖 ondraw 没有问题。
这是我目前唯一的 mapbox 代码:
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint stroke = new Paint();
stroke.setColor(Color.BLACK);
stroke.setStyle(Paint.Style.STROKE);
stroke.setStrokeWidth(5);
stroke.setAntiAlias(true);
canvas.drawLine(0f,0f,1440f,2464f,stroke);
}
如果我没理解错的话,您是想在地图上添加菱形(用户并未绘制该形状)?如果是这种情况,您有几个选择:
使用多边形,只需添加点列表即可绘制形状(在本例中为菱形)。这将是最简单的,但我假设您已经尝试过并且它不适合您。
List<LatLng> polygon = new ArrayList<>(); polygon.add(<LatLng Point 1>); polygon.add(<LatLng Point 2>); ... mapboxMap.addPolygon(new PolygonOptions() .addAll(polygon) .fillColor(Color.parseColor("#3bb2d0")));
使用 4.2.0(仍处于测试阶段)中引入的新样式 API 添加填充图层。这样做首先需要您创建一个带有点的 GeoJSON 对象,然后将其添加到地图中。我必须这样做的最接近的例子是 this example,在演示应用程序中找到。
使用 onDraw,它只需要将 canvas 转换为 GeoJSON 对象并添加为图层,如第 2 步中所述。我只在您有用户时才推荐这样做在运行时绘制形状,在这种情况下坐标是不确定的。
如果您正在寻找不同的东西,我会编辑这个答案。
你可以通过两种方式做你想做的事:
1) 正如您所建议的:"inherit the MapView
class and overridden the onDraw()
event". 但是 MapView
扩展了 FrameLayout
即 ViewGroup
,所以您应该覆盖 dispatchDraw()
而不是 onDraw()
.
此方法需要自定义视图,它扩展了 MapView
并实现了:
画过
MapView
;自定义线条样式("diamonds instead of a simple line");
到
MapView
的Lat/Lon
坐标的绑定路径。
为了覆盖 MapView
你应该覆盖 dispatchDraw()
,例如像这样:
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawDiamondsPath(canvas);
canvas.restore();
}
自定义线条样式可以使用Paint
class的setPathEffect()方法。为此,您应该为 "diamond stamp"(以像素为单位)创建路径,该路径将每隔 "advance"(也以像素为单位)重复:
mPathDiamondStamp = new Path();
mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2, 0);
mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2);
mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2, 0);
mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2);
mPathDiamondStamp.close();
mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2 + DIAMOND_BORDER_WIDTH, 0);
mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2 + DIAMOND_BORDER_WIDTH / 2);
mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2 - DIAMOND_BORDER_WIDTH, 0);
mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2 - DIAMOND_BORDER_WIDTH / 2);
mPathDiamondStamp.close();
mPathDiamondStamp.setFillType(Path.FillType.EVEN_ODD);
mDiamondPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDiamondPaint.setColor(Color.BLUE);
mDiamondPaint.setStrokeWidth(2);
mDiamondPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mDiamondPaint.setStyle(Paint.Style.STROKE);
mDiamondPaint.setPathEffect(new PathDashPathEffect(mPathDiamondStamp, DIAMOND_ADVANCE, DIAMOND_PHASE, PathDashPathEffect.Style.ROTATE));
(在这种情况下,有 2 个 Path
- 第一个(顺时针)用于外边框,第二个(逆时针)用于 "diamond" 透明 "hole" 的内边框)。
为了将屏幕上的路径绑定到 MapView
的 Lat/Lon
坐标,您应该具有 MapView
的 MapboxMap
对象 - 对于 getMapAsync()
和 onMapReady()
应该被覆盖:
@Override
public void getMapAsync(OnMapReadyCallback callback) {
mMapReadyCallback = callback;
super.getMapAsync(this);
}
@Override
public void onMapReady(MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
if (mMapReadyCallback != null) {
mMapReadyCallback.onMapReady(mapboxMap);
}
}
你可以在 "lat/lon-to-screen" 转换中使用它:
mBorderPath = new Path();
LatLng firstBorderPoint = mBorderPoints.get(0);
PointF firstScreenPoint = mMapboxMap.getProjection().toScreenLocation(firstBorderPoint);
mBorderPath.moveTo(firstScreenPoint.x, firstScreenPoint.y);
for (int ixPoint = 1; ixPoint < mBorderPoints.size(); ixPoint++) {
PointF currentScreenPoint = mMapboxMap.getProjection().toScreenLocation(mBorderPoints.get(ixPoint));
mBorderPath.lineTo(currentScreenPoint.x, currentScreenPoint.y);
}
完整源代码:
自定义DrawMapView.java
public class DrawMapView extends MapView implements OnMapReadyCallback{
private float DIAMOND_WIDTH = 42;
private float DIAMOND_HEIGHT = 18;
private float DIAMOND_ADVANCE = 1.5f * DIAMOND_WIDTH; // spacing between each stamp of shape
private float DIAMOND_PHASE = DIAMOND_WIDTH / 2; // amount to offset before the first shape is stamped
private float DIAMOND_BORDER_WIDTH = 6; // width of diamond border
private Path mBorderPath;
private Path mPathDiamondStamp;
private Paint mDiamondPaint;
private OnMapReadyCallback mMapReadyCallback;
private MapboxMap mMapboxMap = null;
private List<LatLng> mBorderPoints;
public DrawMapView(@NonNull Context context) {
super(context);
init();
}
public DrawMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public DrawMapView(@NonNull Context context, @Nullable MapboxMapOptions options) {
super(context, options);
init();
}
public void setBorderPoints(List<LatLng> borderPoints) {
mBorderPoints = borderPoints;
}
@Override
public void getMapAsync(OnMapReadyCallback callback) {
mMapReadyCallback = callback;
super.getMapAsync(this);
}
@Override
public void onMapReady(MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
if (mMapReadyCallback != null) {
mMapReadyCallback.onMapReady(mapboxMap);
}
}
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawDiamondsPath(canvas);
canvas.restore();
}
private void drawDiamondsPath(Canvas canvas) {
if (mBorderPoints == null || mBorderPoints.size() == 0) {
return;
}
mBorderPath = new Path();
LatLng firstBorderPoint = mBorderPoints.get(0);
PointF firstScreenPoint = mMapboxMap.getProjection().toScreenLocation(firstBorderPoint);
mBorderPath.moveTo(firstScreenPoint.x, firstScreenPoint.y);
for (int ixPoint = 1; ixPoint < mBorderPoints.size(); ixPoint++) {
PointF currentScreenPoint = mMapboxMap.getProjection().toScreenLocation(mBorderPoints.get(ixPoint));
mBorderPath.lineTo(currentScreenPoint.x, currentScreenPoint.y);
}
mPathDiamondStamp = new Path();
mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2, 0);
mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2);
mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2, 0);
mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2);
mPathDiamondStamp.close();
mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2 + DIAMOND_BORDER_WIDTH, 0);
mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2 + DIAMOND_BORDER_WIDTH / 2);
mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2 - DIAMOND_BORDER_WIDTH, 0);
mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2 - DIAMOND_BORDER_WIDTH / 2);
mPathDiamondStamp.close();
mPathDiamondStamp.setFillType(Path.FillType.EVEN_ODD);
mDiamondPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDiamondPaint.setColor(Color.BLUE);
mDiamondPaint.setStrokeWidth(2);
mDiamondPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mDiamondPaint.setStyle(Paint.Style.STROKE);
mDiamondPaint.setPathEffect(new PathDashPathEffect(mPathDiamondStamp, DIAMOND_ADVANCE, DIAMOND_PHASE, PathDashPathEffect.Style.ROTATE));
canvas.drawPath(mBorderPath, mDiamondPaint);
}
private void init() {
mBorderPath = new Path();
mPathDiamondStamp = new Path();
}
}
ActivityMain.java
public class MainActivity extends AppCompatActivity {
private DrawMapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MapboxAccountManager.start(this, getString(R.string.access_token));
setContentView(R.layout.activity_main);
mapView = (DrawMapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
mapView.setBorderPoints(Arrays.asList(new LatLng(-36.930129, 174.958843),
new LatLng(-36.877860, 174.978108),
new LatLng(-36.846373, 174.901841),
new LatLng(-36.829215, 174.814659),
new LatLng(-36.791326, 174.779337),
new LatLng(-36.767680, 174.823242)));
}
});
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context="ua.com.omelchenko.mapboxlines.MainActivity">
<ua.com.omelchenko.mapboxlines.DrawMapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:center_latitude="-36.841362"
mapbox:center_longitude="174.851110"
mapbox:style_url="@string/style_mapbox_streets"
mapbox:zoom="10"/>
</RelativeLayout>
最后,结果,你应该得到这样的东西:
并且你应该考虑一些"special cases",例如,如果路径的所有点都在当前地图视图之外,则上面没有线,甚至线应该穿过地图视图并且应该是可见的.
2)(更好的方法)创建并发布带有您的额外线路的地图,并为此 custom style for them (especially take a look at "Line patterns with Images" sections). You can use Mapbox Studio。在这种方法中,所有 "special cases" 和性能问题都在 Mabpox 端得到解决。