百度地图4.1_1开发教程(9)poi搜索功能

来源:互联网 发布:樱桃初夏网络剧 编辑:程序博客网 时间:2024/05/30 22:43
继上次

http://blog.csdn.net/u012552275/article/details/53377213保存搜索历史

http://blog.csdn.net/u012552275/article/details/53364197百度地图4.1_1开发教程(6)点收藏(2)
之后,已经有段时间了,一直想把他写出来分享,但是太忙了。

本章包含:搜索建议 城市POI搜索,POI:  Point of Interest,翻译过来就是“兴趣点”。我们在百度地图看到的烤吧、网吧等都算是POI。百度地图SDK提供了三种类型的POI检索:周边检索、区域检索和城市内检索。由于我的项目只涉及到了城市检索,这里只对城市内检索做记录。满足不了需求的请绕道不要浪费时间。看图:

这里写图片描述

使用一个AutoComplateTextView来呈现搜索建议,点击其中一项呈现搜索结果:

这里写图片描述

点击其中某项,跳转地图对应点。

首先,在布局中加入控件AutoComplateTextView

<AutoCompleteTextView            android:id="@+id/activity_favo_add_et_search"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginRight="50dp"            android:background="@drawable/edit_backgroud"            android:drawableLeft="@mipmap/search_icon"            android:drawablePadding="@dimen/padding10"            android:hint="@string/favo_search_hint"            android:imeOptions="actionSearch"            android:maxLength="30"            android:maxLines="1"            android:padding="@dimen/padding10"            android:lines="1"            android:textColor="@color/ios_btntext_blue"            android:textColorHint="@color/gray"/>

在类中,我们需要对文字改变做出监听事件,当文字发生改变时,搜索关键词的建议结果显示至适配器。

private SuggestionSearch mSuggestionSearch = null; // 搜索建议    private PoiSearch mPoiSearch = null;// 初始化建议搜索模块,注册建议搜索事件监听        mSuggestionSearch = SuggestionSearch.newInstance();        mSuggestionSearch.setOnGetSuggestionResultListener(this);        // 初始化搜索模块,注册搜索事件监听        mPoiSearch = PoiSearch.newInstance();        mPoiSearch.setOnGetPoiSearchResultListener(this);

接下来,我们为控件添加文字改变的监听:

// 文字变动监听        et_search.addTextChangedListener(new TextWatcher()        {            @Override            public void beforeTextChanged(CharSequence s, int start, int count, int after)            {            }            @Override            public void onTextChanged(CharSequence s, int start, int before, int count)            {            }            @Override            public void afterTextChanged(Editable s)            {                // 输入的内容不可为空                if (TextUtils.isEmpty(s))                {                    return;                }                // 使用建议搜索服务获取建议列表,结果在onGetSuggestionResult()中更新                mSuggestionSearch                        .requestSuggestion((new SuggestionSearchOption())                                .keyword(s.toString()).city(""));            }        });

