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

Flutter实现搜索组件与ListView联动滚动,使用SingleChildScrollView报错求助

解决搜索框与ListView联动滚动的问题

你的需求是让搜索组件和列表结果一起滚动,原代码用Column+Expanded+ListView的结构会导致搜索框固定在顶部,无法随列表滚动。以下是可行的解决方案及优化后的完整代码:

核心思路

将搜索框和列表内容纳入同一个滚动组件,同时优化搜索逻辑避免无效空节点占用性能。这里推荐使用CustomScrollView,它能灵活组合不同类型的滚动组件。

完整修改代码

import 'package:coronavirus_app/Services/states_services.dart';
import 'package:coronavirus_app/resources/sizeconfig.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shimmer/shimmer.dart';

import '../Modal/world_countries_modal.dart';
import '../resources/colormanager.dart';
import '../resources/routesmanager.dart';

class CountriesListScreen extends ConsumerStatefulWidget {
  const CountriesListScreen({Key? key}) : super(key: key);

  @override
  ConsumerState<CountriesListScreen> createState() => _CountriesListScreenState();
}

class _CountriesListScreenState extends ConsumerState<CountriesListScreen> {
  final TextEditingController searchcontroller = TextEditingController();
  
  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);
    final countrydata = ref.watch(countrydataProvider);
    
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Theme.of(context).scaffoldBackgroundColor,
      ),
      body: countrydata.when(
        error: (err, stack) => Text('Error: ${err.toString()}'),
        loading: () => Shimmer.fromColors(
          baseColor: ColorManager.grey,
          highlightColor: ColorManager.lightGrey,
          child: ListView.builder(
            itemCount: 5,
            itemBuilder: ((context, index) {
              return const ListTile(
                title: SizedBox(height: 20, width: 89, child: ColoredBox(color: Colors.white)),
                leading: SizedBox(height: 100, width: 50, child: ColoredBox(color: Colors.white)),
                subtitle: SizedBox(height: 20, width: 89, child: ColoredBox(color: Colors.white)),
              );
            }),
          ),
        ),
        data: ((data) {
          List<WorldCountriesModal> countrieslist = data.map((e) => e).toList();
          // 提前过滤搜索结果,避免空容器占位
          List<WorldCountriesModal> filteredCountries = countrieslist.where((country) {
            if (searchcontroller.text.isEmpty) return true;
            return country.country!.toLowerCase().contains(searchcontroller.text.toLowerCase());
          }).toList();

          return CustomScrollView(
            slivers: [
              // 搜索框作为滚动头部
              SliverToBoxAdapter(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: SizedBox(
                    height: getProportionateScreenHeight(50),
                    width: double.infinity,
                    child: TextFormField(
                      controller: searchcontroller,
                      onChanged: (value) => setState(() {}),
                      decoration: InputDecoration(
                        contentPadding: const EdgeInsets.symmetric(vertical: 10),
                        hintText: 'Search with country name',
                        prefixIcon: const Icon(Icons.search),
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(50),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
              // 列表内容
              SliverList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) {
                    var data = filteredCountries[index];
                    return InkWell(
                      onTap: () {
                        FocusScope.of(context).unfocus();
                        Navigator.pushNamed(context, Routes.detail, arguments: data);
                      },
                      child: ListTile(
                        title: Text(data.country.toString()),
                        leading: SizedBox(
                          height: getProportionateScreenHeight(100),
                          width: getProportionateScreenWidth(50),
                          child: Image.network(data.countryInfo!.flag.toString()),
                        ),
                        subtitle: Text(data.cases.toString()),
                      ),
                    );
                  },
                  childCount: filteredCountries.length,
                ),
              ),
            ],
          );
        }),
      ),
    );
  }
}

关键优化点

  1. 联动滚动实现:通过CustomScrollView将搜索框(SliverToBoxAdapter)和列表(SliverList)绑定为同一滚动体,实现滚动同步。
  2. 搜索逻辑优化:用where提前过滤列表,替代原代码中返回空容器的写法,减少无效渲染节点,提升性能。
  3. 代码简化:将嵌套的Image(image: Image.network(...).image)简化为直接使用Image.network(...),减少冗余代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:35:47