开发国内应用当我们需要使用到地图时,首选肯定是高德地图或者百度地图,这是因为它们的地图功能足够强大,对于开发人员来说,更是因为 API 封装的完善和简单的调用实现,扩展功能强大。
如果要开发全球通用的 APP,需要集成地图,我们难免会对需要使用的地图 SDK 进行一番调研,百度和高德并没有全世界范围的地图数据,在亚洲或许还能使用以下,对于需要全球范围内都要使用到的就那么不适用了。
所以我们可选方案就只有 MapBox 和 Google Map 了,相对于 MapBox,Google Map 的地点数据非常详尽,特别是对于多语言,区分国家这类的 APP 了。在地图开发中,多语言是一件特别麻烦的事情,例如手机语言是中文,定位位置是美国,现在在地图上用中文搜索美国黄石公园,因为手机语言是中文,也要求搜索返回结果是中文。或者手机语言是中文,我在中国湖北搜索武汉 East Lake 要求返回查询东湖的英文结果等等,因为你不能确定你的 APP 用户是哪国人,在哪个国家使用你的 APP,这样一来如果自己实现语言和区域转换就极度复杂了,就算是调用 Google Map WebService API,要处理好数据也不是那么容易的事情。另外一个场景就是,就是假定我的定位位置是日本,我的搜索结果只允许返回日本的数据,同样,实现在哪个国家搜索地点,就返回哪个国家的地点数据等,这时候,使用 Google Map 就方便多了。
Google Map 的 Android 搜索自动提示文档可参考:
https://developers.google.com/places/android-sdk/autocomplete
对于这个功能的实现,Google Map 的建议是使用 Activity 或者 Fragment,如果你的 APP 风格比较统一,不想让用户跳转到其它 Activity 中,那么就可以使用 Fragment,在我的项目中就是这么使用的。
第一步是界面,代码如下,在你的对应的 Layout 添加:
<fragment
android:id="@+id/place_autocomplete_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment"
/>
在 Java 代码中的处理控件的事件和搜索返回结果:
PlaceAutocompleteFragment autocompleteFragment = (PlaceAutocompleteFragment)
getFragmentManager().findFragmentById(R.id.place_autocomplete_fragment);
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(Place place) {
// TODO: Get info about the selected place.
Log.i(TAG, "Place: " + place.getName());
}
@Override
public void onError(Status status) {
// TODO: Handle the error.
Log.i(TAG, "An error occurred: " + status);
}
});
当然这是非常极简的调用了,上面说到的依据国家区域等,下面会提到。
AutocompleteFilter 会为地点搜素功能设置过滤器,文档参见:
我们可以先构造一个 AutocompleteFilter.Builder 对象
AutocompleteFilter.Builder typeFilterBuilder = new AutocompleteFilter.Builder().setTypeFilter(AutocompleteFilter.TYPE_FILTER_NONE);
接下来可以通过 setCountry(String country) 方法设置返回结果的国家区域。country 参数在文档中的描述如下:
The country to restrict results to. This should be a ISO 3166-1 Alpha-2 country code (case insensitive). If this is not set, no country filtering will take place.
对于 ISO 3166-1 是国际上规定的国家区域码,目前全球230多个国家已经有对应的国家代码,可以参考:
https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
至此自动搜索的功能基本就可以实现,相信大部分开发者实现起来也没有太大问题,更多的是搜索框,文字如何和主题色保持一致,这个就相对麻烦点了,通过查看 PlaceAutocompleteFragment 的源代码,可以知道搜索框 Fragment 是三个控件组成,一个放大镜 ImageView 控件,一个 EditText 用于输入关键字的控件,还有一个清除搜索的 × 图标控件,基于此,我们可以动态的删除或隐藏控件即可。
try {
EditText editText = mAutocompleteView.getView().findViewById(R.id.place_autocomplete_search_input);
editText.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.color_258CAA));
editText.setHintTextColor(ContextCompat.getColor(getApplicationContext(), R.color.color_258CAA));
editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
View view = mAutocompleteView.getView().findViewById(R.id.place_autocomplete_search_button);
view.setVisibility(View.GONE);
} catch (Exception __) {
Log.e("GoogleMap",__);
}