项目中的对地图的各种需求,实现方式。
需求1:自定义缩放按钮,自定义当前位置按钮
解决方式:隐藏地图本身自带的缩放按钮,添加自定义的缩放按钮,实现点击缩放地图功能
(一). 隐藏地图本身自带的缩放按钮:
// 隐藏logo
View child = mMapView.getChildAt(1);
if (child != null&&
(child instanceof ImageView||child instanceof ZoomControls)) {
child.setVisibility(View.INVISIBLE);
}
mapView.showZoomControls(false); // 设置是否显示缩放控件
mapView.showScaleControl(false);
(二).添加自定义按钮,实现点击缩放地图功能。
1. 先获取到地图当前的缩放级别,最大,最小级别
public float getBaiduMapZoom() {
maxZoom = baiduMap.getMaxZoomLevel();//最大级别
miniZoom = baiduMap.getMinZoomLevel();//最小级别
currentZoom = baiduMap.getMapStatus().zoom;//当前级别
return currentZoom;
}
2.按钮放大地图功能:
// 加大地图比例
public void plusBaiduZoom() {
if (getBaiduMapZoom() < maxZoom) {
baiduMap.setMapStatus(
MapStatusUpdateFactory.zoomIn());
} else {
plus_iv.setEnabled(false);
//plus_iv为加大按钮,当已经是最大级别时,设置按钮不可点击
}
}
3.按钮缩小地图功能:
// 缩小地图比例
public void minusBaiduZoom() {
if (getBaiduMapZoom() > miniZoom) {
baiduMap.setMapStatus(
MapStatusUpdateFactory.zoomOut());
} else {
minus_iv.setEnabled(false);
//minus_iv为缩小按钮
}
}
4.当手势缩放地图,造成地图缩放级别改变,自定义的缩放按钮也必须随着改变 解决方式:OnMapStatusChangeListener中的onMapStatusChange()中监控
public void onMapStatusChange(MapStatus status) {
currentZoom = status.zoom;
if (currentZoom == maxZoom) {
plus_iv.setEnabled(false);
}
else if (currentZoom == miniZoom) {
minus_iv.setEnabled(false);
}
else {
plus_iv.setEnabled(true);
minus_iv.setEnabled(true);
}
}
(三)自定义当前位置的按钮:
// 定位中心点和缩放比例
public void locationBaidu_locationZoom() {
LatLng ll;
if (latitude > 0 && longtitude > 0) {
ll = new LatLng(latitude, longtitude);
}else{
return;
}
baiduMap.setMapStatus(
MapStatusUpdateFactory.newLatLngZoom(ll,13));
}
需求2:自定义覆盖物,不单纯是图片,还需要生成有文字的marker
解决方式: BitmapDescriptorFactory.fromView(),将xml生成一个icon
(一)对应的xml: 注意点:xml最外层的应该是LinearLayout,不然会报空指针
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" >
<RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" >
<ImageView android:id="@+id/mark_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" />
<TextView android:id="@+id/mark_content_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:textSize="10sp" android:textColor="@color/orange1" android:layout_marginTop="8dp" />
</RelativeLayout>
(二)将xml生成对应的view:
首先获取到view:优化多次findviewbyid:
private View view;
//参数: 图片资源,文字
private View getView(int resId, StringBuffer str) {
ViewHolder viewHolder;
if (view == null) {
view = View.inflate(activity,
R.layout.baidumarklayout, null);
viewHolder = new ViewHolder();
viewHolder.iv = (ImageView)
view.findViewById(R.id.mark_iv);
viewHolder.tv = (TextView)
view.findViewById(R.id.mark_content_tv);
view.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.iv.setImageResource(resId);
viewHolder.tv.setText(str);
return view;
}
private static class ViewHolder {
public TextView tv;
public ImageView iv;
}
(三)将view生成icon:
//将view生成icon:
BitmapDescriptor bdOpen_iv=
BitmapDescriptorFactory.fromView(
getView(R.drawable.bdopen_iv, stringBuffer));
//将BitmapDescriptor设置marker的icon:
new MarkerOptions().icon(bdOpen_iv);
需求3:覆盖物实现缩放效果
解决方式: 在覆盖物的点击事件中做出处理,通过MarkerOptions.setIcon()替换图片
public boolean onMarkerClick(Marker marker) {
this.marker = marker;
entity = (Gasstation)
marker.getExtraInfo().get(extramessage_mark);
//替换icon
marker.setIcon(getScalleIcon(entity));
return true;
}
//注意点:手机点back键,时会要恢复原本icon大小,要针对做出处理
需求4:只显示当前手机屏幕下的覆盖物,随着地图改变,所显示的覆盖物业随着改变
解决方式:先获取到当前手机屏幕下的地图上全部点,开启工作线程进行筛选
(一)先获取到手机屏幕下的地图点
private LatLngBounds latLngBounds;
public LatLngBounds getLatLngBounds(){
if(latLngBounds==null){
latLngBounds=baiduMap.getMapStatus().bound;
}
return latLngBounds;
}
(二)在工作线程中进行筛选:latLngBounds.contains(latLng)
@Override
public void run() {
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_BACKGROUND);
task.setCurrentThread(Thread.currentThread());
try {
if (Thread.interrupted()) {
return;
}
//先获取到手机屏幕下的地图点
LatLngBounds latLngBounds=
gasStationFragment.getLatLngBounds();
//清空存储的覆盖物的坐标
gasStionList.clear();
for (Gasstation gasstation : jsonBean.getReplydata()) {
LatLng latLng = new
LatLng(gasstation.latitude,
gasstation.longitude);
//进行筛选工作
if (latLngBounds.contains(latLng)) {
gasStionList.add(gasstation);
}
}
if (Thread.interrupted()) {
return;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
task.handleResult(0);
task.setCurrentThread(null);
task.setCurrentRunnable(null);
Thread.interrupted();
}
}
(三) 最后别忘记了将筛选后的覆盖物添加到地图上
注意点:缩放按钮,当前位置按钮,手势缩放地图,都会造成手机屏幕包含的点发生改变,都应该针对这些情况作出处理。
需求5:驾车路线搜索,自定义沿途进过的站点,添加途经点标志
解决方式:通过起点,终点,搜索路线,然后将要进过的站点设置到规划的路线上
(一)设置起点,终点,途经点,进行路线搜索:
// 初始化搜索模块,注册事件监听
RoutePlanSearch mSearch = RoutePlanSearch.newInstance();
mSearch.setOnGetRoutePlanResultListener(
getRoutePlanResultListener);
//设置途径点
List<PlanNode> planNode_list = new ArrayList<PlanNode>();
PlanNode passby = PlanNode.withLocation(latlng);//途径点
planNode_list.add(passby);
// 设置起终点信息
PlanNode stNode = PlanNode.withLocation(stLatlng);
PlanNode enNode = PlanNode.withLocation(enLatlng);
mSearch.drivingSearch(
new DrivingRoutePlanOption()
.from(stNode)
.to(enNode)
.passBy(planNode_list));
(二)搜索结果回调,将结果显示在地图上:
private OnGetRoutePlanResultListener
getRoutePlanResultListener =
new OnGetRoutePlanResultListener() {
@Override
public void
onGetWalkingRouteResult(WalkingRouteResult arg0) {
}
@Override
public void
onGetTransitRouteResult(TransitRouteResult arg0) {
}
@Override
public void
onGetDrivingRouteResult(DrivingRouteResult result) {
if (result == null || result.error !=
SearchResult.ERRORNO.NO_ERROR) {
Toast.makeText(
BaiduRoutePlanningActivity.this,
R.string.cannot_find_result,
Toast.LENGTH_SHORT).show();
}
if (result.error ==
SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) {
// 起终点或途经点地址有岐义,通过以下接口获取建议查询信息
// result.getSuggestAddrInfo()
return;
}
if (result.error ==
SearchResult.ERRORNO.NO_ERROR) {
setRoutePlanning(result);
}
}
@Override
public void
onGetBikingRouteResult(BikingRouteResult arg0) {
// TODO Auto-generated method stub
}
};
//将结果显示在地图上
private void setRoutePlanning(DrivingRouteResult result) {
DrivingRouteOverlay overlay = new
MyCustomRouteOverlay(mBaiduMap);
// mBaiduMap.setOnMarkerClickListener(overlay);
overlay.setData(result.getRouteLines().get(0));
overlay.addToMap();
overlay.zoomToSpan();
}
private class MyCustomRouteOverlay extendsDrivingRouteOverlay {
public MyCustomRouteOverlay(BaiduMap baiduMap) {
super(baiduMap);
}
@Override
// 自定义起点坐标
public BitmapDescriptor getStartMarker() {
// return bdNotOpen_iv;
return null;
}
@Override
// 自定义终点坐标
public BitmapDescriptor getTerminalMarker() {
// return bdNotOpen_iv;
return null;
}
}
(三)隐藏百度地图上的沿途的带有方向的覆盖物(step node):
DrivingRouteOverlay.java中隐藏覆盖物(/* */部分)
public final List<OverlayOptions> getOverlayOptions() {
if (mRouteLine == null) {
return null;
}
List<OverlayOptions> overlayOptionses =
new ArrayList<OverlayOptions>();
/*
// step node
if (mRouteLine.getAllStep() != null
&& mRouteLine.getAllStep().size() > 0) {
for (DrivingRouteLine.DrivingStep step : mRouteLine.getAllStep()) {
Bundle b = new Bundle();
b.putInt("index", mRouteLine.getAllStep().indexOf(step));
if (step.getEntrance() != null) {
overlayOptionses.add((new MarkerOptions())
.position(step.getEntrance().getLocation())
.anchor(0.5f, 0.5f)
.zIndex(10)
.rotate((360 - step.getDirection()))
.extraInfo(b)
.icon(BitmapDescriptorFactory
.fromAssetWithDpi("Icon_line_node.png")));
}
// 最后路段绘制出口点
if (mRouteLine.getAllStep().indexOf(step) == (mRouteLine
.getAllStep().size() - 1) && step.getExit() != null) {
overlayOptionses.add((new MarkerOptions())
.position(step.getExit().getLocation())
.anchor(0.5f, 0.5f)
.zIndex(10)
.icon(BitmapDescriptorFactory
.fromAssetWithDpi("Icon_line_node.png")));
}
}
}
if (mRouteLine.getStarting() != null) {
overlayOptionses.add((new MarkerOptions())
.position(mRouteLine.getStarting().getLocation())
.icon(getStartMarker() != null ? getStartMarker()
: BitmapDescriptorFactory
.fromAssetWithDpi("Icon_start.png"))
.zIndex(10));
}
if (mRouteLine.getTerminal() != null) {
overlayOptionses.add((new MarkerOptions())
.position(mRouteLine.getTerminal().getLocation())
.icon(getTerminalMarker() != null ? getTerminalMarker()
: BitmapDescriptorFactory
.fromAssetWithDpi("Icon_end.png"))
.zIndex(10));
}
*/
// poly line
if (mRouteLine.getAllStep() != null
&& mRouteLine.getAllStep().size() > 0) {
List<DrivingStep> steps = mRouteLine.getAllStep();
int stepNum = steps.size();
List<LatLng> points = new ArrayList<LatLng>();
ArrayList<Integer> traffics = new ArrayList<Integer>();
int totalTraffic = 0;
for (int i = 0; i < stepNum; i++) {
if (i == stepNum - 1) {
points.addAll(steps.get(i).getWayPoints());
} else {
points.addAll(steps.get(i).getWayPoints()
.subList(0, steps.get(i).getWayPoints().size() - 1));
}
totalTraffic += steps.get(i).getWayPoints().size() - 1;
if (steps.get(i).getTrafficList() != null
&& steps.get(i).getTrafficList().length > 0) {
for (int j = 0; j < steps.get(i).getTrafficList().length; j++) {
traffics.add(steps.get(i).getTrafficList()[j]);
}
}
}
// Bundle indexList = new Bundle();
// if (traffics.size() > 0) {
// int raffic[] = new int[traffics.size()];
// int index = 0;
// for (Integer tempTraff : traffics) {
// raffic[index] = tempTraff.intValue();
// index++;
// }
// indexList.putIntArray("indexs", raffic);
// }
boolean isDotLine = false;
if (traffics != null && traffics.size() > 0) {
isDotLine = true;
}
PolylineOptions option = new PolylineOptions()
.points(points)
.textureIndex(traffics)
.width(11)
.dottedLine(isDotLine)
.focus(true)
.color(getLineColor() != 0 ? getLineColor() : Color.argb(
178, 0, 139, 0)).zIndex(0);//设置线条的颜色
if (isDotLine) {
option.customTextureList(getCustomTextureList());
}
overlayOptionses.add(option);
}
return overlayOptionses;
}
(四)最后在地图上添加起点,终点,途径点的覆盖物
需求6:找到当前最近的站点
解决方式:通过工作线程,筛选最近的气站(DistanceUtil.getDistance(locationLatLng,
latLng);)
(一):获取到当前城市(根据城市来缩小比对数据),当前的经纬度
public class MyLocationListenner implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
if (location == null) {
return;
}
BaseApplication.getContext().longtitude = location.getLongitude();
BaseApplication.getContext().latitude = location.getLatitude();
BaseApplication.getContext().address = location.getAddrStr();
String cityMark = location.getCity();
upDateNavigation(cityMark);
}
}
(二)工作线程内,筛选:
//获取到全部站点数据,此处省略(联网获取,或者本地数据库获取)
Gasstation gasstation = null;//含有站点信息得对象
LatLng locationLatLng = new LatLng(
BaseApplication.getContext().latitude,
BaseApplication.getContext().longtitude);
for (int i = 0; i < navigationList.size(); ++i) {
Gasstation gasstation2 = navigationList.get(i);//根据城市晒选出来的比对数据
LatLng latLng = new LatLng(gasstation2.latitude,
gasstation2.longitude);
double distance = DistanceUtil.getDistance(locationLatLng,
latLng);
if (i == 0) {
minDistanc = distance;
gasstation = gasstation2;
}
else {
if (distance < minDistanc) {
minDistanc = distance;
gasstation = gasstation2;
}
}
}