想要做一款基于位置的安卓应用,可交互的地图是重要的一部分。GoogleLeaflet都提供接口给开发者,Leaflet是一个开源的Javascript库,用于gis相关的应用,比google具有更高的定制性,本例就是基于Leaflet讲解安卓应用开发的地图方面的基本配置。
Leaflet 地图示例
地图底图用Mapbox提供的数据来显示,其中包含大量数据,来源于OpenStreetMap,NASA等等。在Mapbox Studio中可以定制自己的底图。
Leaflet需要用到JavaScript,可以先跑通js再放进java代码中编译,推荐一个轻量级的在线editor Plunker


由于Mapbox Studio提供的是在线的地图,所以在这里需要在Layout中创建一个Webview来显示地图。

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<WebView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />

然后配置manifest文件,以获取网络请求许可。在<manifest>标签内添加如下元素:

1
<uses-permission android:name="android.permission.INTERNET" />

java文件中,OnCreate()方法中添加加载地图的参数

1
2
3
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/map.html");

到此地图的地基已经搭建完成,接下来就要写htmljs代码完成地图的定制化显示。在app这个文件夹内新建文件夹assets,再在其中新建文件并命名为map.html,把自定义的图标star.png复制在assets文件夹目录下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html>
<head>
<title>Custom Map</title>
<meta charset="utf-8"/>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no"/>
<link rel="stylesheet"
href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>
<style>
html, body {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#map {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id='map'></div>
<script>
var map = L.map('map', {
center: [48.12855, 13.123903],
zoom: 15
});
var myIcon = L.icon({
iconUrl:'star.png',
iconAnchor: [12, 12],
popupAnchor: [0, -12]
});
L.marker([48.12855, 13.123903], {
icon: myIcon
})
.addTo(map)
.bindPopup("<b>This is</b><br>a demo")
.on('click', clickCenter);
function clickCenter(e) {
map.setView(e.target.getLatLng(),map.getZoom());
}
var circleOptions = {
color: '#f07910',
fillcolor: '#ff00dc',
weight: 3,
opacity: 1
};
L.circle([48.12855, 13.123903], 50, circleOptions).addTo(map);
L.tileLayer(
'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw',
{
id: 'mapbox.streets'
}).addTo(map);
</script>
</body>
</html>

解释一下上面这段代码,首先在html文件head之中要包含leaflet的css和js文件。在body部分我们添加了一个div定义了将要显示的地图为map。为了使地图全屏显示,在head部分用css代码控制元素的宽和高为100%。
script标签内,第一个变量map指定了显示的中心和缩放等级。myIcon指定自定义的图标,iconAnchor指定图标显示的地理位置,默认的热点是左上角。本例中图标是24*24,所以需要向右向下各移动12个像素,这样图标才能被放置在指定位置的中间。popupAnchor指定popups的位置,在本例中[0,-12]
表示的是图标上边缘的中点。接下来marker把图标和popup一起添加给地图。clickCenter函数的功能是,当用户点击marker,就移动地图的显示范围,使其位于屏幕中心。然后指定一个圆圈绘制的属性,最后在地图上显示一个圆圈,并使用circleOptions指定的属性。
最后tileLayer提供地图底图,当然可以自己在Mapbox Studio中定制。
最后附上编译后的app示例:
Leaflet 地图app示例