效果图:具体实现可参考以下项目代码。
1.导入jar包、so包。去百度地图开发者平台里面申请key写在功能清单文件里。具体申请地址http://wiki.lbsyun.baidu.com/index.php?title=androidsdk/guide/create-map/showmap
获取密钥的时候会要求提供SHA1,获取方式:点击studio 右侧Gradle,双击android下的signingReport可查看到SHA1.
获取到密钥后,在清单文件里面用key替换value。
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="1lVTzY7mMaf63GrKDCuKf9Tj0ZuGf5aC" />
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" >
</service>
2.布局,这里是用ImageView改变图标控制播放、暂停。下方的ProgressBar同步显示绘制进度。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</com.baidu.mapapi.map.MapView>
<ImageView
android:id="@+id/location_ivPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:contentDescription="@null"
android:src="@mipmap/play" />
<ProgressBar
android:id="@+id/progressBar1"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="48dp"
android:max="100"/>
</FrameLayout>
3.初始化代码,Application里面进行地图初始化,记得在功能清单里加上BaseApplication的全类名。
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SDKInitializer.initialize(BaseApplication.this);// 初始化百度地图
}
}
4.实现核心代码。
private fun initBaiduMap() {
mBaiduMap = bmapView.map
mBaiduMap?.isMyLocationEnabled = true
mBaiduMap?.setMapStatus(MapStatusUpdateFactory.zoomTo(12.0f))
addRouteLine(routeList) // 添加路线
}
显示出地图,zoomTo()是设置地图缩放级别,我这里写的是5公里。
private fun parseJson() {
try {
val jObject = JSONObject(routeJson)
val jArray = jObject.getJSONArray("list")
println(jArray.length())
var `object`: JSONObject? = null
routeList = ArrayList()
for (i in 0 until jArray.length()) {
`object` = jArray.getJSONObject(i)
routeList!!.add(
LatLng(
`object`.getDouble("lat"), `object`
.getDouble("lon")
)
)
}
println("latlng size=" + routeList!!.size)
} catch (e: JSONException) {
e.printStackTrace()
}
}
解析json,自己写的json字符串,里面包含了很多点的经纬度。"{\"list\":[{\"lon\":122.235502,\"lat\":37.330564},{\"lon\":122.235727,\"lat\":37.328527}]}"这种形式。
private fun addRouteLine(routeList: List<LatLng>?) {
var routeList = routeList
mBaiduMap!!.clear()
// 百度最多支持10000个点连线
if (routeList!!.size > 10000) {
routeList = routeList.subList(0, 10000)
}
mBaiduMap!!.addOverlay(
PolylineOptions().width(5).color(-0xe96b01)
.points(routeList)
)
moveToLocation(routeList[routeList.size / 2], true)
}
/**
* 移动到指定位置 并缩放
* @param latlng
*/
private fun moveToLocation(latlng: LatLng, flag: Boolean) {
val u = MapStatusUpdateFactory.newLatLng(latlng) // 设置新的中心点
mBaiduMap!!.animateMapStatus(u)
if (flag && mBaiduMap!!.mapStatus.zoom < 12.0f) {
// 加个延时播放的效果,就可以有先平移 ,再缩放的效果
mTimer.start()
}
}
添加路线,moveToLocation里的第一个参数是表示以哪个点作为地图中心点,我想让线大概在中间的位置,就取了集合的中间点。
override fun onClick(v: View) {
if (v.id == R.id.location_ivPlay) {
if (routeList == null || routeList!!.size <= 0) {
return
}
routeFlag = !routeFlag
location_ivPlay.setImageResource(if (routeFlag) R.mipmap.pause else R.mipmap.play)
if (routeFlag) {
if (routeIndex == 0) {
mBaiduMap!!.clear()
routeMarker = null
}
mHandler.sendEmptyMessageDelayed(ROUTE, 0)
} else {
mHandler.removeMessages(ROUTE)
}
}
}
routeFlag表示是否在回放,默认为false。routeIndex表示绘制点的位置。点击了播放按钮,用handler发消息,再点击一次,说明暂停,则移除此消息。
private val mHandler = object : Handler(Looper.myLooper()!!) {
override fun handleMessage(msg: Message) {
if (msg.what == ROUTE) {
sendEmptyMessage(PROGRESS)
if (routeIndex == routeList!!.size - 1) {
routeFlag = false
location_ivPlay.setImageResource(R.mipmap.play)
Toast.makeText(this@MainActivity, "播放完毕", Toast.LENGTH_LONG)
.show()
routeIndex = 0
if (routeMarker != null) {
routeMarker!!.remove()
routeMarker = null
}
addRouteLine(routeList)
return
}
if (routeIndex != 0) {
val polyLine = PolylineOptions()
.width(5)
.color(-0xe96b01)
.points(
routeList!!.subList(
routeIndex - 1,
routeIndex + 1
)
)
mBaiduMap!!.addOverlay(polyLine)
}
// 页面跟随移动,注掉这行就是在原图上绘制
// moveToLocation(routeList.get(routeIndex), false);
if (routeMarker == null) {
val cur = MarkerOptions()
.position(routeList!![routeIndex++])
.perspective(false).anchor(0.5f, 0.5f).zIndex(10)
} else {
routeMarker!!.position = routeList!![routeIndex++]
}
sendEmptyMessageDelayed(ROUTE, ROUTETIME.toLong())
}
if (msg.what == PROGRESS) {
if (routeIndex == 0) { // 因为播放完毕时routeIndex被赋值成了0,不写进度条会直接跳到0的位置
setProgss(100)
} else {
setProgss((routeIndex + 1) * 100 / routeList!!.size)
}
}
}
}
处理handler消息,当接到了ROUTE消息之后发PROGRESS消息是为了通知progressbar同步显示进度。mHandler.sendEmptyMessageDelayed(ROUTE, ROUTETIME);是循环执行这个画线的操作,时间间隔为ROTERTIME的值。除非再点击变成了暂停,则停止此操作。routeIndex等于最后一个点的时候,说明回放完成。
下面附上源码下载链接:http://download.youkuaiyun.com/detail/xkyh941/9599050(时隔许久,这是当初使用eclipse写的)
可以去github下载:https://github.com/liuyangxiao/RouteHistoryDemo.git
学习的每一天都会充实而美好,希望技术无边界,能帮助到大家。