package com.partynetwork.iparty.map; import java.util.List; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Color; import android.graphics.Point; import android.location.Location; import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; import android.view.View; import android.view.animation.BounceInterpolator; import android.view.animation.Interpolator; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.EditText; import android.widget.ImageView; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.SlidingDrawer; import android.widget.TextView; import android.widget.SlidingDrawer.OnDrawerCloseListener; import android.widget.SlidingDrawer.OnDrawerOpenListener; import com.amap.api.location.AMapLocation; import com.amap.api.location.AMapLocationListener; import com.amap.api.location.LocationManagerProxy; import com.amap.api.location.LocationProviderProxy; import com.amap.api.maps.AMap; import com.amap.api.maps.AMap.InfoWindowAdapter; import com.amap.api.maps.AMap.OnInfoWindowClickListener; import com.amap.api.maps.AMap.OnMapLongClickListener; import com.amap.api.maps.AMap.OnMarkerClickListener; import com.amap.api.maps.AMap.OnMarkerDragListener; import com.amap.api.maps.CameraUpdateFactory; import com.amap.api.maps.LocationSource; import com.amap.api.maps.MapView; import com.amap.api.maps.Projection; import com.amap.api.maps.UiSettings; import com.amap.api.maps.model.BitmapDescriptorFactory; import com.amap.api.maps.model.LatLng; import com.amap.api.maps.model.Marker; import com.amap.api.maps.model.MarkerOptions; import com.amap.api.maps.model.MyLocationStyle; import com.amap.api.maps.overlay.PoiOverlay; import com.amap.api.services.core.LatLonPoint; import com.amap.api.services.core.PoiItem; import com.amap.api.services.core.SuggestionCity; import com.amap.api.services.geocoder.GeocodeResult; import com.amap.api.services.geocoder.GeocodeSearch; import com.amap.api.services.geocoder.GeocodeSearch.OnGeocodeSearchListener; import com.amap.api.services.geocoder.RegeocodeQuery; import com.amap.api.services.geocoder.RegeocodeResult; import com.amap.api.services.poisearch.Cinema; import com.amap.api.services.poisearch.Dining; import com.amap.api.services.poisearch.Hotel; import com.amap.api.services.poisearch.PoiItemDetail; import com.amap.api.services.poisearch.PoiResult; import com.amap.api.services.poisearch.PoiSearch; import com.amap.api.services.poisearch.Scenic; import com.amap.api.services.poisearch.PoiSearch.OnPoiSearchListener; import com.amap.api.services.poisearch.PoiSearch.SearchBound; import com.lidroid.xutils.ViewUtils; import com.lidroid.xutils.view.annotation.ViewInject; import com.lidroid.xutils.view.annotation.event.OnClick; import com.partynetwork.dataprovider.util.AMapUtil; import com.partynetwork.dataprovider.util.Util; import com.partynetwork.iparty.R; import com.partynetwork.iparty.find.FindItemAdapter; /** * AMapV2地图中介绍如何使用mapview显示地图 */ public class BasicMapActivity extends Activity implements LocationSource, AMapLocationListener, OnMarkerDragListener, OnMarkerClickListener, OnPoiSearchListener, InfoWindowAdapter, OnMapLongClickListener, OnInfoWindowClickListener, OnDrawerCloseListener, OnDrawerOpenListener, OnGeocodeSearchListener, OnItemClickListener { public static final int MAP_CODE = 80; public static final String ADDRESS = "address"; public static final String LATITUDE = "latitude"; public static final String LONGITUDE = "longitude"; private AMap aMap; /** * 地图视图 */ @ViewInject(R.id.map) private MapView mapView; /** * 显示餐馆信息的listview */ @ViewInject(R.id.find_content_lv) private ListView mListView; /** * 输入的文本 */ @ViewInject(R.id.find_search_et) private EditText keyEdit; /** * 抽屉 */ @ViewInject(R.id.slidingdrawer) private SlidingDrawer slidingDrawer; /** * SlidingDrawer 的 三角箭头 */ @ViewInject(R.id.handle_icon) private ImageView handleIcon; /** * 完成 */ @ViewInject(R.id.menu_head_right_tv) private TextView submit; /** * 地址布局 */ @ViewInject(R.id.address_rl) private RelativeLayout addressRl; /** * 地址文本 */ @ViewInject(R.id.address_tv) private TextView addressTv; /** listview适配器 */ public FindItemAdapter mFindItemAdapter; /** 定位监听 */ private OnLocationChangedListener mListener; /** 位置管理 */ private LocationManagerProxy mAMapLocationManager; /** 地图控件是否显示 */ private UiSettings mUiSettings; /** 搜索时进度条 */ private ProgressDialog progDialog = null; /** Poi查询条件类 */ private PoiSearch.Query query; /** Poi搜索对象 */ private PoiSearch poiSearch; /** 显示Marker的详情 */ private Marker detailMarker; /** poi返回的结果 */ private PoiResult poiResult; /** poi数据 */ private List<PoiItem> poiItems; /** poi图层 */ private PoiOverlay poiOverlay; /** 标识 */ private MarkerOptions markerOption; /** 长按时的标识 */ private Marker longMarker; /** 跳跃的坐标 */ private LatLng latLng; /** 点击的位置名称 */ private String addressTitle; /** 点击的位置 */ private String addressSnippet; /** poi搜索关键字 */ private String keyWord = "餐厅"; /** 城市名称 */ private String cityName; /** 最后确定的点 */ private PoiItem mPoiItem; /** 我的位置 */ private AMapLocation myAMapLocation; /** 逆地理编码对象 */ private GeocodeSearch geocoderSearch; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // R 需要引用包import com.amapv2.apis.R; setContentView(R.layout.find); ViewUtils.inject(this); mapView.onCreate(savedInstanceState);// 必须要写 init(); } /** * 初始化AMap对象 */ private void init() { if (aMap == null) { aMap = mapView.getMap(); setUpMap(); } slidingDrawer.setOnDrawerCloseListener(this); slidingDrawer.setOnDrawerOpenListener(this); setListener(); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { PoiItem poiItem = poiItems.get(position); mPoiItem = poiItem; String str = poiItem.getTitle() + poiItem.getSnippet(); addressRl.setVisibility(View.VISIBLE); addressTv.setText(str); submit.setTextColor(getResources().getColor(R.color.blue_text)); LatLonPoint latLonPoint = poiItem.getLatLonPoint(); aMap.animateCamera(CameraUpdateFactory.changeLatLng(AMapUtil .convertToLatLng(latLonPoint))); List<Marker> markers = aMap.getMapScreenMarkers(); if (position >= markers.size()) { addressTitle = poiItem.getTitle(); addressSnippet = poiItem.getSnippet(); drawMarkers(AMapUtil.convertToLatLng(latLonPoint)); } else { markers.get(position).showInfoWindow(); } } /** * 设置监听 */ private void setListener() { mListView.setOnItemClickListener(this); } /** * 显示我的位置 */ private void setUpMap() { // 自定义系统定位小蓝点 MyLocationStyle myLocationStyle = new MyLocationStyle(); myLocationStyle.myLocationIcon(BitmapDescriptorFactory .fromResource(R.drawable.map_icon));// 设置小蓝点的图标 myLocationStyle.strokeColor(Color.BLUE);// 设置圆形的边框颜色 // myLocationStyle.radiusFillColor(color)//设置圆形的填充颜色 // myLocationStyle.anchor(int,int)//设置小蓝点的锚点 myLocationStyle.strokeWidth(0.01f);// 设置圆形的边框粗细 aMap.setMyLocationStyle(myLocationStyle); aMap.setMyLocationRotateAngle(180); aMap.setLocationSource(this);// 设置定位监听 aMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示 aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false aMap.setOnMarkerDragListener(this);// 设置marker可拖拽事件监听器 aMap.setOnMarkerClickListener(this);// 设置点击marker事件监听器 aMap.setInfoWindowAdapter(this);// 添加显示infowindow监听事件 aMap.setOnInfoWindowClickListener(this);// 设置点击infoWindow事件监听器 aMap.setOnMapLongClickListener(this);// 对amap添加长按地图事件监听器 mUiSettings = aMap.getUiSettings(); /** * 设置地图默认的缩放按钮是否显示 */ mUiSettings.setZoomControlsEnabled(false); /** * 设置地图默认的定位按钮是否显示 */ mUiSettings.setMyLocationButtonEnabled(false); geocoderSearch = new GeocodeSearch(this); geocoderSearch.setOnGeocodeSearchListener(this); initData(); } private void initData() { markerOption = new MarkerOptions(); } /** * 事件监听 * * @param view */ @OnClick({ R.id.menu_head_left, R.id.find_more_iv, R.id.menu_head_right }) public void onClick(View view) { switch (view.getId()) { case R.id.menu_head_left: // 关闭 finish(); break; case R.id.find_more_iv: // 搜索 String text = keyEdit.getText().toString(); if (text.equals("")) { } else { keyWord = text; doSearchQuery(null); keyEdit.setText(""); } break; case R.id.menu_head_right: // 完成 Intent intent = new Intent(); intent.putExtra(ADDRESS, mPoiItem.getTitle() + mPoiItem.getSnippet()); intent.putExtra(LATITUDE, mPoiItem.getLatLonPoint().getLatitude()); intent.putExtra(LONGITUDE, mPoiItem.getLatLonPoint().getLongitude()); setResult(MAP_CODE, intent); finish(); break; default: break; } } /** * 方法必须重写 */ @Override protected void onResume() { super.onResume(); mapView.onResume(); } /** * 方法必须重写 */ @Override protected void onPause() { super.onPause(); mapView.onPause(); } /** * 方法必须重写 */ @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } /** * 方法必须重写 */ @Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); } /******************************************************************************** 方法 */ /** * 开始进行poi搜索 */ protected void doSearchQuery(LatLonPoint lp) { showProgressDialog();// 显示进度框 query = new PoiSearch.Query(keyWord, "", cityName);// 第一个参数表示搜索字符串,第二个参数表示poi搜索类型,第三个参数表示poi搜索区域(空字符串代表全国) query.setPageSize(30);// 设置每页最多返回多少条poiitem query.setPageNum(0);// 设置查第一页 query.setLimitDiscount(false); query.setLimitGroupbuy(false); poiSearch = new PoiSearch(this, query); poiSearch.setOnPoiSearchListener(this); if (lp != null) { poiSearch.setBound(new SearchBound(lp, 5000, true));// } else { poiSearch .setBound(new SearchBound(new LatLonPoint(myAMapLocation .getLatitude(), myAMapLocation.getLongitude()), 10000, true));// } poiSearch.searchPOIAsyn();// 异步搜索 } /** * 显示进度框 */ private void showProgressDialog() { if (progDialog == null) progDialog = new ProgressDialog(this); progDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progDialog.setIndeterminate(false); progDialog.setCancelable(false); progDialog.setMessage("正在搜索中"); try { progDialog.show(); } catch (Exception e) { } } /** * 绘制系统默认的1种marker背景图片 */ public void drawMarkers(LatLng latlng) { aMap.clear();// 清理之前的图标 markerOption.title(addressTitle); if (addressSnippet.length() > 20) { addressSnippet = addressSnippet.substring(0, 20) + "\n" + addressSnippet.substring(20); } markerOption.snippet(addressSnippet); markerOption.position(latlng); markerOption.perspective(true); markerOption.draggable(true); markerOption.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_BLUE)); longMarker = aMap.addMarker(markerOption); longMarker.showInfoWindow();// 设置默认显示一个infowinfow } /** * marker点击时跳动一下 */ public void jumpPoint(final Marker marker) { final Handler handler = new Handler(); final long start = SystemClock.uptimeMillis(); Projection proj = aMap.getProjection(); Point startPoint = proj.toScreenLocation(latLng); startPoint.offset(0, -100); final LatLng startLatLng = proj.fromScreenLocation(startPoint); final long duration = 1500; final Interpolator interpolator = new BounceInterpolator(); handler.post(new Runnable() { @Override public void run() { long elapsed = SystemClock.uptimeMillis() - start; float t = interpolator.getInterpolation((float) elapsed / duration); double lng = t * latLng.longitude + (1 - t) * startLatLng.longitude; double lat = t * latLng.latitude + (1 - t) * startLatLng.latitude; marker.setPosition(new LatLng(lat, lng)); if (t < 1.0) { handler.postDelayed(this, 16); } } }); } /** * 隐藏进度框 */ private void dissmissProgressDialog() { if (progDialog != null) { progDialog.dismiss(); } } /** * POI深度信息获取 */ private StringBuffer getDeepInfo(PoiItemDetail result, StringBuffer sbuBuffer) { switch (result.getDeepType()) { // 餐饮深度信息 case DINING: if (result.getDining() != null) { Dining dining = result.getDining(); sbuBuffer .append("\n菜系:" + dining.getTag() + "\n特色:" + dining.getRecommend() + "\n来源:" + dining.getDeepsrc()); } break; // 酒店深度信息 case HOTEL: if (result.getHotel() != null) { Hotel hotel = result.getHotel(); sbuBuffer.append("\n价位:" + hotel.getLowestPrice() + "\n卫生:" + hotel.getHealthRating() + "\n来源:" + hotel.getDeepsrc()); } break; // 景区深度信息 case SCENIC: if (result.getScenic() != null) { Scenic scenic = result.getScenic(); sbuBuffer .append("\n价钱:" + scenic.getPrice() + "\n推荐:" + scenic.getRecommend() + "\n来源:" + scenic.getDeepsrc()); } break; // 影院深度信息 case CINEMA: if (result.getCinema() != null) { Cinema cinema = result.getCinema(); sbuBuffer.append("\n停车:" + cinema.getParking() + "\n简介:" + cinema.getIntro() + "\n来源:" + cinema.getDeepsrc()); } break; default: break; } return sbuBuffer; } /** * 查单个poi详情 * * @param poiId */ public void doSearchPoiDetail(String poiId) { if (poiSearch != null && poiId != null) { poiSearch.searchPOIDetailAsyn(poiId); } } /** * poi没有搜索到数据,返回一些推荐城市的信息 */ private void showSuggestCity(List<SuggestionCity> cities) { } /** * 响应逆地理编码 */ public void getAddress(final LatLonPoint latLonPoint) { RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 200, GeocodeSearch.AMAP);// 第一个参数表示一个Latlng,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 geocoderSearch.getFromLocationAsyn(query);// 设置同步逆地理编码请求 } /******************************************************************************** 监听 */ /** * 激活定位 */ @Override public void activate(OnLocationChangedListener listener) { mListener = listener; if (mAMapLocationManager == null) { mAMapLocationManager = LocationManagerProxy.getInstance(this); /* * mAMapLocManager.setGpsEnable(false); * 1.0.2版本新增方法,设置true表示混合定位中包含gps定位,false表示纯网络定位,默认是true Location * API定位采用GPS和网络混合定位方式 * ,第一个参数是定位provider,第二个参数时间最短是5000毫秒,第三个参数距离间隔单位是米,第四个参数是定位监听者 */ mAMapLocationManager.requestLocationUpdates( LocationProviderProxy.AMapNetwork, 5000, 10, this); } } /** * 停止定位 */ @Override public void deactivate() { mListener = null; if (mAMapLocationManager != null) { mAMapLocationManager.removeUpdates(this); mAMapLocationManager.destory(); } mAMapLocationManager = null; } @Override public void onLocationChanged(Location location) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } /** * 定位成功后回调函数 */ @Override public void onLocationChanged(AMapLocation aLocation) { if (mListener != null && aLocation != null) { myAMapLocation = aLocation; mListener.onLocationChanged(aLocation);// 显示系统小蓝点 float bearing = aMap.getCameraPosition().bearing; aMap.setMyLocationRotateAngle(bearing);// 设置小蓝点旋转角度 deactivate(); doSearchQuery(new LatLonPoint(aLocation.getLatitude(), aLocation.getLongitude())); cityName = aLocation.getCity(); } } /** * 监听拖动marker时事件回调 */ @Override public void onMarkerDrag(Marker arg0) { } /** * 监听拖动marker结束事件回调 */ @Override public void onMarkerDragEnd(Marker arg0) { latLng = arg0.getPosition(); } /** * 监听开始拖动marker事件回调 */ @Override public void onMarkerDragStart(Marker arg0) { } /** * 对marker标注点点击响应事件 */ @Override public boolean onMarkerClick(Marker marker) { if (aMap != null) { if (marker.getPosition().equals(latLng)) { jumpPoint(marker); } else if (poiOverlay != null && poiItems != null && poiItems.size() > 0) { detailMarker = marker; doSearchPoiDetail(poiItems.get(poiOverlay.getPoiIndex(marker)) .getPoiId()); } } return false; } /** * POI详情回调 */ @Override public void onPoiItemDetailSearched(PoiItemDetail result, int rCode) { dissmissProgressDialog();// 隐藏对话框 if (rCode == 0) { if (result != null) {// 搜索poi的结果 if (detailMarker != null) { StringBuffer sb = new StringBuffer(result.getSnippet()); if ((result.getGroupbuys() != null && result.getGroupbuys() .size() > 0) || (result.getDiscounts() != null && result .getDiscounts().size() > 0)) { if (result.getGroupbuys() != null && result.getGroupbuys().size() > 0) {// 取第一条团购信息 sb.append("\n团购:" + result.getGroupbuys().get(0).getDetail()); } if (result.getDiscounts() != null && result.getDiscounts().size() > 0) {// 取第一条优惠信息 sb.append("\n优惠:" + result.getDiscounts().get(0).getDetail()); } int i = 0; int index = 0; while (index < sb.length()) {// 描述太长,分割显示 if (sb.charAt(index) == '\n') {// 已经有换行,重新计算 i = 0; } index++; i++; if (i % 25 == 0) { sb.insert(index, '\n'); } } } else { sb = new StringBuffer("地址:" + result.getSnippet() + "\n电话:" + result.getTel() + "\n类型:" + result.getTypeDes()); } sb = getDeepInfo(result, sb);// 加入poi搜索深度信息 detailMarker.setSnippet(sb.toString()); } } else { } } else if (rCode == 27) { Util.showMsg(this, R.string.error_network); } else if (rCode == 32) { Util.showMsg(this, R.string.error_key); } else { Util.showMsg(this, R.string.error_other); } } /** * POI搜索回调 */ @Override public void onPoiSearched(PoiResult result, int rCode) { dissmissProgressDialog();// 隐藏对话框 if (rCode == 0) { if (result != null && result.getQuery() != null) {// 搜索poi的结果 if (result.getQuery().equals(query)) {// 是否是同一条 poiResult = result; poiItems = poiResult.getPois();// 取得第一页的poiitem数据,页数从数字0开始 List<SuggestionCity> suggestionCities = poiResult .getSearchSuggestionCitys();// 当搜索不到poiitem数据时,会返回含有搜索关键字的城市信息 if (poiItems != null && poiItems.size() > 0) { // 添加到适配器 mFindItemAdapter = new FindItemAdapter(this, poiItems); mListView.setAdapter(mFindItemAdapter); /** * 打开抽屉 */ slidingDrawer.animateOpen(); aMap.clear();// 清理之前的图标 poiOverlay = new PoiOverlay(aMap, poiItems); poiOverlay.removeFromMap(); poiOverlay.addToMap(); poiOverlay.zoomToSpan(); } else if (suggestionCities != null && suggestionCities.size() > 0) { showSuggestCity(suggestionCities); } else { Util.showMsg(this, R.string.no_result); } } } else { Util.showMsg(this, R.string.no_result); } } else if (rCode == 27) { Util.showMsg(this, R.string.error_network); } else if (rCode == 32) { Util.showMsg(this, R.string.error_key); } else { Util.showMsg(this, R.string.error_other); } } @Override public View getInfoContents(Marker arg0) { return null; } @Override public View getInfoWindow(Marker arg0) { return null; } /** * 对长按地图事件回调 */ @Override public void onMapLongClick(LatLng arg0) { latLng = arg0; getAddress(new LatLonPoint(arg0.latitude, arg0.longitude)); } @Override public void onInfoWindowClick(Marker arg0) { String str = arg0.getSnippet() + arg0.getTitle(); addressRl.setVisibility(View.VISIBLE); addressTv.setText(str); submit.setTextColor(getResources().getColor(R.color.blue_text)); PoiItem poi = new PoiItem("1", new LatLonPoint( arg0.getPosition().latitude, arg0.getPosition().longitude), arg0.getTitle(), arg0.getSnippet()); mPoiItem = poi; } @Override public void onDrawerOpened() { handleIcon.setImageResource(R.drawable.map_handle_down); } @Override public void onDrawerClosed() { handleIcon.setImageResource(R.drawable.map_handle_up); } /** * 地理编码查询回调 */ @Override public void onGeocodeSearched(GeocodeResult arg0, int arg1) { } /** * 逆地理编码回调 */ @Override public void onRegeocodeSearched(RegeocodeResult result, int rCode) { if (rCode == 0) { if (result != null && result.getRegeocodeAddress() != null && result.getRegeocodeAddress().getFormatAddress() != null) { addressTitle = result.getRegeocodeAddress().getBuilding(); addressSnippet = result.getRegeocodeAddress() .getFormatAddress(); aMap.animateCamera(CameraUpdateFactory.changeLatLng(AMapUtil .convertToLatLng(new LatLonPoint(latLng.latitude, latLng.longitude)))); drawMarkers(latLng); } else { Util.showMsg(this, R.string.no_result); } } else if (rCode == 27) { Util.showMsg(this, R.string.error_network); } else if (rCode == 32) { Util.showMsg(this, R.string.error_key); } else { Util.showMsg(this, R.string.error_other); } } }