Flutter listview 在其内容滚动屏幕的末尾

Posted

技术标签:

【中文标题】Flutter listview 在其内容滚动屏幕的末尾【英文标题】:Flutter listview at the end of its content scrolls screen 【发布时间】:2021-02-06 12:45:04 【问题描述】:

我想知道是否有可能在SingleChildScrollView 中有一个具有固定高度的垂直ListView,并且当垂直ListView 中没有更多内容时,滚动将应用于整个屏幕(@987654324 @)

类似这样的:

SingleChildScrollView(
      child: Column(
          children: [
            // some widgets ....
            
            Container(
              constraints: BoxConstraints(maxHeight: 200),
              child: ListView.builder(
                // other settings
                scrollDirection: Axis.vertical,
              ),
            )
          ]
      )
  )

【问题讨论】:

【参考方案1】:

我使用的是 SingleChildScrollView 的 Listview,但它是一样的:

import 'dart:async';

import 'package:flutter/material.dart';

void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(title: 'Flutter Demo', home: MyListView());
  


class MyListView extends StatelessWidget 
  ScrollController _mainScrollController = ScrollController();
  double listHeight = 370;
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: const Text('AppBar'),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        child: ListView(
            controller: _mainScrollController,
            children: <Widget>[

              Container(height: listHeight,child: RapportList(parentScrollController: _mainScrollController)),
              OtherElement(text: "Other element 1 which will be scrolled",),
              OtherElement(text: "Other element 2 which will be scrolled",),
              OtherElement(text: "Other element 3 which will be scrolled",),
              OtherElement(text: "Other element 4 which will be scrolled",),
              OtherElement(text: "Other element 5 which will be scrolled",),
            ],
        ),
      ),
    );
  


class RapportList extends StatefulWidget 
  final ScrollController parentScrollController;
  RapportList(@required this.parentScrollController);
  @override
  _RapportListState createState() => _RapportListState();


class _RapportListState extends State<RapportList> 
  ScrollPhysics physics = ScrollPhysics();
  // NeverScrollableScrollPhysics()
  ScrollController _listViewScrollController;


  void listViewScrollListener()
     print("smth");
    if(_listViewScrollController.offset >= _listViewScrollController.position.maxScrollExtent &&
        !_listViewScrollController.position.outOfRange)
      if(widget.parentScrollController.offset==0)
        widget.parentScrollController.animateTo(50,duration: Duration(milliseconds: 200),curve: Curves.linear);
      
      setState(()
        physics = NeverScrollableScrollPhysics();
      );
      print("bottom");
    
  

  void mainScrollListener()
    if(widget.parentScrollController.offset <= widget.parentScrollController.position.minScrollExtent &&
        !widget.parentScrollController.position.outOfRange)
      setState(()
        if(physics is NeverScrollableScrollPhysics)
          physics = ScrollPhysics();
          _listViewScrollController.animateTo(_listViewScrollController.position.maxScrollExtent-50,duration: Duration(milliseconds: 200),curve: Curves.linear);
        
      );
      print("top");
    
  

  @override
  void setState(fn) 
    super.setState(fn);
  
  @override
  void initState() 
    _listViewScrollController = ScrollController();
    _listViewScrollController.addListener(listViewScrollListener);

    // TODO: implement initState
    super.initState();
  
  @override
  Widget build(BuildContext context) 

    widget.parentScrollController.addListener(mainScrollListener);
    return ListView.builder(
      controller: _listViewScrollController,
      physics: physics,
      shrinkWrap: true,
      itemCount: 50,
      itemBuilder: (context, index) 
        return ListTile(
          title: GestureDetector(
            child: Row(
              children: <Widget>[
                Container(child: Text("text $index")),
              ],
            ),
          ),
        );
      ,
    );
  



class OtherElement extends StatelessWidget 
  final String text;
  OtherElement(this.text);
  @override
  Widget build(BuildContext context) 
    return Container(
      height: 100,
      child: Center(child: Padding(
        padding: const EdgeInsets.symmetric(horizontal:40.0),
        child: Text(this.text,style:TextStyle(fontSize: 30)),
      )),
    );
  

githubgist.

演示 gif:

【讨论】:

很好的例子。它适用于从上到下的滚动,您能否说明从下到上滚动需要做什么(我的意思是从上到下和从下到上)?仅供参考,我是新手,无法继续保持这种行为。如果我能在这方面得到帮助,那就太好了。【参考方案2】:

我想你可以尝试使用Nested ScrollView Widget。

此小部件可让您完成所需的工作。

【讨论】:

【参考方案3】:

我认为您更新的代码有错误。因为如果你在 SingleChildScrollView 中有一个 Scrollable ListView,你就不能滚动它。让它成为你必须将它添加到你的 listView:

            physics: const NeverScrollableScrollPhysics(),

现在它应该可以工作了。在大多数情况下,您也可以尝试添加列而不是列表视图。

【讨论】:

以上是关于Flutter listview 在其内容滚动屏幕的末尾的主要内容,如果未能解决你的问题,请参考以下文章

Flutter ListView中的TextField上下滑动内容丢失

25.Flutter的ListView监听滚动事件之ScrollController

Flutter:ListView在开始时有间隙

Flutter ListView没有滚动到最后一个元素

Flutter - 如何使列屏幕可滚动

如何在 Flutter 中让 ListView 中的项目覆盖整个屏幕