Flutter中点击分区后基于ID筛选展示对应地点列表的实现需求
Flutter 实现分区点击筛选地点功能
实现核心逻辑
- 维护选中分区ID的状态,点击分区时更新该状态
- 根据选中ID过滤
LocationLists中对应的数据 - 将过滤后的数据传入
GridView.builder展示
方式一:基础 StatefulWidget 实现
直接在页面内部管理选中状态,适合简单场景:
import 'package:flutter/material.dart'; // 导入你的 DivisionClass 和 Locations 类 class LocationFilterScreen extends StatefulWidget { const LocationFilterScreen({super.key}); @override State<LocationFilterScreen> createState() => _LocationFilterScreenState(); } class _LocationFilterScreenState extends State<LocationFilterScreen> { String? _selectedDivisionId; final DivisionLists _divisionData = DivisionLists(); final LocationLists _locationData = LocationLists(); @override Widget build(BuildContext context) { // 过滤对应ID的地点数据 final filteredLocations = _selectedDivisionId == null ? _locationData.locationList : _locationData.locationList .where((loc) => loc.id == _selectedDivisionId) .toList(); return Scaffold( appBar: AppBar(title: const Text('分区地点筛选')), body: Column( children: [ // 横向分区选择栏 SizedBox( height: 80, child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 8), itemCount: _divisionData.divisionList.length, itemBuilder: (ctx, index) { final division = _divisionData.divisionList[index]; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: GestureDetector( onTap: () => setState(() => _selectedDivisionId = division.id), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: _selectedDivisionId == division.id ? Colors.blue : Colors.grey.shade200, borderRadius: BorderRadius.circular(20), ), child: Text( division.divisionName!, style: TextStyle( color: _selectedDivisionId == division.id ? Colors.white : Colors.black, fontWeight: FontWeight.bold, ), ), ), ), ); }, ), ), // 地点展示 GridView Expanded( child: GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 16, mainAxisSpacing: 16, childAspectRatio: 0.8, ), itemCount: filteredLocations.length, itemBuilder: (ctx, index) { final location = filteredLocations[index]; return Card( elevation: 4, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Image.network( location.dImageUrl!, fit: BoxFit.cover, width: double.infinity, ), ), Padding( padding: const EdgeInsets.all(8), child: Text( location.locationName!, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Text( location.locationDescription!, style: const TextStyle(fontSize: 12, color: Colors.grey), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), ], ), ); }, ), ), ], ), ); } }
方式二:结合 Provider 全局状态管理
适合需要跨页面共享选中状态的场景:
1. 扩展 LocationLists 添加过滤方法
class LocationLists with ChangeNotifier { final List<Locations> _locationlists = [ // 你的地点数据 ]; List<Locations> get locationList => _locationlists; // 根据分区ID过滤地点 List<Locations> getFilteredLocations(String? divisionId) { if (divisionId == null) return _locationlists; return _locationlists.where((loc) => loc.id == divisionId).toList(); } }
2. 创建筛选状态管理类
class FilterState with ChangeNotifier { String? _selectedDivisionId; String? get selectedDivisionId => _selectedDivisionId; void updateSelectedDivision(String? id) { _selectedDivisionId = id; notifyListeners(); } }
3. 在 main.dart 注册 Provider
void main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => DivisionLists()), ChangeNotifierProvider(create: (_) => LocationLists()), ChangeNotifierProvider(create: (_) => FilterState()), ], child: const MyApp(), ), ); }
4. 实现筛选页面
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class LocationFilterScreen extends StatelessWidget { const LocationFilterScreen({super.key}); @override Widget build(BuildContext context) { final divisionData = Provider.of<DivisionLists>(context); final locationData = Provider.of<LocationLists>(context); final filterState = Provider.of<FilterState>(context); final filteredLocations = locationData.getFilteredLocations(filterState.selectedDivisionId); return Scaffold( appBar: AppBar(title: const Text('分区地点筛选')), body: Column( children: [ // 横向分区选择栏 SizedBox( height: 80, child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 8), itemCount: divisionData.divisionList.length, itemBuilder: (ctx, index) { final division = divisionData.divisionList[index]; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: GestureDetector( onTap: () => filterState.updateSelectedDivision(division.id), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: filterState.selectedDivisionId == division.id ? Colors.blue : Colors.grey.shade200, borderRadius: BorderRadius.circular(20), ), child: Text( division.divisionName!, style: TextStyle( color: filterState.selectedDivisionId == division.id ? Colors.white : Colors.black, fontWeight: FontWeight.bold, ), ), ), ), ); }, ), ), // 地点展示 GridView Expanded( child: GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 16, mainAxisSpacing: 16, childAspectRatio: 0.8, ), itemCount: filteredLocations.length, itemBuilder: (ctx, index) { final location = filteredLocations[index]; return Card( elevation: 4, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Image.network( location.dImageUrl!, fit: BoxFit.cover, width: double.infinity, ), ), Padding( padding: const EdgeInsets.all(8), child: Text( location.locationName!, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Text( location.locationDescription!, style: const TextStyle(fontSize: 12, color: Colors.grey), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), ], ), ); }, ), ), ], ), ); } }
内容的提问来源于stack exchange,提问作者NoobInCode
相关产品推荐
相关产品推荐

