概述
前段时间,在用到新版(3.5.0版)百度地图时,在地图覆盖物实现以及覆盖物点击事件的添加部分遇到点挫折,发现网上很多的资料写得都不够详细,所以我就想写一个有关从地图定位到地图覆盖物及其点击事件的实现的博文。
效果图:
覆盖物及其点击事件:
自定义缩放控件的实现效果(注意图中的加减按钮):
实现此例程之前要做的的步骤:
- 1、申请Baidu API_KEY;
- 2、下载Baidu SDK,以及Baidu BS Sample,在libs中导入baidumapapi_v3_5_0.jar和locSDK_6.11.jar两个包
- 3、在main目录下新建一个jniLibs文件夹,导入你解压好的的Baidu sdk中so包中的arm64-v8a、armeabi、armeabi-v7a、x86、x86_64这几个文件夹,然后在Baidu BS中找到so库arm64-v8a、armeabi、armeabi-v7a、mips、mips64、x86、x86_64,如果你下的是Baidu BS Sample,可以直接找个什么功能都有的sample,把它的libs下的所有文件拷贝到你的libs目录下,这里的每个so包的作用都不一样,都导进去可以确保万无一失,也可以在libs文件夹下直接导入上述的那些文件夹几个文件夹。
注:我的jniLibs包的结构: - 4、在AndroidManifest中添加权限:
<!-- 这个权限用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission> <!-- 这个权限用于访问GPS定位--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission> <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> <!-- 获取运营商信息,用于支持提供运营商信息相关的接口--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位--> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission> <!-- 用于读取手机当前的状态--> <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> <!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <!-- 访问网络,网络定位需要上网--> <uses-permission android:name="android.permission.INTERNET" /> <!-- SD卡读取权限,用户写入离线定位数据--> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.CALL_PHONE"/>
- 5、申明你的API KEY
<meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="yOqOdhwa6jL82BmiG9SXWZn6" />
你还可以在Baidu地图官网上找到他们的API照着他们的步骤好好做一遍,把所有预备工作做好,然后直接看下面的Demo
Demo
public class BaiduMapActivity extends BaseActivity implements View.OnClickListener { private MapView mMapView; private BaiduMap mBaiduMap; private LocationClient mLocationClient = null; public BDLocationListener mBDListener = new MyLocationListener(); private List<BDMapData> bdMapClientList; private double latitude; private double longitude; private boolean isFirstLocate = true; private Button mButtonAdd; private Button mButtonSub; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SDKInitializer.initialize(getApplicationContext()); setContentView(R.layout.activity_baidu_map); /** * 缩放地图的按钮 */ mButtonAdd = (Button) findViewById(R.id.button_add); mButtonSub = (Button) findViewById(R.id.button_sub); mButtonAdd.setOnClickListener(this); mButtonSub.setOnClickListener(this); mMapView = (MapView) findViewById(R.id.mapView_client_raise); mMapView.showZoomControls(false);//让百度地图默认的地图缩放控件不显示 mBaiduMap = mMapView.getMap(); mBaiduMap.setMyLocationEnabled(true);//使能百度地图的定位功能 mLocationClient = new LocationClient(getApplicationContext()); mLocationClient.registerLocationListener(mBDListener);//注册地图的监听器 initLocation(); mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { final String info = (String) marker.getExtraInfo().get("info"); InfoWindow infoWindow; //动态生成一个Button对象,用户在地图中显示InfoWindow final Button textInfo = new Button(getApplicationContext()); textInfo.setBackgroundResource(R.drawable.locate_popup_state); textInfo.setPadding(10, 10, 10, 10); textInfo.setTextColor(Color.BLACK); textInfo.setTextSize(12); textInfo.setText(info); //得到点击的覆盖物的经纬度 LatLng ll = marker.getPosition(); textInfo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(BaiduMapActivity.this, "你点击了"+info, Toast.LENGTH_SHORT).show(); } }); //将marker所在的经纬度的信息转化成屏幕上的坐标 Point p = mBaiduMap.getProjection().toScreenLocation(ll); p.y -= 90; LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p); //初始化infoWindow,最后那个参数表示显示的位置相对于覆盖物的竖直偏移量,这里也可以传入一个监听器 infoWindow = new InfoWindow(textInfo, llInfo, 0); mBaiduMap.showInfoWindow(infoWindow);//显示此infoWindow //让地图以备点击的覆盖物为中心 MapStatusUpdate status = MapStatusUpdateFactory.newLatLng(ll); mBaiduMap.setMapStatus(status); return true; } }); //开始定位 mLocationClient.start(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button_add: //放大地图 mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomIn()); break; case R.id.button_sub: //缩小地图 mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomOut()); break; default: break; } } /** * 自定义一个百度地图的定位监听器,可监听定位类型,位置经纬度变化等一系列状态 */ private class MyLocationListener implements BDLocationListener { @Override public void onReceiveLocation(BDLocation bdLocation) { latitude = bdLocation.getLatitude();//得到纬度 longitude = bdLocation.getLongitude();//得到经度 boolean isLocateFailed = false;//定位是否成功 if (isFirstLocate) { if (bdLocation.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位结果 ToastUtils.showToast(getApplicationContext(), "GPS定位"); } else if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation) {// 网络定位结果 ToastUtils.showToast(getApplicationContext(), "网络定位"); } else if (bdLocation.getLocType() == BDLocation.TypeOffLineLocation) {// 离线定位结果 ToastUtils.showToast(getApplicationContext(), "离线定位"); } else if (bdLocation.getLocType() == BDLocation.TypeServerError || bdLocation.getLocType() == BDLocation.TypeNetWorkException || bdLocation.getLocType() == BDLocation.TypeCriteriaException) { isLocateFailed = true; } /** * 如果定位不成功,显示定位失败的dialog */ if (isLocateFailed) { simpleDialog(); } initMapDataList(); addOverlay(); isFirstLocate = false; } } } /** * 添加覆盖物的方法 */ private void addOverlay() { Marker marker = null; LatLng point = null; MarkerOptions option = null; BitmapDescriptor bitmap =BitmapDescriptorFactory.fromResource(R.mipmap.customer_location);; for (BDMapData data : bdMapClientList) { point = new LatLng(data.getLatitude(), data.getLongitude()); option = new MarkerOptions().position(point).icon(bitmap); marker = (Marker) mBaiduMap.addOverlay(option); //Bundle用于通信 Bundle bundle = new Bundle(); bundle.putSerializable("info", data.getName()+"\n"+"纬度:"+data.getLatitude()+" 经度:"+data.getLongitude()); marker.setExtraInfo(bundle);//将bundle值传入marker中,给baiduMap设置监听时可以得到它 } //将地图移动到最后一个标志点 MapStatusUpdate status = MapStatusUpdateFactory.newLatLng(point); mBaiduMap.setMapStatus(status); } /** * BaiduAPI上的例程,初始化定位 */ private void initLocation() { LocationClientOption option = new LocationClientOption(); option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy );//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备 option.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系 int span = 1000; option.setScanSpan(span);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的 option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要 option.setOpenGps(true);//可选,默认false,设置是否使用gps option.setLocationNotify(true);//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果 option.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近” option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到 option.setIgnoreKillProcess(false);//可选,默认false,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认杀死 option.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集 option.setEnableSimulateGps(false);//可选,默认false,设置是否需要过滤gps仿真结果,默认需要 mLocationClient.setLocOption(option); } //初始化每个覆盖物对应的信息 private void initMapDataList() { bdMapClientList = new ArrayList<>(); //让所有覆盖物的经纬度与你自己的经纬度相近,以便打开地图就能看到那些覆盖物 bdMapClientList.add(new BDMapData("中兴创维", latitude - 0.0656, longitude - 0.00354)); bdMapClientList.add(new BDMapData("领卓科技", latitude + 0.024, longitude - 0.0105)); bdMapClientList.add(new BDMapData("蓝翔驾校", latitude - 0.00052, longitude - 0.01086)); bdMapClientList.add(new BDMapData("优衣库折扣店", latitude + 0.0124, longitude + 0.00184)); } /** * 定位失败时显示的dialog的初始化方法 */ public void simpleDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(BaiduMapActivity.this); builder.setMessage("当前网络不可用,请检查网络设置") .setNeutralButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); AlertDialog dialog = builder.create(); dialog.setCanceledOnTouchOutside(true); dialog.show(); }}
用于存储覆盖物信息的类
public class BDMapData { private String name; private double latitude;//纬度 private double longitude;//经度 public BDMapData(String name, double latitude, double longitude) { this.name = name; this.latitude = latitude; this.longitude = longitude; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getLatitude() { return latitude; } public void setLatitude(double latitude) { this.latitude = latitude; } public double getLongitude() { return longitude; } public void setLongitude(double longitude) { this.longitude = longitude; }}
布局文件activity_baidu_map:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/relativeLayout_top_clientRaise" android:layout_width="match_parent" android:layout_height="60dp" android:background="@drawable/item_bg"> <LinearLayout android:id="@+id/linearlayout_clientRise_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:gravity="center" android:orientation="horizontal" android:descendantFocusability="beforeDescendants"> <Button android:layout_width="25dp" android:layout_height="25dp" android:background="@mipmap/btn_back_normal"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="返回" android:textSize="@dimen/head_left_text_size"/> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="百度地图Demo" android:textSize="20dp"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.baidu.mapapi.map.MapView android:id="@+id/mapView_client_raise" android:layout_width="match_parent" android:layout_height="match_parent"> </com.baidu.mapapi.map.MapView> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentBottom="true" android:layout_margin="10dp" android:orientation="vertical"> <Button android:id="@+id/button_add" android:layout_width="35dp" android:layout_height="35dp" android:textSize="15dp" android:textColor="@color/dark_brow" android:background="@drawable/add_state"/> <Button android:id="@+id/button_sub" android:layout_width="35dp" android:layout_height="35dp" android:background="@drawable/sub_state" android:textSize="15dp" android:textColor="@color/dark_brow"/> </LinearLayout> </RelativeLayout></LinearLayout>
不想贴源码了。。。
drawable文件夹下内容:
item_bg.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#ffffff"></solid> <stroke android:width="0.3dp" android:color="#606060"> </stroke></shape>
add_state.xml
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@mipmap/add_group_press" android:state_pressed="true"></item> <item android:drawable="@mipmap/add_group"></item></selector>
sub_state.xml:
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@mipmap/btn_reduction_group_press" android:state_pressed="true"></item> <item android:drawable="@mipmap/btn_reduction_group"></item></selector>
locate_popup.xml
white:#ffffff
grey:#d0d0d0
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/white" android:state_pressed="true"></item> <item android:drawable="@color/grey"></item></selector>
mipmap中的图片
customer_location.png:
add_group.png:
add_group_press.png:
btn_reduction_group.png:
btn_reduction_group_press.png:
btn_back_normal.png:
总结:
这里只是实现了BaiduMap的最基本的几个功能,它还有其它许多种功能,但都没这个功能应用得频繁,像什么美团之类的应用里就用到了覆盖物,至于Baidu SDK别的很多功能,有了解的朋友可以写个博客给大家展示一下。
版权声明:本文为博主原创文章,未经博主允许不得转载。