如何用Stream Builder结合按钮实现Firebase数据排序与筛选
Flutter实现Firebase房源价格与位置筛选功能
修复现有问题并实现完整筛选逻辑
以下是修改后的完整代码,解决了原代码的数据流返回、UI刷新问题,并添加了价格范围和位置筛选的完整功能:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'package:realstate/home%20page/addingpage.dart'; import '../account page/account page.dart'; class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @override State<Home> createState() => _HomeState(); } class _HomeState extends State<Home> { // 筛选状态变量 double? _minPrice; double? _maxPrice; String? _selectedLocation; bool _isFilterActive = false; // Firestore集合引用 final CollectionReference _database = FirebaseFirestore.instance.collection('Detabase'); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( backgroundColor: Colors.white, appBar: AppBar( centerTitle: true, title: const Text( "Home", style: TextStyle( color: Colors.black, fontFamily: 'Montserrat', fontWeight: FontWeight.bold, fontSize: 32, ), ), leading: IconButton( icon: const Icon(Icons.add_business_sharp, color: Colors.black, size: 26), onPressed: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => const Addingpage())), ), backgroundColor: Colors.white, actions: [ IconButton( onPressed: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => const AccountPage())), icon: const Icon(Icons.account_circle, color: Colors.black), highlightColor: Colors.transparent, focusColor: Colors.transparent, hoverColor: Colors.transparent, splashColor: Colors.transparent, ) ], ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 筛选栏 _buildFilterBar(), const SizedBox(height: 20), // 房源列表 _buildPropertyList(), ], ), ), ), ); } // 构建筛选栏UI Widget _buildFilterBar() { return Column( children: [ Row( children: [ Expanded( child: TextField( keyboardType: TextInputType.number, decoration: const InputDecoration(labelText: "最低价格"), onChanged: (value) => setState(() => _minPrice = double.tryParse(value)), ), ), const SizedBox(width: 10), Expanded( child: TextField( keyboardType: TextInputType.number, decoration: const InputDecoration(labelText: "最高价格"), onChanged: (value) => setState(() => _maxPrice = double.tryParse(value)), ), ), ], ), const SizedBox(height: 10), TextField( decoration: const InputDecoration(labelText: "位置"), onChanged: (value) => setState(() => _selectedLocation = value.trim()), ), const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: () { setState(() { _minPrice = null; _maxPrice = null; _selectedLocation = null; _isFilterActive = false; }); }, child: const Text("重置筛选"), ), ElevatedButton( onPressed: () => setState(() => _isFilterActive = true), child: const Text("应用筛选"), ), ], ), ], ); } // 构建房源列表 Widget _buildPropertyList() { return SizedBox( height: MediaQuery.of(context).size.height - 300, // 固定高度避免滚动冲突 child: StreamBuilder<QuerySnapshot>( stream: _getFilteredStream(), builder: (context, snapshot) { if (snapshot.hasError) return const Text('加载出错'); if (snapshot.connectionState == ConnectionState.waiting) return const Text("加载中..."); return ListView.builder( shrinkWrap: true, physics: const AlwaysScrollableScrollPhysics(), itemCount: snapshot.data!.docs.length, itemBuilder: (context, index) { final data = snapshot.data!.docs[index].data() as Map<String, dynamic>; return ListTile( title: Text("位置: ${data['location']}"), subtitle: Text("租金: ${data['expectedrent']} | 详情: ${data['detals']}"), ); }, ); }, ), ); } // 获取筛选后的Firestore数据流 Stream<QuerySnapshot> _getFilteredStream() { Query query = _database.orderBy('expectedrent', descending: false); // 添加价格范围筛选 if (_minPrice != null) query = query.where('expectedrent', isGreaterThanOrEqualTo: _minPrice); if (_maxPrice != null) query = query.where('expectedrent', isLessThanOrEqualTo: _maxPrice); // 添加位置筛选(精确匹配,若需模糊搜索需提前处理数据) if (_selectedLocation != null && _selectedLocation!.isNotEmpty) { query = query.where('location', isEqualTo: _selectedLocation); } return query.snapshots(); } }
关键修改说明
- 筛选状态管理:新增
_minPrice、_maxPrice、_selectedLocation变量记录筛选条件,_isFilterActive标记筛选状态 - 动态查询构建:
_getFilteredStream()根据当前筛选条件动态组合Firestore的where子句,支持多条件叠加 - 布局优化:给嵌套的ListView设置固定高度,添加
shrinkWrap: true避免布局溢出,同时保留滚动功能 - 交互逻辑:筛选栏输入实时更新状态,点击"应用筛选"触发数据流刷新,"重置筛选"清空所有条件
注意事项
- 若需要位置模糊搜索,需提前在Firestore文档中存储位置关键词数组,使用
arrayContains或Firebase全文检索服务 - 确保Firestore已为
expectedrent和location字段创建复合索引,避免多条件查询报错
内容的提问来源于stack exchange,提问作者ISLAM IS LIFE
相关产品推荐
相关产品推荐

