You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:01:05