Android高德地图API实现POI搜索
实现效果图如下:
导入高德地图的搜索服务包到工程的libs目录中,并配置好权限与用户KEY。
权限如下:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
用户KEY配置如下:
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="这里填你的KEY"/>
创建activity_main.xml布局文件如下,因为要实现用户输入直接就显示数据,所以就没用到搜索按钮。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/search_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ListView
android:id="@+id/search_list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
创建address_item.xml布局文件如下,用于ListView中每一个Item布局。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp" >
<TextView
android:id="@+id/item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="标题"
android:textSize="20sp"/>
<TextView
android:id="@+id/item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="内容"
android:textColor="#FF4A4A4A"/>
</LinearLayout>
创建AddressBean实体类,代码如下
public class AddressBean {
private double longitude;//经度
private double latitude;//纬度
private String title;//信息标题
private String text;//信息内容
public AddressBean(double lon, double lat, String title, String text){
this.longitude = lon;
this.latitude = lat;
this.title = title;
this.text = text;
}
public double getLongitude() {
return longitude;
}
public double getLatitude() {
return latitude;
}
public String getTitle() {
return title;
}
public String getText(){
return text;
}
}
创建SearchAdapter数据适配器类,代码如下:
public class SearchAdapter extends BaseAdapter{
private List<AddressBean> data;
private LayoutInflater li;
public SearchAdapter(Context context){
li = LayoutInflater.from(context);
}
/**
* 设置数据集
* @param data
*/
public void setData(List<AddressBean> data){
this.data = data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh = null;
if(convertView == null){
vh = new ViewHolder();
convertView = li.inflate(R.layout.address_item, null);
vh.title = (TextView) convertView.findViewById(R.id.item_title);
vh.text = (TextView) convertView.findViewById(R.id.item_text);
convertView.setTag(vh);
}else{
vh = (ViewHolder) convertView.getTag();
}
vh.title.setText(data.get(position).getTitle());
vh.text.setText(data.get(position).getText());
return convertView;
}
private class ViewHolder{
public TextView title;
public TextView text;
}
}
这里会提供方法setData()用于动态更新数据集。
创建InputTask类,封装PoiSearch的搜索服务,并与Adapter进行绑定。
public class InputTask implements OnPoiSearchListener {
private static InputTask mInstance;
private SearchAdapter mAdapter;
private PoiSearch mSearch;
private Context mContext;
private InputTask(Context context, SearchAdapter adapter){
this.mContext = context;
this.mAdapter = adapter;
}
/**
* 获取实例
* @param context 上下文
* @param adapter 数据适配器
* @return
*/
public static InputTask getInstance(Context context, SearchAdapter adapter){
if(mInstance == null){
synchronized (InputTask.class) {
if(mInstance == null){
mInstance = new InputTask(context, adapter);
}
}
}
return mInstance;
}
/**
* 设置数据适配器
* @param adapter
*/
public void setAdapter(SearchAdapter adapter){
this.mAdapter = adapter;
}
/**
* POI搜索
* @param key 关键字
* @param city 城市
*/
public void onSearch(String key, String city){
//POI搜索条件
PoiSearch.Query query = new PoiSearch.Query(key, "", city);
mSearch = new PoiSearch(mContext, query);
//设置异步监听
mSearch.setOnPoiSearchListener(this);
//查询POI异步接口
mSearch.searchPOIAsyn();
}
/**
* 异步搜索回调
*/
@Override
public void onPoiSearched(PoiResult poiResult, int rCode) {
if(rCode == 0 && poiResult != null){
ArrayList<AddressBean> data = new ArrayList<AddressBean>();
ArrayList<PoiItem> items = poiResult.getPois();
for(PoiItem item : items){
//获取经纬度对象
LatLonPoint llp = item.getLatLonPoint();
double lon = llp.getLongitude();
double lat = llp.getLatitude();
//获取标题
String title = item.getTitle();
//获取内容
String text = item.getSnippet();
data.add(new AddressBean(lon, lat, title, text));
}
mAdapter.setData(data);
mAdapter.notifyDataSetChanged();
}
}
}
使用PoiSearch.Query定义搜索条件,构造方法有三个参数分别是:搜索关键字、POI类别、城市(地区)。
其中多个关键字用“|”分割,POI类别可以为””空字符串代表不区分类别,城市可以为””空字符串代表检索所有城市。
在搜索到结果回调的时候使用notifyDataSetChanged()更新数据适配器,实现数据动态更新。
创建MainAty类,代码如下:
public class MainAty extends Activity implements TextWatcher, OnItemClickListener{
private static final String TAG = "MainAty";
private EditText edit;
private ListView lv;
private SearchAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView(){
edit = (EditText) findViewById(R.id.search_edit);
lv = (ListView) findViewById(R.id.search_list);
edit.addTextChangedListener(this);
mAdapter = new SearchAdapter(this);
lv.setAdapter(mAdapter);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
InputTask.getInstance(this, mAdapter).onSearch(s.toString(), "");
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//Item点击事件处理
}
}
实现TextWatcher,并重写onTextChanged方法监听输入框数据的变化,从而实现实时更新数据。