Android开发,MapBox的使用及部分功能实现(二)----- draw、layer、以及一些杂的知识点

接上一节
 Android开发,MapBox的使用及部分功能实现(一)----- 初始化、标记、定位、styleurl

 上一节,主要写了最基本的时候,这一篇准备写一写更深一点的内容

一些很杂的知识点
设置地图UI

就是修改地图上一些你不喜欢的东西,比如说左下角的logo,以及一个提示按钮,右上角的罗盘,地图可以调整角度,又可以旋转,太乱了这种

代码如下

        UiSettings uiSettings = mMapboxMap.getUiSettings();
        uiSettings.setCompassEnabled(false);//隐藏指南针
        uiSettings.setLogoEnabled(false);//隐藏logo
        uiSettings.setTiltGesturesEnabled(true);//设置是否可以调整地图倾斜角
        uiSettings.setRotateGesturesEnabled(true);//设置是否可以旋转地图
        uiSettings.setAttributionEnabled(false);//设置是否显示那个提示按钮

很简单,注释都写好了


绘制线和面
绘制polyline

List polyline = new ArrayList<>();
                polyline.add(new LatLng(26.1564854, 103.156741));
                polyline.add(new LatLng(24.1255854, 108.254741));
                polyline.add(new LatLng(29.1114854, 102.241741));
                polyline.add(new LatLng(26.5764854, 107.272741));
                polyline.add(new LatLng(21.7874854, 104.278741));
                polyline.add(new LatLng(25.0044854, 106.782741));
                polyline.add(new LatLng(20.7174854, 106.014741));
                polyline.add(new LatLng(33.7684854, 103.520741));
                polyline.add(new LatLng(30.1274854, 108.104741));
                polyline.add(new LatLng(28.4174854, 101.000741));
                mapboxMap.addPolyline(new PolylineOptions()
                        .addAll(polyline)
                        .color(ContextCompat.getColor(PolygonActivity.this, R.color.seagreen))
                        .alpha(0.5f)
                        .width(2));
                return true;


如上,很简单,调用addPolyline就可以了,另外,还可以调用addPolylines,即可以同时添加多条线

颜色,透明度,宽度,这些就就不说了

Android开发,MapBox的使用及部分功能实现(二)----- draw、layer、以及一些杂的知识点_第1张图片

绘制polygon

绘制polygon,也就是我们说的图斑

和polyline差不多

List polygon = new ArrayList<>();
                polygon.add(new LatLng(26.1564854, 103.156741));
                polygon.add(new LatLng(24.1255854, 108.254741));
                polygon.add(new LatLng(29.1114854, 102.241741));
                polygon.add(new LatLng(26.5764854, 107.272741));
                polygon.add(new LatLng(21.7874854, 104.278741));
                polygon.add(new LatLng(25.0044854, 106.782741));
                polygon.add(new LatLng(20.7174854, 106.014741));
                polygon.add(new LatLng(33.7684854, 103.520741));
                polygon.add(new LatLng(30.1274854, 108.104741));
                polygon.add(new LatLng(28.4174854, 101.000741));
                mapboxMap.addPolygon(new PolygonOptions()
                        .addAll(polygon)
                        .fillColor(ContextCompat.getColor(PolygonActivity.this, R.color.blueviolet))
                        .alpha(0.5f)
                        .strokeColor(ContextCompat.getColor(PolygonActivity.this, R.color.steelblue))
                );

有一些自己的方法,填充颜色,边界颜色,都很简单

Android开发,MapBox的使用及部分功能实现(二)----- draw、layer、以及一些杂的知识点_第2张图片

需要注意一点,虽然我们设置了边界线颜色,但是,边界线不能设置宽度,所以很难看到边界线,除非两个颜色有很大的区别

根据geojson绘制

geojison,是一个geometry的点阵集合的一个json串,说白了,里面放了很多的点。

