Android必知必会-带列表的地图POI周边搜索

背景

先看效果图:(以公司附近的国贸为中心点)

上面是地图,下面是地理位置列表,有的只有地理位置列表(QQ动态的位置),这是个很常见的功能。它有个专门的叫法:POI周边搜索

实现

这个效果实现起来其实很简单,不过需要你先阅读下地图的API,这里使用的是高德地图的Android SDK,SDK的配置这里不作讲解,文末会放一些链接供学习。

思路:

  1. 利用地图的定位功能,获取用户当前的位置
  2. 根据获得的位置信息调用POI搜索,获取位置列表
  3. ListView展示位置列表
  4. 用户拖动地图,获取地图中心坐标的位置信息,并执行2~3的步骤

代码:

Layout:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<com.amap.api.maps2d.MapView
android:id="@+id/map_local"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"/>

<ListView
android:id="@+id/map_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:divider="@color/space"
android:dividerHeight="1dp"
android:scrollbars="none"/>

</LinearLayout>

Activity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
public class New_LocalActivity extends Activity implements LocationSource,
AMapLocationListener, AMap.OnCameraChangeListener, PoiSearch.OnPoiSearchListener {

@BindView(R.id.map_local)
MapView mapView;
@BindView(R.id.map_list)
ListView mapList;

public static final String KEY_LAT = "lat";
public static final String KEY_LNG = "lng";
public static final String KEY_DES = "des";


private AMapLocationClient mLocationClient;
private LocationSource.OnLocationChangedListener mListener;
private LatLng latlng;
private String city;
private AMap aMap;
private String deepType = "";// poi搜索类型
private PoiSearch.Query query;// Poi查询条件类
private PoiSearch poiSearch;
private PoiResult poiResult; // poi返回的结果
private PoiOverlay poiOverlay;// poi图层
private List<PoiItem> poiItems;// poi数据

private PoiSearch_adapter adapter;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new__local);
ButterKnife.bind(this);
mapView.onCreate(savedInstanceState);
init();
}

private void init() {
if (aMap == null) {
aMap = mapView.getMap();
aMap.setOnCameraChangeListener(this);
setUpMap();
}

deepType = "餐饮";//这里以餐饮为例
}

//-------- 定位 Start ------

private void setUpMap() {
if (mLocationClient == null) {
mLocationClient = new AMapLocationClient(getApplicationContext());
AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
//设置定位监听
mLocationClient.setLocationListener(this);
//设置为高精度定位模式
mLocationOption.setOnceLocation(true);
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置定位参数
mLocationClient.setLocationOption(mLocationOption);
mLocationClient.startLocation();
}
// 自定义系统定位小蓝点
MyLocationStyle myLocationStyle = new MyLocationStyle();
myLocationStyle.myLocationIcon(BitmapDescriptorFactory
.fromResource(R.drawable.location_marker));// 设置小蓝点的图标
myLocationStyle.strokeColor(Color.BLACK);// 设置圆形的边框颜色
myLocationStyle.radiusFillColor(Color.argb(100, 0, 0, 180));// 设置圆形的填充颜色
myLocationStyle.strokeWidth(1.0f);// 设置圆形的边框粗细
aMap.setMyLocationStyle(myLocationStyle);
aMap.setLocationSource(this);// 设置定位监听
aMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示
aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
}

/**
* 开始进行poi搜索
*/
protected void doSearchQuery() {
aMap.setOnMapClickListener(null);// 进行poi搜索时清除掉地图点击事件
int currentPage = 0;
query = new PoiSearch.Query("", deepType, city);// 第一个参数表示搜索字符串,第二个参数表示poi搜索类型,第三个参数表示poi搜索区域(空字符串代表全国)
query.setPageSize(20);// 设置每页最多返回多少条poiitem
query.setPageNum(currentPage);// 设置查第一页
LatLonPoint lp = new LatLonPoint(latlng.latitude, latlng.longitude);

poiSearch = new PoiSearch(this, query);
poiSearch.setOnPoiSearchListener(this);
poiSearch.setBound(new PoiSearch.SearchBound(lp, 5000, true));
// 设置搜索区域为以lp点为圆心,其周围2000米范围
poiSearch.searchPOIAsyn();// 异步搜索

}

@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (mListener != null && aMapLocation != null) {
if (aMapLocation.getErrorCode() == 0) {
// 显示我的位置
mListener.onLocationChanged(aMapLocation);
//设置第一次焦点中心
latlng = new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude());
aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latlng, 14), 1000, null);
city = aMapLocation.getProvince();
doSearchQuery();
} else {
String errText = "定位失败," + aMapLocation.getErrorCode() + ": " + aMapLocation.getErrorInfo();
Log.e("AmapErr", errText);
}
}
}

@Override
public void activate(OnLocationChangedListener listener) {
mListener = listener;
mLocationClient.startLocation();
}

@Override
public void deactivate() {
mListener = null;
if (mLocationClient != null) {
mLocationClient.stopLocation();
mLocationClient.onDestroy();
}
mLocationClient = null;
}

@Override
public void onCameraChange(CameraPosition cameraPosition) {
}

@Override
public void onCameraChangeFinish(CameraPosition cameraPosition) {
latlng = cameraPosition.target;
aMap.clear();
aMap.addMarker(new MarkerOptions().position(latlng));
doSearchQuery();
}

@Override
public void onPoiSearched(PoiResult result, int rCode) {
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();
if (poiItems != null && poiItems.size() > 0) {
adapter = new PoiSearch_adapter(this, poiItems);
mapList.setAdapter(adapter);
mapList.setOnItemClickListener(new mOnItemClickListener());

}
}
else {
Logger.d("无结果");
}
}
} else {
Logger.e("无结果");
}
} else if (rCode == 27) {
Logger.e("error_network");
} else if (rCode == 32) {
Logger.e("error_key");
} else {
Logger.e("error_other:" + rCode);
}
}

@Override
public void onPoiItemSearched(PoiItem poiItem, int i) {

}

//-------- 定位 End ------

@Override
protected void onResume() {
super.onResume();
mLocationClient.startLocation();
}

@Override
protected void onPause() {
super.onPause();
mLocationClient.stopLocation();
}

@Override
protected void onDestroy() {
mLocationClient.onDestroy();
super.onDestroy();
}

private class mOnItemClickListener implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent();
intent.putExtra(KEY_LAT, poiItems.get(position).getLatLonPoint().getLatitude());
intent.putExtra(KEY_LNG, poiItems.get(position).getLatLonPoint().getLongitude());
intent.putExtra(KEY_DES, poiItems.get(position).getTitle());
setResult(RESULT_OK, intent);
finish();
}
}

示例中的Activity是使用startActivityForResult方式启动的,最后点击位置之后会返回点选的位置信息。

总结

我第一次准备实现上述的效果时,也是不知所措,因为还没有对地图API有比较全面的认识,后来看了不少资料,自己便结合了一下地图的功能点,实现了设计图中的效果。

下面是一些资料,初学者务必先学习基础API的应用:

如果你有什么问题,可以在博客上留言。

PS:

你可以关注的我 GithubCSDN微博