此时,我们让Activity 实现: implements OnGetSuggestionResultListener, OnGetPoiSearchResultListener这两个监听器

    /**     * 获取在线建议搜索结果,得到requestSuggestion返回的搜索结果     */    @Override    public void onGetSuggestionResult(SuggestionResult res)    {        if (res == null || res.getAllSuggestions() == null) // 不能为空        {            return;        }        suggestList = new ArrayList<>();        for (SuggestionResult.SuggestionInfo info : res.getAllSuggestions())        {            if (info.key != null) // 将结果集放入List中            {                suggestList.add(info.key);            }        }        sugAdapter = new ArrayAdapter<>(activity, R.layout.item_favo_add_suggess, suggestList);        et_search.setAdapter(sugAdapter);        sugAdapter.notifyDataSetChanged();    }

将搜索结果集用Adapter呈现出来,搜索建议的部分就完成了。它实现了根据关键词搜索近似的地理位置,而城市内搜索,只能搜城市内的地点,如果没有城市位置,应该是默认为北京市,当然也可以搜索其他地区的东西,只不过精确度应该会下降。接下来,点击搜索建议的Adapter,将搜索建议的内容作为搜索关键词,当我们按下键盘的搜索按钮,跳转到搜索结果。注意,搜索建议和搜索结果是不同的。

接下来,为ACTION_SEARCH做监听事件:

// 搜索        et_search.setOnEditorActionListener(new TextView.OnEditorActionListener()        {            @Override            public boolean onEditorAction(TextView v, int actionId, KeyEvent event)            {                String keyword = et_search.getText().toString().trim();                if (actionId == EditorInfo.IME_ACTION_SEARCH && !"".equals(keyword) && keyword != null)                {                    KeyboardUtils.closeKeyboard(activity, et_search); // 先隐藏键盘                    // 市内搜索,如果已有定位数据,使用已保存的,如果没有定位数据,则默认以北京为市搜索                    if (GlobalVariable.getLOCATION() != null)                    {                        mPoiSearch.searchInCity((new PoiCitySearchOption()).city(GlobalVariable.getLOCATION()).keyword(keyword).pageNum(loadIndex));                    } else                    {                        showToast("无法定位到当前城市,\n请确保开启定位权限提高搜索精确度。");                        mPoiSearch.searchInCity((new PoiCitySearchOption()).city(Constant.BEIJINGSHI).keyword(keyword).pageNum(loadIndex));                    }                    return true;                }                return false;            }        });

当搜索时,先隐藏键盘,然后使用API的接口
mPoiSearch.searchInCity((new PoiCitySearchOption()).city(GlobalVariable.getLOCATION()).keyword(keyword).pageNum(loadIndex));
GlobalVariable.getLOCATION()是我保存的全局变量,它保存了定位的当前的城市。keyword是搜索关键词,pageNum是页数,因为搜索建议可能成百上千。我的项目用不到,所以这里没细研究,就用第一页搜索建议作为参考。其结果在onGetPoiResult回调。

    /**     * 获取POI搜索结果,包括searchInCity,searchNearby,searchInBound返回的搜索结果     */    @Override    public void onGetPoiResult(PoiResult result)    {        if (result == null || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND)        {            Logger.w("1_1", "未找到结果");            return;        }        if (result.error == SearchResult.ERRORNO.NO_ERROR)        {        if (result == null || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND)        {            Logger.w("1_1", "未找到结果");            return;        }        if (result.error == SearchResult.ERRORNO.NO_ERROR)        {            startActivity(new Intent(activity, FavoSearchResultActivity.class).setFlags(FLAG_ACTIVITY_NEW_TASK)                            .putExtra("result", (Serializable) result.getAllPoi()),                    ActivityOptions.makeSceneTransitionAnimation(activity).toBundle());            return;        }        // 当输入关键字在本市没有找到,但在其他城市找到时,返回包含该关键字信息的城市列表        if (result.error == SearchResult.ERRORNO.AMBIGUOUS_KEYWORD)        {            String strInfo = "在多个地区:\n";            for (CityInfo cityInfo : result.getSuggestCityList())            {                strInfo += cityInfo.city;                strInfo += "\n";            }            strInfo += "\n找到结果,建议重新搜索更详细的地址!";            showToast(strInfo);        } else        {            showToast("搜索超时,请检查网络");        }    }    @Override    public void onGetPoiDetailResult(PoiDetailResult result)    {    }    @Override    public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult)    {    }
在多个城市搜索到关键地点,提示用户改变更精确的关键词搜索。如果搜索没发生错误并且不为空,我们将参数传递到下一级页面FavoSearchResultActivity展示。

在FavoSearchResultActivity中,仅有一个RecyclerView控件,布局就不贴了。
在各种初始化后,用适配器将传递来的结果显示出来:

// 接受查询的结果        infoList = (List<PoiInfo>) getIntent().getSerializableExtra("result");        mAdapter = new FavoSearchResultAdapter(activity, infoList);        rv_list.setAdapter(mAdapter);

给出Adapter的代码,使用interface添加点击事件,单击其中一项结果,跳转到地图对应的点

/** 搜索结果适配器 * Created by kowal on 2016/11/30. */public class FavoSearchResultAdapter extends RecyclerView.Adapter<FavoSearchResultAdapter.MyViewHolder>{    private List<PoiInfo> list;    private Context context;    private LayoutInflater mInflater;    private OnSearchResultItemCL listener = null;    public interface OnSearchResultItemCL    {        void onItemClick(View view, int position );    }    public void setOnItemClickListener(OnSearchResultItemCL mOnItemClickListener)    {        this.listener = mOnItemClickListener;    }    public FavoSearchResultAdapter (Context context , List<PoiInfo> list)    {        mInflater = LayoutInflater.from(context);        this.context = context;        this.list = list;    }    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)    {        MyViewHolder holder = new MyViewHolder(mInflater.inflate(                R.layout.item_favo_search_result, parent, false));        return holder;    }    @Override    public void onBindViewHolder(final MyViewHolder holder, final int position)    {        holder.tv_title.setText(list.get(position).name);//为控件绑定数据        holder.tv_address.setText(list.get(position).address);//为控件绑定数据        holder.tv_city.setText(list.get(position).city );//为控件绑定数据        if (null != listener)        {            holder.itemView.setOnClickListener(new View.OnClickListener()            {                @Override                public void onClick(View v)                {                    listener.onItemClick(holder.itemView, position );                }            });        }    }    @Override    public int getItemCount()    {        return list == null ? 0 : list.size();    }    class MyViewHolder extends RecyclerView.ViewHolder    {        TextView tv_title;        TextView tv_address;        TextView tv_city;        public MyViewHolder(final View itemView)        {            super(itemView);            tv_title = (TextView) itemView.findViewById(R.id.item_favo_search_result_tv_title);            tv_address = (TextView) itemView.findViewById(R.id.item_favo_search_result_tv_address);            tv_city = (TextView) itemView.findViewById(R.id.item_favo_search_result_tv_city);        }    }}

这样,我们在FavoSearchResultActivity中添加点击事件

mAdapter.setOnItemClickListener(new FavoSearchResultAdapter.OnSearchResultItemCL()        {            @Override            public void onItemClick(View view, int position)            {                // 跳转地图对应的点                startActivity(new Intent(activity, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)                                .putExtra("location", (Parcelable) infoList.get(position).location ),                        ActivityOptions.makeSceneTransitionAnimation(activity).toBundle());            }        });

infoList是搜索结果的List,百度已经帮我们序列化了,因此直接拿来用(Parcelable) ,在地图中,根据实际需要,getExtra–location就可以拿到经纬度,然后移动到该点即可。
我将用到的布局和类打包了一下,需要的可以下载。
http://download.csdn.net/detail/u012552275/9707348

0 0