在Flutter中滚动时调整ListView的大小

eh57zj3b  于 2023-01-27  发布在  Flutter
关注(0)|答案(2)|浏览(303)

我试图构建一个屏幕,其中两个垂直堆叠的ListView会因滚动而增大和缩小。

初始状态是两个列表分别占据屏幕顶部和底部的50%。当用户开始向下拖动顶部列表(以向上滚动)时,在正常滚动行为开始之前,最初将使列表扩展到占据屏幕的75%;当用户改变方向、向上拖动(以向下滚动)时,当他们到达列表底部时,将导致列表收缩回到仅占据屏幕的50%(初始状态)。
底部列表的工作原理类似,向上拖动会导致列表向上扩展,在正常滚动行为开始之前占据屏幕的75%;当用户改变方向、向下拖动(以向上滚动)时,当他们到达列表的顶部时,列表将收缩回到屏幕的50%。
我的问题是,实现这个功能的最佳小部件组合是什么?如何将滚动事件与调整ListView大小联系起来?
到目前为止,这是我得到的:

Column(
  children: [
    SizedBox(
      height: availableHeight / 2,
      child: ListView(...)
    ),
    Expanded(child: ListView(...)),
  ],
),

就类似的行为而言,CustomScrollView和SliverAppBar似乎具有我所追求的滚动行为中的一些元素,但如何将其转换为我上面描述的两个相邻列表视图对我来说并不明显。
如有任何建议,将不胜感激,谢谢!

yebdmbv4

yebdmbv41#

嗨检查这个,

Column(
    children: [
      Expanded ( 
      flex:7,
        child: Container(

          child: ListView.builder(
              itemCount:50,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                    leading: const Icon(Icons.list),
                    trailing: const Text(
                      "GFG",
                      style: TextStyle(color: Colors.green, fontSize: 15),
                    ),
                    title: Text("List item $index"));
              }),
        ),
      ),
      Expanded ( 
      flex:3,
        child: Container(
          child: ListView.builder(
              itemCount:50,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                    leading: const Icon(Icons.list),
                    trailing: const Text(
                      "GFG",
                      style: TextStyle(color: Colors.green, fontSize: 15),
                    ),
                    title: Text("aaaaaaaaa $index"));
              }),
        ),
      ),
    ],
  ),
mm9b1k5b

mm9b1k5b2#

首先,为两个列表视图初始化两个滚动控制器。然后使用WidgetsBinding.instance.addPostFrameCallback注册一个帧后回调,以确保滚动控制器已链接到滚动视图。接下来,在该回调中设置滚动侦听器。
要收听滚动更新,您可以使用scrollController.addListener。因为我们不需要知道用户现在是否正在滚动,所以我注解掉了这一部分,但如果您需要,我会把它留在那里。
要监听开始和停止滚动,你可以使用scrollController.position.isScrollingNotifier.addListener。稍后,我们可以使用两个布尔值来改变滚动列表视图的高度。你可以检查我的代码实现如下:

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final ScrollController _scrollCtrl1 = ScrollController();
  final ScrollController _scrollCtrl2 = ScrollController();
  bool hasScrollStarted1 = false;
  bool hasScrollStarted2 = false;

  @override
  void initState() {

    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      // _scrollCtrl1.addListener(() {
      //   print('scrolling');
      // });
      _scrollCtrl1.position.isScrollingNotifier.addListener(() {
        if(!_scrollCtrl1.position.isScrollingNotifier.value) {
          setState(() {
            hasScrollStarted1 = false;
          });
        } else {
          print('scroll is started');
          setState(() {
            hasScrollStarted1 = true;
          });
        }
      });

      _scrollCtrl2.position.isScrollingNotifier.addListener(() {
        if(!_scrollCtrl2.position.isScrollingNotifier.value) {
          setState(() {
            hasScrollStarted2 = false;
          });
        } else {
          print('scroll is started');
          setState(() {
            hasScrollStarted2 = true;
          });
        }
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          Expanded (
            flex: hasScrollStarted1 ? 7 : hasScrollStarted2 ? 3 : 1,
            child: ListView.builder(
                itemCount:50,
                controller: _scrollCtrl1,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                      leading: const Icon(Icons.list),
                      trailing: const Text(
                        "GFG",
                        style: TextStyle(color: Colors.green, fontSize: 15),
                      ),
                      title: Text("List item $index"));
                }),
          ),
          const Divider(thickness: 5,),
          Expanded (
            flex: hasScrollStarted2 ? 7 : hasScrollStarted1 ? 3 : 1,
            child: ListView.builder(
                itemCount:50,
                controller: _scrollCtrl2,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                      leading: const Icon(Icons.list),
                      trailing: const Text(
                        "GFG",
                        style: TextStyle(color: Colors.green, fontSize: 15),
                      ),
                      title: Text("aaaaaaaaa $index"));
                }),
          ),
        ],
      ),
    );
  }
}

快乐编码!!

相关问题