如下

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "Crema to Council Crest"
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          ...
          [
            106.70717,
            29.49798
          ],
          [
            106.70713,
            29.4984
          ],
          [
            106.70774,
            29.49893
          ]
        ]
      }
    }
  ]
}


这里我就不放太多了,这是我的一个geojson,其实格式并不重要,最终,我们都是通过转换成json,再各种getJSONArray,getJSONObject,来获取到坐标,添加到坐标集合,是的,和上面的两种方式是一样的,只不过一种是代码敲出来的坐标集合,一种是写入到文件中的坐标集合。

这个文件,我存在的assets中,命名为example.geojson

private class DrawGeoJson extends AsyncTask> {
        @Override
        protected List doInBackground(Void... voids) {
            List points = new ArrayList<>();
            try {
                //加载geojson文件
                InputStream inputStream = getAssets().open("example.geojson");
                BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder sb = new StringBuilder();
                int cp;
                while ((cp = rd.read()) != -1) {
                    sb.append(((char) cp));
                }
                inputStream.close();

                //转换成json
                JSONObject json = new JSONObject(sb.toString());
                JSONArray features = json.getJSONArray("features");
                JSONObject feature = features.getJSONObject(0);
                JSONObject geometry = feature.getJSONObject("geometry");
                if (geometry != null) {
                    String type = geometry.getString("type");

                    if (!TextUtils.isEmpty(type) && type.equalsIgnoreCase("LineString")) {
                        JSONArray coords = geometry.getJSONArray("coordinates");
                        for (int lc = 0; lc < coords.length(); lc++) {
                            JSONArray coord = coords.getJSONArray(lc);
                            LatLng latlng = new LatLng(coord.getDouble(1), coord.getDouble(0));
                            points.add(latlng);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return points;
        }
        @Override
        protected void onPostExecute(List latLngs) {
            super.onPostExecute(latLngs);
            if (latLngs.size() > 0) {
                mapboxMap.addPolyline(new PolylineOptions()
                        .addAll(latLngs)
                        .color(Color.parseColor("#3bb2d0"))
                        .width(2));
            }
        }
    }

这里采用了异步的操作去执行,官方demo就是这样的,然而,听了我刚刚的解释,你应该能想到,这样其实并不需要!这只是一种比较好的方法,而不是必须的方法,如果你想,你放到主线程里面去也行,new一个Thread也没问题。代码不多说,很简单的。图都懒得放了,就和画polyline是一样的。

layer的绘制

layer即图层,这里主要讲一讲图层的绘制,请注意,这里面的坑不是一般的多,多到你想用就得重写很多工具类才行的地步。

SymbolLayer

SymbolLayer,就是标记型的layer

如下

Android开发,MapBox的使用及部分功能实现(二)----- draw、layer、以及一些杂的知识点_第3张图片

看着和前面的Marker很像是不是,但是并不一样,前面的是一个Marker,这里是一个Layer,只是我用的图标是这样的,同时,如果一个地方出现多个Symbol,当地图比例尺变大时,两个接近的会变成一个Layer,这个做过地图的都知道,比如下面这种

Android开发,MapBox的使用及部分功能实现(二)----- draw、layer、以及一些杂的知识点_第4张图片

可以看到,现在只有两个图标了,右边的那一个其实代表了两个。

好,看代码

List featureList = new ArrayList<>();
                featureList.add(Feature.fromGeometry(
                        Point.fromCoordinates(
                                Position.fromCoordinates(106.124621, 29.123654))));
                featureList.add(Feature.fromGeometry(
                        Point.fromCoordinates(
                                Position.fromCoordinates(106.135491, 29.121623))));
                featureList.add(Feature.fromGeometry(
                        Point.fromCoordinates(
                                Position.fromCoordinates(106.130192, 29.193052))));

                FeatureCollection featureCollection = FeatureCollection.fromFeatures(featureList);
                Source source = new GeoJsonSource("marker-source", featureCollection);

                mapboxMap.addSource(source);


说实话,上面那一堆fromGeometry、fromCoordinates,我是真没怎么懂

不过大体上还是明白的,就是根据坐标构建feature,再将feature列表构造成一个FeatureCollection对象,这其实就是一个Feature集合的对象,他没有更多的方法,就是一个实体类,源代码如下

package com.mapbox.services.commons.geojson;

import com.mapbox.services.commons.geojson.BaseFeatureCollection;
import com.mapbox.services.commons.geojson.Feature;
import java.util.Arrays;
import java.util.List;

public class FeatureCollection extends BaseFeatureCollection {
    private final List features;

    protected FeatureCollection(List features) {
        this.features = features;
    }

    public List getFeatures() {
        return this.features;
    }

    public static FeatureCollection fromFeatures(List features) {
        return new FeatureCollection(features);
    }

    public static FeatureCollection fromFeatures(Feature[] features) {
        return new FeatureCollection(Arrays.asList(features));
    }
}

然后,将其构造成一个资源类型Source,前面是资源id,后面是资源集

然后就添加到mapboxmap

//添加一个图标到地图上,以备随时使用
                Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.yellow_marker);
                mapboxMap.addImage("my-marker", icon);

                //设置layer id,并绑定资源
                SymbolLayer markers = new SymbolLayer("marker-layer", "marker-source")
                        .withProperties(PropertyFactory.iconImage("my-marker"));//从配置里面找到刚刚存入的图标
                mapboxMap.addLayer(markers);

然后我们创建了一个Bitmap对象,作为图片资源添加到mapboxmap中,请注意,这个addImage并不是说直接就把图片添加到地图上了,而是暂时放到了mapboxmap中,然后下次要使用的时候可以直接拿出来用,下面,设置layer id ,并将资源进行绑定,这里的marker-source就是我们刚刚创建的资源名称,我也不知道为什么不直接把资源拿来用,非要先添加,再使用。

好,下面就是坑了

Positon,fromCoordinates(106.124621, 29.123654),和LatLng是相反的!
LatLng是(Latitude,Longitude)

但是,我们看源代码

public static Position fromCoordinates(double longitude, double latitude, double altitude) {
        return new Position(longitude, latitude, altitude);
    }

    public static Position fromCoordinates(double longitude, double latitude) {
        return new Position(longitude, latitude, 0.0D / 0.0);
    }


居然是相反的,这个很坑爹了。

然后是第二个坑,比如我这个demo,我可能会重复添加一次这个layer,这是就会报错了

对,不能重复添加已存在的source

也就是说,在此之前,你必须得先移除所有的source,那想到这,你可能会想了,很简单,removeAllSource,然而并没有这个方法,mapboxmap.clear,然而这个方法移除不掉clear,好,可能你就会想到遍历,删除咯

for (Source source : mapboxMap.getSources()) {
            mapboxMap.removeSource(source);
        }
然而,不行,因为这里getSources,获取到的并不只是我们添加进去的source,即使不添加,也仍然会有两个source,我没有具体的去看是哪两个,但是,很明显,不能这样来进行移除,所以,要么使用mapboxmap.removeSource来移除单个的source,但是这样,就必须记住每个source的id,我采用的是

private List addSource = new ArrayList<>();
建立一个添加的集合,再来遍历

for (Source source : addSource) {
            mapboxMap.removeSource(source);
        }
这里可以创建自己的mapboxmap继承MapBoxMap,重写addSource方法,每次添加都同时addSource.add(souce);添加到集合中,思路就这样,我暂时还没写,后面有时间会写的。

可以想到,Layer也不能这么搞

是的,Layer也没有removeAllLayer,clear也清除不掉

要一次性移除所有的Layer,就只能选择遍历,而且!和Souce一样,mapboxMap,getLayers得到的Layer不仅仅是你添加的Layer,事实上,这里可以得到一百多个Layer,所以如果你移除所有,你将看到一片漆黑,啥都没有

方法和上面一样,建立集合,添加进去addLayer.add(marker);,遍历集合。

你可能感兴趣的:(地图相关)