Flutter:点击搜索栏后缀图标实现不同页面特定内容展示
解决方案
核心思路
给FilterSearchBar新增清除按钮点击的回调方法,让父组件(HomeScreen/PlayerScreen)根据自身需求处理清除后的逻辑,而非仅由SearchBar内部清空输入框。
步骤1:修改FilterSearchBar,添加清除回调
在组件参数中新增onClearPressed回调,点击清除图标时触发该回调:
class FilterSearchBar extends StatefulWidget { final String filterType; final TextEditingController searchController; final TextInputType keyboard; final ValueChanged<String>? onChanged; // 新增清除按钮回调 final VoidCallback? onClearPressed; const FilterSearchBar({ Key? key, required this.filterType, required this.searchController, required this.keyboard, this.onChanged, this.onClearPressed, }) : super(key: key); @override State<FilterSearchBar> createState() => _FilterSearchBarState(); } class _FilterSearchBarState extends State<FilterSearchBar> { bool isClearClicked = false; @override void initState() { widget.searchController.addListener(() { setState(() { isClearClicked = widget.searchController.text.isNotEmpty; }); }); super.initState(); } @override void dispose() { widget.searchController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16.0), child: TextFormField( keyboardType: widget.keyboard, controller: widget.searchController, onChanged: widget.onChanged, decoration: InputDecoration( border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(90)), borderSide: BorderSide(color: Colors.grey), ), prefixIcon: Icon(Icons.search, color: Colors.grey), hintText: widget.filterType, hintStyle: TextStyle( color: Colors.grey, fontSize: 16, fontWeight: FontWeight.bold, ), suffixIcon: isClearClicked ? IconButton( onPressed: () { clearSearchBar(); // 触发父组件的清除逻辑 widget.onClearPressed?.call(); }, icon: Icon(Icons.clear, color: Colors.grey), ) : null, filled: true, fillColor: Colors.white, ), ), ); } void clearSearchBar() { widget.searchController.clear(); } }
步骤2:修改HomeScreen,处理清除事件
传入onClearPressed回调,点击清除按钮时重置球队列表为完整数据:
class _HomeScreenState extends State<HomeScreen> { TextEditingController searchController = TextEditingController(); List<Team> allTeams = Team.getNFCTeam(); List<Team> suggestions = Team.getNFCTeam(); List<Team> teams = Team.getNFCTeam(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("NFC")), body: Column( children: [ FilterSearchBar( filterType: "Search team", searchController: searchController, keyboard: TextInputType.text, onChanged: searchTeam, // 清除后显示完整球队列表 onClearPressed: () { setState(() => teams = allTeams); }, ), showAllTeams(), ], ), ); } // 其余代码保持不变 Widget showAllTeams() => Expanded( child: ListView.builder( itemCount: teams.length, itemBuilder: (context, index) { final team = teams[index]; return Column( children: [ ListTile( title: Padding( padding: EdgeInsets.all(10), child: Row(children: [Text(team.name, style: TextStyle(color: Colors.black))]), ), onTap: () => Navigator.push( context, MaterialPageRoute(builder: (context) => PlayerScreen(team: team.name)), ), ), Divider(height: 1, color: Colors.grey), ], ); }, ), ); void searchTeam(String query) { suggestions = allTeams.where((team) => team.name.toLowerCase().startsWith(query.toLowerCase())).toList(); setState(() => teams = suggestions.isEmpty ? allTeams : suggestions); } }
步骤3:修改PlayerScreen,处理清除事件
传入onClearPressed回调,清除后重置玩家列表并回到默认文本状态:
class _PlayerScreenState extends State<PlayerScreen> { TextEditingController searchController = TextEditingController(); // 修正拼写错误:allPayers -> allPlayers List<Player> allPlayers = Player.getPlayer(); List<Player> suggestions = Player.getPlayer(); List<Player> players = Player.getPlayer(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(widget.team)), body: Container( color: Colors.grey, child: Column( children: [ FilterSearchBar( filterType: "Search player", searchController: searchController, keyboard: TextInputType.text, onChanged: searchPlayer, // 清除后回到默认文本 onClearPressed: () { setState(() => players = allPlayers); }, ), searchController.text.isNotEmpty ? showAllPlayers() : Center( child: Text( "No player found", style: TextStyle(color: Colors.black, fontSize: 18, fontWeight: FontWeight.bold), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), ], ), ) ); } // 其余代码保持不变 Widget showAllPlayers() => Expanded( child: ListView.builder( itemCount: players.length, itemBuilder: (context, index) { final player = players[index]; return Column( children: [ ListTile( title: Padding( padding: EdgeInsets.all(10), child: Row( children: [ Text(player.number, style: TextStyle(color: Colors.black)), SizedBox(width: 5), Text(player.position, style: TextStyle(color: Colors.black)), SizedBox(width: 5), Text(player.name, style: TextStyle(color: Colors.black)), ], ), ), ), Divider(height: 1, color: Colors.grey), ], ); }, ), ); void searchPlayer(String query) { suggestions = allPlayers.where((player) => player.name.toLowerCase().startsWith(query.toLowerCase())).toList(); setState(() => players = suggestions.isEmpty ? allPlayers : suggestions); } }
额外修正:Player类字段补全类型
补充number和position字段的类型声明,避免隐式类型警告:
class Player { final int id; final String name; final String number; final String position; Player({required this.id, required this.name, required this.number, required this.position}); static List<Player> getPlayer() => [ Player(id: 0, name: "Brock Purdy", number: "#13", position: "QB"), Player(id: 1, name: "Christian McCaffrey", number: "#23", position: "RB"), Player(id: 2, name: "George Kittle", number: "#85", position: "TE"), Player(id: 3, name: "Deebo Samuel", number: "#19", position: "WR"), Player(id: 4, name: "Nick Bosa", number: "#97", position: "DL"), Player(id: 5, name: "Fred Warner", number: "#54", position: "LB"), ]; }
内容的提问来源于stack exchange,提问作者Seth
相关产品推荐
相关产品推荐

