如何在独立Search组件中获取地图参数实现地址搜索?
实现独立Search组件的地址搜索功能
核心思路
通过组件间传参实现Search和地图组件的解耦:让Search负责输入交互,地图组件处理数据请求和地图更新,无需合并代码到同一个文件。
步骤1:改造Search组件
让Search组件接收外部的文本控制器和搜索触发回调,实现输入内容向地图组件的传递,同时触发搜索逻辑:
class Search extends StatelessWidget { // 接收外部传入的文本控制器 final TextEditingController searchController; // 接收外部传入的搜索触发方法 final VoidCallback onSearchSubmitted; const Search({ Key? key, required this.searchController, required this.onSearchSubmitted, }) : super(key: key); @override Widget build(BuildContext context) { return Center( child: Column( children: [ SizedBox( height: MediaQuery.of(context).size.height * 0.68, ), CustomTextField( hintText: 'A donde vamos?', sizeW: MediaQuery.of(context).size.width * 0.9, // 绑定外部传入的控制器 controller: searchController, // 输入完成时触发外部的搜索方法 onSubmitted: (value) => onSearchSubmitted(), // 若需要实时搜索,可替换为onChanged: (value) => onSearchSubmitted() ), ], ), ); } }
如果你的CustomTextField原本不支持controller和onSubmitted参数,需要给它扩展属性:
class CustomTextField extends StatelessWidget { final String hintText; final double sizeW; final TextEditingController? controller; final Function(String)? onSubmitted; final Function(String)? onChanged; const CustomTextField({ Key? key, required this.hintText, required this.sizeW, this.controller, this.onSubmitted, this.onChanged, }) : super(key: key); @override Widget build(BuildContext context) { return SizedBox( width: sizeW, child: TextField( controller: controller, onSubmitted: onSubmitted, onChanged: onChanged, decoration: InputDecoration( hintText: hintText, // 保留你原本的样式配置 ), ), ); } }
步骤2:修改地图组件集成Search
在GoogleMapsLocation的布局中加入Search组件,把自身的文本控制器和搜索方法传递过去:
class GoogleMapsLocation extends StatefulWidget { const GoogleMapsLocation({super.key}); @override State<GoogleMapsLocation> createState() => _GoogleMapsLocationState(); } class _GoogleMapsLocationState extends State<GoogleMapsLocation> { late GoogleMapController googleController; CameraPosition _initialCameraPosition = const CameraPosition( target: LatLng(37.42796133580664, -122.085749655962), zoom: 14.0, ); final TextEditingController _searchController = TextEditingController(); Set<Marker> markers = {}; Future<void> getLocations() async { Loading.loadingCircle(context: context); Location? placeLocation = await ServicesLocation.getLocation( context: context, text: _searchController.text); if (placeLocation != null) { setState(() { _initialCameraPosition = CameraPosition( target: LatLng(placeLocation.latitude, placeLocation.longitude), zoom: 14); markers.add(Marker( markerId: const MarkerId('Ubicación lugar'), position: LatLng(placeLocation.latitude, placeLocation.longitude))); }); googleController.animateCamera( CameraUpdate.newCameraPosition(_initialCameraPosition)); } Navigator.of(context).pop(); } @override Widget build(BuildContext context) { return Stack( children: [ GoogleMap( zoomControlsEnabled: false, markers: markers, mapType: MapType.terrain, initialCameraPosition: _initialCameraPosition, onMapCreated: (GoogleMapController controller) { googleController = controller; }, ), messageAvatar(), // 加入Search组件,传递控制器和搜索方法 Search( searchController: _searchController, onSearchSubmitted: getLocations, ), ], ); } }
逻辑说明
- Search组件仅负责输入交互,数据请求、地图更新等核心逻辑仍保留在地图组件中,实现了职责分离。
- 输入的搜索内容通过
TextEditingController传递到地图组件,触发getLocations方法调用ServicesLocation获取地址数据。 - 搜索完成后,地图组件通过
setState更新标记和相机位置,完成地图跳转。
内容的提问来源于stack exchange,提问作者Julian Hernandez
相关产品推荐
相关产品推荐

