如何将MaterialSearchView+Toolbar与Google Maps集成?
集成MaterialSearchView + Toolbar 与 Google Maps
我帮你梳理了完整的集成方案,从布局补全到功能实现,一步步带你完成搜索工具栏和Google Maps的联动:
第一步:补全布局文件
先把你的布局补全成这样,保证Toolbar、搜索组件和地图容器的层级与属性配置到位:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.myapp.DrawerActivityMainActivity"> <!-- 顶部导航Toolbar --> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:title="MyApp" app:titleTextColor="@android:color/white"/> <!-- MaterialSearchView 搜索组件 --> <com.miguelcatalan.materialsearchview.MaterialSearchView android:id="@+id/search_view" android:layout_width="match_parent" android:layout_height="wrap_content" app:mtv_background="@color/white" app:mtv_hint="搜索地点" app:mtv_textColor="@color/black" app:mtv_textColorHint="@color/grey"/> <!-- Google Maps 容器 --> <FrameLayout android:id="@+id/map_container" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 加载Google Maps的Fragment --> <fragment android:id="@+id/map_fragment" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout> </LinearLayout>
第二步:添加依赖与初始化组件
首先在build.gradle中添加必要的依赖:
// MaterialSearchView 依赖 implementation 'com.miguelcatalan:materialsearchview:1.4.0' // Google Maps 核心依赖 implementation 'com.google.android.gms:play-services-maps:18.1.0' // Google Places API(用于精准地点搜索) implementation 'com.google.android.gms:play-services-places:17.0.0'
然后在Activity中完成基础组件的初始化(以Kotlin为例,Java逻辑完全一致):
class DrawerActivityMainActivity : AppCompatActivity(), OnMapReadyCallback { private lateinit var toolbar: Toolbar private lateinit var searchView: MaterialSearchView private lateinit var googleMap: GoogleMap // 用于地点搜索的客户端 private lateinit var geoDataClient: GeoDataClient override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化Toolbar并设置为ActionBar toolbar = findViewById(R.id.toolbar) setSupportActionBar(toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) // 初始化MaterialSearchView searchView = findViewById(R.id.search_view) // 绑定Toolbar上的搜索按钮(需要提前在menu文件中定义) searchView.setMenuItem(menu.findItem(R.id.action_search)) // 初始化地点搜索客户端 geoDataClient = Places.getGeoDataClient(this) // 加载Google Maps val mapFragment = supportFragmentManager.findFragmentById(R.id.map_fragment) as SupportMapFragment mapFragment.getMapAsync(this) } // 地图加载完成后的回调 override fun onMapReady(map: GoogleMap) { googleMap = map // 设置地图初始位置(这里以北京为例) val initialLocation = LatLng(39.9042, 116.4074) googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(initialLocation, 12f)) } }
第三步:实现搜索与地图联动
给MaterialSearchView添加搜索监听,当用户提交搜索内容时,调用Places API查询地点并在地图上定位:
override fun onCreate(savedInstanceState: Bundle?) { // ... 保留之前的初始化代码 // 设置搜索提交监听 searchView.setOnQueryTextListener(object : MaterialSearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { query?.let { searchAndLocatePlace(it) } searchView.closeSearch() return true } override fun onQueryTextChange(newText: String?): Boolean { // 可选:在这里实现实时搜索建议 return false } }) } // 搜索地点并在地图上定位 private fun searchAndLocatePlace(query: String) { // 定义需要获取的地点字段 val placeFields = listOf(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG) // 构建搜索请求 val autocompleteRequest = FindAutocompletePredictionsRequest.builder() .setQuery(query) .setCountry("CN") // 设置搜索的国家代码,比如中国填CN .build() geoDataClient.findAutocompletePredictions(autocompleteRequest) .addOnSuccessListener { response -> if (response.autocompletePredictions.isNotEmpty()) { // 取第一个搜索结果 val prediction = response.autocompletePredictions[0] val placeId = prediction.placeId // 根据placeId获取详细地点信息 val placeRequest = FetchPlaceRequest.builder(placeId, placeFields).build() geoDataClient.fetchPlace(placeRequest) .addOnSuccessListener { placeResponse -> val place = placeResponse.place place.latLng?.let { latLng -> // 移动地图相机到目标地点 googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f)) // 在地图上添加标记 googleMap.addMarker(MarkerOptions().position(latLng).title(place.name)) } } } } .addOnFailureListener { exception -> // 处理搜索失败的情况 Toast.makeText(this, "搜索失败:${exception.message}", Toast.LENGTH_SHORT).show() } }
第四步:配置权限与API密钥
别忘了在AndroidManifest.xml中添加必要权限和Google服务的API密钥:
<!-- 地图与定位权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> <application> <!-- Google Maps/Places API 密钥(需要在Google Cloud Console生成) --> <meta-data android:name="com.google.android.geo.API_KEY" android:value="你的API密钥"/> </application>
额外注意点
- 要在Google Cloud Console中启用Maps SDK for Android和Places API,并生成有效的API密钥。
- Toolbar的搜索按钮需要在menu文件中定义,比如
res/menu/toolbar_menu.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_search" android:icon="@drawable/ic_search" android:title="搜索" app:showAsAction="ifRoom"/> </menu>
内容的提问来源于stack exchange,提问作者user3599803
相关产品推荐
相关产品推荐

