前段时间项目需要做路径规划,简单的研究了下。不过,后来没用到
效果图:
实现的是从北京西二旗地铁站 到 北京百度科技园的路径规划。这里是固定的,可以根据自己需要改成可输入起止位置
这里面有很多坑,需要一一踩过才知道。
记下来,我们来实现功能吧:
至于引入sdk、配置权限等,就不做具体的介绍了,网上或者百度地图官方文档都可以查到。
只许看加粗的主要部分就可以,因为还有其他的功能,所以显得冗余。
1、显示地图页面Activity,我取名叫FiveActivity
package com.example.my;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.route.BikingRouteLine;
import com.baidu.mapapi.search.route.BikingRoutePlanOption;
import com.baidu.mapapi.search.route.BikingRouteResult;
import com.baidu.mapapi.search.route.DrivingRouteResult;
import com.baidu.mapapi.search.route.IndoorRouteResult;
import com.baidu.mapapi.search.route.MassTransitRouteResult;
import com.baidu.mapapi.search.route.OnGetRoutePlanResultListener;
import com.baidu.mapapi.search.route.PlanNode;
import com.baidu.mapapi.search.route.RoutePlanSearch;
import com.baidu.mapapi.search.route.TransitRouteResult;
import com.baidu.mapapi.search.route.WalkingRouteResult;
import com.baidu.mapapi.utils.DistanceUtil;
import com.example.my.db.LatLngDB;
import com.example.my.util.BikingRouteOverlay;
import com.example.my.util.DragFloatActionButton;
import org.litepal.crud.DataSupport;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import me.bakumon.library.adapter.SimpleBulletinAdapter;
import me.bakumon.library.view.BulletinView;
/**
* Created by Administrator on 2018/2/6.
*/
public class FiveActivity extends AppCompatActivity {
private RoutePlanSearch mSearch;
private MapView mMapView = null;
BikingRouteOverlay overlay;
DragFloatActionButton btn_click, btn_refresh, btn_searchDB;
BulletinView bulletin_view;
Button btn_start, btn_end;
private long timeusedinsec;
private boolean isstop = false;
TextView tv_time;
public LocationClient mLocationClient = null;
private MyLocationListener myListener = new MyLocationListener();
private MyHandler myHandler;
private PopupWindow popupWindow;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在使用SDK各组件之前初始化context信息,传入ApplicationContext
//注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_five_layout);
initElement();
boolean isAllGranted = checkPermissionAllGranted(new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
});
if (isAllGranted) {
btn_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myHandler.removeMessages(1);
myHandler.sendEmptyMessage(1);
isstop = false;
mLocationClient.start();
Toast.makeText(FiveActivity.this, "开始采集坐标", Toast.LENGTH_SHORT).show();
}
});
btn_end.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isstop = true;
mLocationClient.stop();
Toast.makeText(FiveActivity.this, "停止采集坐标", Toast.LENGTH_SHORT).show();
}
});
}
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
},
0);
}
private void initElement() {
mSearch = RoutePlanSearch.newInstance();
mSearch.setOnGetRoutePlanResultListener(listener);
//获取地图控件引用
mMapView = (MapView) findViewById(R.id.bmapView);
btn_click = (DragFloatActionButton) findViewById(R.id.btn_click);
btn_refresh = (DragFloatActionButton) findViewById(R.id.btn_refresh);
btn_searchDB = (DragFloatActionButton) findViewById(R.id.btn_searchDB);
btn_start = findViewById(R.id.btn_start);
btn_end = findViewById(R.id.btn_end);
tv_time = findViewById(R.id.tv_time);
mLocationClient = new LocationClient(getApplicationContext());
mLocationClient.registerLocationListener(myListener);
initLocationClientOption();
//点击btn_click 即可实现路径规划
btn_click.setOnClickListener(new View.OnClickListener() {});
//可以忽略
btn_searchDB.setOnClickListener(new View.OnClickListener() {});
//可以忽略
}
2、activity_five_layout xml布局文件,只看自己需要的就行。DragFloatActionButton 悬浮按钮 和 Button按钮可以删除,根据自己需要来写布局文件吧
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:padding="@dimen/margin_10"
android:text="开始:北京, 西二旗地铁站"
android:textColor="@color/black" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:padding="@dimen/margin_10"
android:text="结束:北京, 百度科技园"
android:textColor="@color/black" />
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" />
android:layout_height="130dp"
android:layout_gravity="bottom|center_horizontal"
android:orientation="vertical">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:clickable="true"
android:focusable="true"
android:src="@android:drawable/ic_menu_directions" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:clickable="true"
android:focusable="true"
android:src="@android:drawable/ic_menu_revert" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:clickable="true"
android:focusable="true"
android:src="@android:drawable/ic_menu_search" />
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#30000000"
app:bulletinEnterAnim="@anim/bulletin_item_enter"
app:bulletinInterval="3000"
app:bulletinLeaveAnim="@anim/bulletin_item_leave" />
android:layout_width="100dp"
android:layout_height="25dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/content_five_activity_text_bg"
android:gravity="center"
android:text="跑秒"
android:textColor="@color/light_blue"
android:textStyle="bold" />
3、需要注意的是 BikingRouteOverlay 是需要自己实现的;也可以查看百度路径规划的Demo,有相对应的类。代码如下:
/*
* Copyright (C) 2016 Baidu, Inc. All Rights Reserved.
*/
package com.example.my.util;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.Overlay;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.Polyline;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.route.BikingRouteLine;
import java.util.ArrayList;
import java.util.List;
/**
* 用于显示骑行路线的Overlay
*/
public class BikingRouteOverlay extends OverlayManager {
private BikingRouteLine mRouteLine = null;
public BikingRouteOverlay(BaiduMap baiduMap) {
super(baiduMap);
}
/**
* 设置路线数据。
*
* @param line
* 路线数据
*/
public void setData(BikingRouteLine line) {
mRouteLine = line;
}
@Override
public final List
if (mRouteLine == null) {
return null;
}
List
if (mRouteLine.getAllStep() != null
&& mRouteLine.getAllStep().size() > 0) {
for (BikingRouteLine.BikingStep step : mRouteLine.getAllStep()) {
Bundle b = new Bundle();
b.putInt("index", mRouteLine.getAllStep().indexOf(step));
if (step.getEntrance() != null) {
overlayList.add((new MarkerOptions())
.position(step.getEntrance().getLocation())
.rotate((360 - step.getDirection()))
.zIndex(10)
.anchor(0.5f, 0.5f)
.extraInfo(b)
.icon(BitmapDescriptorFactory
.fromAssetWithDpi("Icon_line_node.png")));
}
// 最后路段绘制出口点
if (mRouteLine.getAllStep().indexOf(step) == (mRouteLine
.getAllStep().size() - 1) && step.getExit() != null) {
overlayList.add((new MarkerOptions())
.position(step.getExit().getLocation())
.anchor(0.5f, 0.5f)
.zIndex(10)
.icon(BitmapDescriptorFactory
.fromAssetWithDpi("Icon_line_node.png")));
}
}
}
// starting
if (mRouteLine.getStarting() != null) {
overlayList.add((new MarkerOptions())
.position(mRouteLine.getStarting().getLocation())
.icon(getStartMarker() != null ? getStartMarker() :
BitmapDescriptorFactory
.fromAssetWithDpi("Icon_start.png")).zIndex(10));
}
// terminal
if (mRouteLine.getTerminal() != null) {
overlayList
.add((new MarkerOptions())
.position(mRouteLine.getTerminal().getLocation())
.icon(getTerminalMarker() != null ? getTerminalMarker() :
BitmapDescriptorFactory
.fromAssetWithDpi("Icon_end.png"))
.zIndex(10));
}
// poly line list
if (mRouteLine.getAllStep() != null
&& mRouteLine.getAllStep().size() > 0) {
LatLng lastStepLastPoint = null;
for (BikingRouteLine.BikingStep step : mRouteLine.getAllStep()) {
List
if (watPoints != null) {
List
if (lastStepLastPoint != null) {
points.add(lastStepLastPoint);
}
points.addAll(watPoints);
overlayList.add(new PolylineOptions().points(points).width(10)
.color(getLineColor() != 0 ? getLineColor() : Color.argb(178, 0, 78, 255)).zIndex(0));
lastStepLastPoint = watPoints.get(watPoints.size() - 1);
}
}
}
return overlayList;
}
/**
* 覆写此方法以改变默认起点图标
*
* @return 起点图标
*/
public BitmapDescriptor getStartMarker() {
return null;
}
public int getLineColor() {
return 0;
}
/**
* 覆写此方法以改变默认终点图标
*
* @return 终点图标
*/
public BitmapDescriptor getTerminalMarker() {
return null;
}
/**
* 处理点击事件
*
* @param i
* 被点击的step在
* {@link BikingRouteLine#getAllStep()}
* 中的索引
* @return 是否处理了该点击事件
*/
public boolean onRouteNodeClick(int i) {
if (mRouteLine.getAllStep() != null
&& mRouteLine.getAllStep().get(i) != null) {
Log.i("baidumapsdk", "BikingRouteOverlay onRouteNodeClick");
}
return false;
}
@Override
public final boolean onMarkerClick(Marker marker) {
for (Overlay mMarker : mOverlayList) {
if (mMarker instanceof Marker && mMarker.equals(marker)) {
if (marker.getExtraInfo() != null) {
onRouteNodeClick(marker.getExtraInfo().getInt("index"));
}
}
}
return true;
}
@Override
public boolean onPolylineClick(Polyline polyline) {
// TODO Auto-generated method stub
return false;
}
}
4、到这里基本可以实现路径规划了,我这里地址是写的固定的,根据自己需要,可以改成输入框
适当的放松可以提高学习的效率,扫面下方二维码,关注微信公众号“休闲1刻”,幽默段子等着你~
休闲1刻