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

Flutter实现点击搜索图标后切换显示清除/搜索图标的需求

实现点击触发的搜索/清除切换功能

关键改动说明

  1. 新增TextEditingController管理输入框文本,替代原onChange实时更新逻辑,确保仅点击操作触发状态变化
  2. 新增showClearIcon布尔变量,控制搜索/清除图标的切换显示
  3. 重构搜索与清除逻辑,严格通过点击事件触发

修改后的完整代码片段

class _OverViewState extends State<OverView> {
  OverViewController overViewController = OverViewController();
  List<House> houses = []; 
  String searchText = '';
  bool isLoading = true;
  // 新增输入控制器,管理文本框内容
  final TextEditingController _searchController = TextEditingController();
  // 控制显示搜索图标还是清除图标
  bool showClearIcon = false;

  @override
  void initState() {
    super.initState();
    getHouses();
    checkLocationPermission();
  }

  @override
  void dispose() {
    // 销毁控制器,避免内存泄漏
    _searchController.dispose();
    super.dispose();
  }

  void getHouses() async {
    await overViewController.fetchSortedHouses();
    houses = overViewController.filterHouses(searchText);
    isLoading = false;
    setState(() {});
  }

  // 执行搜索逻辑:获取输入框文本、过滤数据、切换显示清除图标
  void performSearch() {
    setState(() {
      searchText = _searchController.text.trim();
      houses = overViewController.filterHouses(searchText);
      // 只有输入非空时才显示清除图标
      showClearIcon = searchText.isNotEmpty;
    });
  }

  // 执行清除逻辑:清空文本、重置数据、切换回搜索图标
  void clearSearch() {
    setState(() {
      _searchController.clear();
      searchText = '';
      // 重新获取全量数据(或直接过滤空文本)
      houses = overViewController.filterHouses(searchText);
      showClearIcon = false;
    });
  }

  void checkLocationPermission() async {
    final bool locationAccessGranted =
        await overViewController.authorizeLocationAccess();

    if (locationAccessGranted) {
      await overViewController.getCurrentLocation();
      getHouses();
    }

    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: const Color(0xFFEBEBEB),
        child: Column(
          children: [
            Container(
              child: Padding(
                padding: const EdgeInsets.all(10.0),
                child: Container(
                  decoration: BoxDecoration(
                    color: const Color(0x33000000),
                    borderRadius: BorderRadius.circular(10.0),
                  ),
                  child: Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 10.0),
                    child: Row(
                      children: [
                        Expanded(
                          child: TextField(
                            controller: _searchController, // 绑定控制器
                            // 移除原onChange,避免实时触发
                            decoration: const InputDecoration(
                              hintText: 'Search for something',
                              hintStyle: TextStyle(
                                color: Color(0x66000000),
                              ),
                              border: InputBorder.none,
                            ),
                          ),
                        ),
                        // 根据showClearIcon切换图标
                        GestureDetector(
                          onTap: showClearIcon ? clearSearch : performSearch,
                          child: showClearIcon
                              ? SvgPicture.asset(
                                  'assets/icons/ic_clear.svg', // 替换为你的清除图标路径
                                  width: 25,
                                  height: 25,
                                  color: const Color(0x66000000),
                                )
                              : SvgPicture.asset(
                                  'assets/icons/ic_search.svg',
                                  width: 25,
                                  height: 25,
                                  color: const Color(0x66000000),
                                ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ),
            // 下方列表展示
            isLoading
                ? const Center(child: CircularProgressIndicator())
                : Expanded(
                    child: ListView.builder(
                      itemCount: houses.length,
                      itemBuilder: (context, index) {
                        // 替换为你的列表项UI实现
                        return ListTile(title: Text(houses[index].name));
                      },
                    ),
                  )
          ],
        ),
      ),
    );
  }
}

核心逻辑说明

  • 搜索触发:点击搜索图标时,读取输入框当前文本,执行数据过滤并切换到清除图标(仅当输入非空时)
  • 清除触发:点击清除图标时,清空输入框文本,重置数据为全量列表,切换回搜索图标
  • 输入管理:通过TextEditingController统一控制文本内容,避免onChange实时更新带来的不必要状态刷新

内容的提问来源于stack exchange,提问作者ThatGuy1234

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 22:32:04