学习内容来自“慕课网”
本片学习内容接自前四篇基础
请先学习前4篇再学习本篇,因为本篇在前四篇的基础上进行代码的编写
一、新建一个类用来存放数据(距离,点赞数,介绍图等信息)
1 package com.example.map; 2 3 import java.io.Serializable; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 public class Info implements Serializable 8 { 9 private static final long serialVersionUID = -1010711775392052966L; 10 //经纬度 11 private double latitude; 12 private double longitude; 13 //图片id 14 private int imgId; 15 //商家的名称 16 private String name; 17 //距离 18 private String distance; 19 //点赞的数量 20 private int zan; 21 22 public static List<Info> infos = new ArrayList<Info>(); 23 //这里的数据都是死的,实际开发中数据都是从服务器中获取的,这里只演示如何添加覆盖物这个效果 24 static 25 { 26 infos.add(new Info(34.242652, 108.971171, R.drawable.a01, "英伦贵族小旅馆", 27 "距离209米", 1456)); 28 infos.add(new Info(34.242952, 108.972171, R.drawable.a02, "沙井国际洗浴会所", 29 "距离897米", 456)); 30 infos.add(new Info(34.242852, 108.973171, R.drawable.a03, "五环服装城", 31 "距离249米", 1456)); 32 infos.add(new Info(34.242152, 108.971971, R.drawable.a04, "老米家泡馍小炒", 33 "距离679米", 1456)); 34 } 35 //构造方法 36 public Info(double latitude, double longitude, int imgId, String name, 37 String distance, int zan) 38 { 39 this.latitude = latitude; 40 this.longitude = longitude; 41 this.imgId = imgId; 42 this.name = name; 43 this.distance = distance; 44 this.zan = zan; 45 } 46 47 public double getLatitude() 48 { 49 return latitude; 50 } 51 52 public void setLatitude(double latitude) 53 { 54 this.latitude = latitude; 55 } 56 57 public double getLongitude() 58 { 59 return longitude; 60 } 61 62 public void setLongitude(double longitude) 63 { 64 this.longitude = longitude; 65 } 66 67 public int getImgId() 68 { 69 return imgId; 70 } 71 72 public void setImgId(int imgId) 73 { 74 this.imgId = imgId; 75 } 76 77 public String getName() 78 { 79 return name; 80 } 81 82 public void setName(String name) 83 { 84 this.name = name; 85 } 86 87 public String getDistance() 88 { 89 return distance; 90 } 91 92 public void setDistance(String distance) 93 { 94 this.distance = distance; 95 } 96 97 public int getZan() 98 { 99 return zan; 100 } 101 102 public void setZan(int zan) 103 { 104 this.zan = zan; 105 } 106 107 }
二、添加覆盖物
首先在菜单中增加"添加覆盖物"菜单项
res-menu-main.xml
红色字体部分为新添加的代码部分
1 <menu xmlns:android="http://schemas.android.com/apk/res/android" > 2 3 <item 4 android:id="@+id/id_map_common" 5 6 android:showAsAction="never" 7 android:title="普通地图"/> 8 <item 9 android:id="@+id/id_map_site" 10 11 android:showAsAction="never" 12 android:title="卫星地图"/> 13 <item 14 android:id="@+id/id_map_traffic" 15 16 android:showAsAction="never" 17 android:title="实时交通(off)"/> 18 <item 19 android:id="@+id/id_map_location" 20 21 android:showAsAction="never" 22 android:title="定位我的位置"/> 23 <item 24 android:id="@+id/id_mode_common" 25 26 android:showAsAction="never" 27 android:title="普通模式"/> 28 <item 29 android:id="@+id/id_mode_following" 30 31 android:showAsAction="never" 32 android:title="跟随模式"/> 33 <item 34 android:id="@+id/id_mode_compass" 35 36 android:showAsAction="never" 37 android:title="罗盘模式"/> 38 <item 39 android:id="@+id/id_add_overlay" 40 41 android:showAsAction="never" 42 android:title="添加覆盖物"/> 43 44 </menu>
给菜单项添加响应事件
1 //菜单按钮的响应事件 2 @Override 3 public boolean onOptionsItemSelected(MenuItem item) { 4 // TODO Auto-generated method stub 5 switch (item.getItemId()) { 6 case R.id.id_map_common: 7 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL); 8 break; 9 case R.id.id_map_site: 10 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE); 11 break; 12 case R.id.id_map_traffic: 13 if(mBaiduMap.isTrafficEnabled()) 14 { 15 mBaiduMap.setTrafficEnabled(false); 16 item.setTitle("实时交通(off)"); 17 } 18 else 19 { 20 mBaiduMap.setTrafficEnabled(true); 21 item.setTitle("实时交通(on)"); 22 } 23 break; 24 case R.id.id_map_location: 25 //定位最新自己的位置 26 centerToMyLocation(); 27 break; 28 29 case R.id.id_mode_common: 30 //设置普通模式 31 mLocationMode = LocationMode.NORMAL; 32 break; 33 case R.id.id_mode_following: 34 //设置跟随模式 35 mLocationMode = LocationMode.FOLLOWING; 36 break; 37 case R.id.id_mode_compass: 38 //设置罗盘模式 39 mLocationMode = LocationMode.COMPASS; 40 break; 41 case R.id.id_add_overlay: 42 //设置添加覆盖物 43 addOverlays(Info.infos); 44 break; 45 default: 46 break; 47 } 48 return super.onOptionsItemSelected(item); 49 }
这是添加覆盖物的方法 ,
1 private void addOverlays(List<Info> infos) { 2 // TODO Auto-generated method stub 3 //添加覆盖物 4 //清楚定位的一些图层 5 mBaiduMap.clear(); 6 // 经纬度 7 LatLng latLng = null; 8 Marker marker = null; 9 OverlayOptions options; 10 for (Info info : infos) 11 { 12 // 经纬度 13 latLng = new LatLng(info.getLatitude(), info.getLongitude()); 14 // 图标 15 options = new MarkerOptions().position(latLng).icon(mMarker).zIndex(5);//5表示图层的位置,越大越在上面 16 marker = (Marker) mBaiduMap.addOverlay(options); 17 Bundle arg0 = new Bundle(); 18 arg0.putSerializable("info", info); 19 marker.setExtraInfo(arg0); 20 } 21 //定位好之后,讲地图定位到最后一个图标的位置 22 MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng); 23 mBaiduMap.setMapStatus(msu); 24 25 }
效果图:
可以看到,地图上显示了4个覆盖物的坐标,但是这些坐标无法点击
。下面学习实现点击坐标显示相应的信息效果
二、实现覆盖物信息效果
实现建立显示信息的信息框的布局文件
1 <RelativeLayout 2 android:id="@+id/id_maker_ly" 3 android:layout_width="match_parent" 4 android:layout_height="220dp" 5 android:layout_alignParentBottom="true" 6 android:background="#cc4e5a6b" 7 android:clickable="true" 8 android:visibility="gone" > 9 10 <ImageView 11 android:id="@+id/id_info_img" 12 android:layout_width="fill_parent" 13 android:layout_height="150dp" 14 android:layout_marginBottom="10dp" 15 android:layout_marginLeft="12dp" 16 android:layout_marginRight="12dp" 17 android:layout_marginTop="10dp" 18 android:background="@drawable/img_border" 19 android:scaleType="fitXY" 20 android:src="@drawable/a01" > 21 </ImageView> 22 23 <RelativeLayout 24 android:layout_width="fill_parent" 25 android:layout_height="50dp" 26 android:layout_alignParentBottom="true" 27 android:background="@drawable/bg_map_bottom" > 28 29 <LinearLayout 30 android:layout_width="wrap_content" 31 android:layout_height="wrap_content" 32 android:layout_centerVertical="true" 33 android:layout_marginLeft="20dp" 34 android:orientation="vertical" > 35 36 <TextView 37 android:id="@+id/id_info_name" 38 android:layout_width="wrap_content" 39 android:layout_height="wrap_content" 40 android:text="老米家泡馍" 41 android:textColor="#fff5eb" /> 42 43 <TextView 44 android:id="@+id/id_info_distance" 45 android:layout_width="wrap_content" 46 android:layout_height="wrap_content" 47 android:text="距离200米" 48 android:textColor="#fff5eb" /> 49 </LinearLayout> 50 51 <LinearLayout 52 android:layout_width="wrap_content" 53 android:layout_height="wrap_content" 54 android:layout_alignParentRight="true" 55 android:layout_centerVertical="true" 56 android:layout_marginRight="20dp" 57 android:orientation="horizontal" > 58 59 <ImageView 60 android:layout_width="wrap_content" 61 android:layout_height="wrap_content" 62 android:background="@drawable/map_zan" 63 android:clickable="true" /> 64 65 <TextView 66 android:id="@+id/id_info_zan" 67 android:layout_width="wrap_content" 68 android:layout_height="wrap_content" 69 android:layout_gravity="center" 70 android:text="789" 71 android:textColor="#fff5eb" /> 72 </LinearLayout> 73 </RelativeLayout> 74 </RelativeLayout>
注意第18行代码
这里还需要建一个.xml文件
在res目录下新建文件夹drawable 在此文件夹下新建img_border.xml
res-drawable-img_border.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <shape xmlns:android="http://schemas.android.com/apk/res/android" > 3 4 <stroke 5 android:width="2dp" 6 android:color="#AAFFFFFF" /> 7 8 <padding 9 android:bottom="2dp" 10 android:left="2dp" 11 android:right="2dp" 12 android:top="2dp" > 13 </padding> 14 </shape>
信息框布局文件就由这两个.xml文件构成了
MainActivity.java
1 package com.example.map; 2 3 import java.util.List; 4 5 import com.baidu.location.BDLocation; 6 import com.baidu.location.BDLocationListener; 7 import com.baidu.location.LocationClient; 8 import com.baidu.location.LocationClientOption; 9 import com.baidu.mapapi.SDKInitializer; 10 import com.baidu.mapapi.map.BaiduMap; 11 import com.baidu.mapapi.map.BaiduMap.OnMapClickListener; 12 import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener; 13 import com.baidu.mapapi.map.BitmapDescriptor; 14 import com.baidu.mapapi.map.BitmapDescriptorFactory; 15 import com.baidu.mapapi.map.InfoWindow; 16 import com.baidu.mapapi.map.MapPoi; 17 import com.baidu.mapapi.map.MapStatusUpdate; 18 import com.baidu.mapapi.map.MapStatusUpdateFactory; 19 import com.baidu.mapapi.map.MapView; 20 import com.baidu.mapapi.map.Marker; 21 import com.baidu.mapapi.map.MarkerOptions; 22 import com.baidu.mapapi.map.MyLocationConfiguration; 23 import com.baidu.mapapi.map.MyLocationConfiguration.LocationMode; 24 import com.baidu.mapapi.map.MyLocationData; 25 import com.baidu.mapapi.map.OverlayOptions; 26 import com.baidu.mapapi.model.LatLng; 27 import com.example.map.MyOrientationListener.OnOrientationListener; 28 import com.example.map.R; 29 30 import android.location.Location; 31 import android.os.Bundle; 32 import android.app.Activity; 33 import android.content.Context; 34 import android.graphics.Bitmap; 35 import android.graphics.Color; 36 import android.graphics.Point; 37 import android.view.Menu; 38 import android.view.MenuItem; 39 import android.view.View; 40 import android.view.Window; 41 import android.widget.ImageView; 42 import android.widget.RelativeLayout; 43 import android.widget.TextView; 44 import android.widget.Toast; 45 46 public class MainActivity extends Activity { 47 48 private MapView mMapView = null; 49 private BaiduMap mBaiduMap; 50 //简化代码 用于this.context=this; 51 private Context context; 52 //定位相关 53 private LocationClient mLocationClient; 54 private MyLocationListener mLocationListener; 55 //是否第一次定位的标志 56 private boolean isFirstIn = true; 57 //定位经纬度 58 private double mLatitude; 59 private double mLongtitude; 60 //自定义定位图标 61 private BitmapDescriptor mIconLocation; 62 private LocationMode mLocationMode; 63 private MyOrientationListener myOrientationListener; 64 private float mCurrentX; 65 //添加覆盖物 66 private BitmapDescriptor mMarker; 67 //信息框的布局 68 private RelativeLayout mMarkerLy; 69 70 71 72 @Override 73 protected void onCreate(Bundle savedInstanceState) { 74 super.onCreate(savedInstanceState); 75 //在使用SDK各组件之前初始化context信息,传入ApplicationContext 76 //注意该方法要再setContentView方法之前实现 77 SDKInitializer.initialize(getApplicationContext()); 78 79 requestWindowFeature(Window.FEATURE_NO_TITLE); 80 setContentView(R.layout.activity_main); 81 this.context = this; 82 initView(); 83 //初始化定位 84 initLocation(); 85 //初始化覆盖物相关 86 initMarker(); 87 mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() 88 { 89 @Override 90 public boolean onMarkerClick(Marker marker) 91 { 92 Bundle extraInfo = marker.getExtraInfo(); 93 Info info = (Info) extraInfo.getSerializable("info"); 94 95 ImageView iv = (ImageView) mMarkerLy.findViewById(R.id.id_info_img); 96 TextView distance = (TextView) mMarkerLy.findViewById(R.id.id_info_distance); 97 TextView name = (TextView) mMarkerLy.findViewById(R.id.id_info_name); 98 TextView zan = (TextView) mMarkerLy.findViewById(R.id.id_info_zan); 99 100 iv.setImageResource(info.getImgId()); 101 distance.setText(info.getDistance()); 102 name.setText(info.getName()); 103 zan.setText(info.getZan() + ""); 104 105 mMarkerLy.setVisibility(View.VISIBLE); 106 return true; 107 } 108 }); 109 mBaiduMap.setOnMapClickListener(new OnMapClickListener() 110 { 111 112 @Override 113 public boolean onMapPoiClick(MapPoi arg0) 114 { 115 return false; 116 } 117 118 @Override 119 public void onMapClick(LatLng arg0) 120 { 121 mMarkerLy.setVisibility(View.GONE); 122 mBaiduMap.hideInfoWindow(); 123 } 124 }); 125 } 126 127 private void initMarker() { 128 // TODO Auto-generated method stub 129 //标记图标 130 mMarker = BitmapDescriptorFactory.fromResource(R.drawable.maker); 131 mMarkerLy = (RelativeLayout) findViewById(R.id.id_maker_ly); 132 } 133 134 private void initView() { 135 // TODO Auto-generated method stub 136 mMapView = (MapView) findViewById(R.id.id_bmapView); 137 mBaiduMap = mMapView.getMap(); 138 //设置打开时的显示比列 这里显示500m左右 139 MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f); 140 mBaiduMap.setMapStatus(msu); 141 } 142 private void initLocation() { 143 // TODO Auto-generated method stub 144 mLocationClient = new LocationClient(this); 145 mLocationListener = new MyLocationListener(); 146 mLocationClient.registerLocationListener(mLocationListener); 147 //默认模式为普通型 148 mLocationMode = LocationMode.NORMAL; 149 LocationClientOption option = new LocationClientOption(); 150 option.setCoorType("bd09ll"); 151 option.setIsNeedAddress(true); 152 option.setOpenGps(true); 153 option.setScanSpan(1000); 154 155 mLocationClient.setLocOption(option); 156 157 // 初始化图标 158 mIconLocation = BitmapDescriptorFactory.fromResource(R.drawable.navi_map_gps_locked); 159 myOrientationListener = new MyOrientationListener(context); 160 myOrientationListener.setOnOrientationListener(new OnOrientationListener() 161 { 162 @Override 163 public void onOrientationChanged(float x) 164 { 165 mCurrentX = x; 166 } 167 }); 168 } 169 //activity销毁时百度地图也销毁 170 @Override 171 protected void onDestroy() { 172 super.onDestroy(); 173 //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理 174 mMapView.onDestroy(); 175 } 176 @Override 177 protected void onStart() { 178 // TODO Auto-generated method stub 179 super.onStart(); 180 // 开启定位 181 mBaiduMap.setMyLocationEnabled(true); 182 if (!mLocationClient.isStarted()) 183 mLocationClient.start(); 184 // 开启方向传感器 185 myOrientationListener.start(); 186 187 } 188 @Override 189 protected void onStop() { 190 // TODO Auto-generated method stub 191 super.onStop(); 192 // 停止定位 193 mBaiduMap.setMyLocationEnabled(false); 194 mLocationClient.stop(); 195 // 停止方向传感器 196 myOrientationListener.stop(); 197 } 198 @Override 199 protected void onResume() { 200 super.onResume(); 201 //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理 202 mMapView.onResume(); 203 } 204 @Override 205 protected void onPause() { 206 super.onPause(); 207 //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理 208 mMapView.onPause(); 209 } 210 @Override 211 public boolean onCreateOptionsMenu(Menu menu) { 212 // TODO Auto-generated method stub 213 214 getMenuInflater().inflate(R.menu.main, menu); 215 return true; 216 } 217 //菜单按钮的响应事件 218 @Override 219 public boolean onOptionsItemSelected(MenuItem item) { 220 // TODO Auto-generated method stub 221 switch (item.getItemId()) { 222 case R.id.id_map_common: 223 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL); 224 break; 225 case R.id.id_map_site: 226 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE); 227 break; 228 case R.id.id_map_traffic: 229 if(mBaiduMap.isTrafficEnabled()) 230 { 231 mBaiduMap.setTrafficEnabled(false); 232 item.setTitle("实时交通(off)"); 233 } 234 else 235 { 236 mBaiduMap.setTrafficEnabled(true); 237 item.setTitle("实时交通(on)"); 238 } 239 break; 240 case R.id.id_map_location: 241 //定位最新自己的位置 242 centerToMyLocation(); 243 break; 244 245 case R.id.id_mode_common: 246 //设置普通模式 247 mLocationMode = LocationMode.NORMAL; 248 break; 249 case R.id.id_mode_following: 250 //设置跟随模式 251 mLocationMode = LocationMode.FOLLOWING; 252 break; 253 case R.id.id_mode_compass: 254 //设置罗盘模式 255 mLocationMode = LocationMode.COMPASS; 256 break; 257 case R.id.id_add_overlay: 258 //设置添加覆盖物 259 addOverlays(Info.infos); 260 break; 261 default: 262 break; 263 } 264 return super.onOptionsItemSelected(item); 265 } 266 private void addOverlays(List<Info> infos) { 267 // TODO Auto-generated method stub 268 //添加覆盖物 269 //清楚定位的一些图层 270 mBaiduMap.clear(); 271 // 经纬度 272 LatLng latLng = null; 273 Marker marker = null; 274 OverlayOptions options; 275 for (Info info : infos) 276 { 277 // 经纬度 278 latLng = new LatLng(info.getLatitude(), info.getLongitude()); 279 // 图标 280 options = new MarkerOptions().position(latLng).icon(mMarker).zIndex(5);//5表示图层的位置,越大越在上面 281 marker = (Marker) mBaiduMap.addOverlay(options); 282 Bundle arg0 = new Bundle(); 283 arg0.putSerializable("info", info); 284 marker.setExtraInfo(arg0); 285 } 286 //定位好之后,讲地图定位到最后一个图标的位置 287 MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng); 288 mBaiduMap.setMapStatus(msu); 289 290 } 291 292 //进到自己的位置 293 private void centerToMyLocation() { 294 LatLng latLng = new LatLng(mLatitude,mLongtitude); 295 296 MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng); 297 mBaiduMap.animateMapStatus(msu); 298 } 299 private class MyLocationListener implements BDLocationListener{ 300 301 @Override 302 public void onReceiveLocation(BDLocation location) { 303 // TODO Auto-generated method stub 304 MyLocationData data = new MyLocationData.Builder()// 305 .direction(mCurrentX)// 306 .accuracy(location.getRadius())// 307 .latitude(location.getLatitude())// 308 .longitude(location.getLongitude())// 309 .build(); 310 mBaiduMap.setMyLocationData(data); 311 // 设置自定义图标 312 MyLocationConfiguration config = new MyLocationConfiguration(mLocationMode, true, mIconLocation); 313 mBaiduMap.setMyLocationConfigeration(config); 314 //获取最新经纬度 315 mLatitude = location.getLatitude(); 316 mLongtitude = location.getLongitude(); 317 //判断是否第一次定位 318 if (isFirstIn) 319 { 320 //设置经纬度 321 LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude()); 322 323 MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng); 324 mBaiduMap.animateMapStatus(msu); 325 //将是否第一次定位的标志 变为不是第一次定位 326 isFirstIn = false; 327 //显示当前定位的位置 328 Toast.makeText(context, location.getAddrStr(), 329 Toast.LENGTH_SHORT).show(); 330 } 331 332 } 333 334 } 335 }
其中红色字体部分为本篇新加代码
对应布局文件
activity_main.xml
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" > 5 6 <com.baidu.mapapi.map.MapView 7 android:id="@+id/id_bmapView" 8 android:layout_width="fill_parent" 9 android:layout_height="fill_parent" 10 android:clickable="true" /> 11 12 <RelativeLayout 13 android:id="@+id/id_maker_ly" 14 android:layout_width="match_parent" 15 android:layout_height="220dp" 16 android:layout_alignParentBottom="true" 17 android:background="#cc4e5a6b" 18 android:clickable="true" 19 android:visibility="gone" > 20 21 <ImageView 22 android:id="@+id/id_info_img" 23 android:layout_width="fill_parent" 24 android:layout_height="150dp" 25 android:layout_marginBottom="10dp" 26 android:layout_marginLeft="12dp" 27 android:layout_marginRight="12dp" 28 android:layout_marginTop="10dp" 29 android:background="@drawable/img_border" 30 android:scaleType="fitXY" 31 android:src="@drawable/a01" > 32 </ImageView> 33 34 <RelativeLayout 35 android:layout_width="fill_parent" 36 android:layout_height="50dp" 37 android:layout_alignParentBottom="true" 38 android:background="@drawable/bg_map_bottom" > 39 40 <LinearLayout 41 android:layout_width="wrap_content" 42 android:layout_height="wrap_content" 43 android:layout_centerVertical="true" 44 android:layout_marginLeft="20dp" 45 android:orientation="vertical" > 46 47 <TextView 48 android:id="@+id/id_info_name" 49 android:layout_width="wrap_content" 50 android:layout_height="wrap_content" 51 android:text="老米家泡馍" 52 android:textColor="#fff5eb" /> 53 54 <TextView 55 android:id="@+id/id_info_distance" 56 android:layout_width="wrap_content" 57 android:layout_height="wrap_content" 58 android:text="距离200米" 59 android:textColor="#fff5eb" /> 60 </LinearLayout> 61 62 <LinearLayout 63 android:layout_width="wrap_content" 64 android:layout_height="wrap_content" 65 android:layout_alignParentRight="true" 66 android:layout_centerVertical="true" 67 android:layout_marginRight="20dp" 68 android:orientation="horizontal" > 69 70 <ImageView 71 android:layout_width="wrap_content" 72 android:layout_height="wrap_content" 73 android:background="@drawable/map_zan" 74 android:clickable="true" /> 75 76 <TextView 77 android:id="@+id/id_info_zan" 78 android:layout_width="wrap_content" 79 android:layout_height="wrap_content" 80 android:layout_gravity="center" 81 android:text="789" 82 android:textColor="#fff5eb" /> 83 </LinearLayout> 84 </RelativeLayout> 85 </RelativeLayout> 86 87 </RelativeLayout>
效果图:
点击坐标便显示对应的信息,点击几个坐标以外的位置,信息框便会消失