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

Posted

技术标签:

【中文标题】Flutter ListView没有滚动到最后一个元素【英文标题】:Flutter ListView not scrolling to last element 【发布时间】:2021-06-13 21:40:53 【问题描述】:

PageView 中的 listview 有问题,当我滚动到底部时,缺少两行。

我可以通过更新 ListView 所在的 Container 的高度来纠正这个问题,但屏幕渲染并未针对所有屏幕尺寸进行优化。

Screenshot of the match results list

我们可以成功滚动 8 或 150 个匹配项,当我们完成滚动操作时,我们总是会错过最后 2 个匹配项。

这是管理综合浏览量的代码:

class Results extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        fontFamily: "Josefin",
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomeResults(),
    );
  


class HomeResults extends StatefulWidget 
  @override
  _HomeResultsState createState() => _HomeResultsState();


class _HomeResultsState extends State<HomeResults> 
  PageController _controller = PageController(
    initialPage: 0,
  );

  int currentPage = 0;
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: Column(
          children: [
            Container(
              height: 45,
              child: ListView.builder(
                shrinkWrap: true,
                itemBuilder: (ctx, i) 
                  return Container(
                    child: FlatButton(
                      onPressed: () 
                        _controller.animateToPage(i,
                            duration: Duration(milliseconds: 300),
                            curve: Curves.easeIn);
                      ,
                      child: Text(
                        resultscateg[i],
                        style: TextStyle(
                          color: currentPage == i
                              ? Colors.black
                              : Colors.black.withOpacity(0.4),
                        ),
                      ),
                    ),
                  );
                ,
                itemCount: resultscateg.length,
                scrollDirection: Axis.horizontal,
              ),
            ),
            Expanded(
              child: PageView(
                controller: _controller,
                onPageChanged: (value) 
                  setState(() 
                    currentPage = value;
                  );
                ,
                children: [
                  FutureBuilder<List<Match>>(
                    future: MatchRepository().getResults(1),
                    builder: (context, snapshot) 
                      if (snapshot.hasError) print(snapshot.error);

                      return snapshot.hasData
                          ? ResultsWidget(resultsList: snapshot.data)
                          : Center(
                              child: CircularProgressIndicator(
                              valueColor:
                                  new AlwaysStoppedAnimation<Color>(Colors.red),
                            ));
                    ,
                  ),
                  FutureBuilder<List<Match>>(
                    future: MatchRepository().getResults(2),
                    builder: (context, snapshot) 
                      if (snapshot.hasError) print(snapshot.error);

                      return snapshot.hasData
                          ? ResultsWidget(resultsList: snapshot.data)
                          : Center(
                              child: CircularProgressIndicator(
                              valueColor:
                                  new AlwaysStoppedAnimation<Color>(Colors.red),
                            ));
                    ,
                  ),
                ],
              ),
            )
          ],
        ),
      ),
    );
  

这是结果小部件的代码:

class ResultsWidget extends StatelessWidget 
  final List<Match> resultsList;

  ResultsWidget(Key key, this.resultsList) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return Stack(
      children: [
        Container(
          width: MediaQuery.of(context).size.width,
          child: ListView(
            children: [
              //last results
              Container(
                // Pour gérer le padding entre les scores
                height: MediaQuery.of(context).size.height,
                child: resultsList.isEmpty
                    ? Center(child: Text('Aucun résultat actuellement.'))
                    : ListView.builder(
                        itemCount: resultsList.length,
                        scrollDirection: Axis.vertical,
                        shrinkWrap: true,
                        itemBuilder: (ctx, i) => Padding(
                          padding: EdgeInsets.all(10),
                          child: Material(
                            color: Colors.white,
                            elevation: 5,
                            borderRadius: BorderRadius.circular(15),
                            clipBehavior: Clip.hardEdge,
                            child: Container(
                              width: MediaQuery.of(context).size.width,
                              height: 110,
                              padding: EdgeInsets.all(5),
                              child: Column(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceAround,
                                children: <Widget>[
                                  Container(
                                    height: 30,
                                    decoration: BoxDecoration(
                                      image: DecorationImage(
                                          image: AssetImage(
                                              "assets/images/bgheader.png"),
                                          fit: BoxFit.cover),
                                      // Gère l'arrondi des bords de chaque score
                                      borderRadius: BorderRadius.circular(10),
                                    ),
                                    child: Row(
                                      children: [
                                        Expanded(
                                          child: Padding(
                                            padding: const EdgeInsets.all(6.0),
                                            child: Text(
                                                resultsList[i]
                                                        .etapecompetition
                                                        .libelle ??
                                                    "",
                                                maxLines: 1,
                                                textAlign: TextAlign.left,
                                                overflow: TextOverflow.fade,
                                                style: TextStyle(
                                                    fontSize: 14,
                                                    fontWeight: FontWeight.bold,
                                                    color: Colors.yellow)),
                                          ),
                                        ),
                                        Expanded(
                                          child: Padding(
                                            padding: const EdgeInsets.all(6.0),
                                            child: Text(
                                                resultsList[i].roundLibelle ??
                                                    "",
                                                maxLines: 1,
                                                textAlign: TextAlign.right,
                                                overflow: TextOverflow.fade,
                                                style: TextStyle(
                                                    fontSize: 14,
                                                    color: Colors.white)),
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                  Row(
                                    mainAxisAlignment:
                                        MainAxisAlignment.spaceEvenly,
                                    children: <Widget>[
                                      Container(
                                        height: 50,
                                        width: 50,
                                        decoration: BoxDecoration(
                                          shape: BoxShape.circle,
                                        ),
                                        child: ClipRRect(
                                          borderRadius:
                                              BorderRadius.circular(10),
                                          child: Image.network(
                                            'https://ruiznicolas.ovh/img/logos/$resultsList[i].equipe1.logo ?? "asa.png"',
                                            height: 95,
                                            fit: BoxFit.fitHeight,
                                          ),
                                        ),
                                      ),
                                      SizedBox(
                                        //Marge du logo de gauche par rapport au reste
                                        width: 5,
                                      ),
                                      Expanded(
                                        //Colonne de l'equipe 1
                                        child: Column(
                                          //Gère le centrage du texte
                                          mainAxisAlignment:
                                              MainAxisAlignment.spaceEvenly,
                                          crossAxisAlignment:
                                              CrossAxisAlignment.start,
                                          children: [
                                            Text(
                                              '',
                                              style: TextStyle(
                                                color: Colors.white,
                                              ),
                                            ),
                                            Text(
                                              resultsList[i].equipe1.nom ?? "",
                                              maxLines: 2,
                                              overflow: TextOverflow.fade,
                                              style: TextStyle(
                                                color: Colors.black,
                                                fontSize: 17,
                                                fontWeight: FontWeight.bold,
                                              ),
                                            ),
                                            Text(
                                              "",
                                              style: TextStyle(
                                                color: Colors.white
                                                    .withOpacity(0.7),
                                              ),
                                            )
                                          ],
                                        ),
                                      ),
                                      Expanded(
                                        //Colonne du score
                                        child: Column(
                                          //Gère le centrage du texte
                                          mainAxisAlignment:
                                              MainAxisAlignment.spaceEvenly,
                                          crossAxisAlignment:
                                              CrossAxisAlignment.center,
                                          children: [
                                            Text(
                                              '',
                                              style: TextStyle(
                                                color: Colors.white,
                                              ),
                                            ),
                                            Text(
                                              '$resultsList[i].score1 ?? "" - $resultsList[i].score2 ?? ""',
                                              maxLines: 2,
                                              textAlign: TextAlign.center,
                                              overflow: TextOverflow.fade,
                                              style: TextStyle(
                                                color: Colors.grey,
                                                fontSize: 17,
                                                fontWeight: FontWeight.bold,
                                              ),
                                            ),
                                            resultsList[i].tabs1 != null
                                                ? Text(
                                                    "(TAB : $resultsList[i].tabs1 ?? "" - $resultsList[i].tabs2 ?? "")",
                                                    style: TextStyle(
                                                      color: Colors.grey
                                                          .withOpacity(0.7),
                                                      fontSize: 12,
                                                    ),
                                                  )
                                                : Text(
                                                    "",
                                                    style: TextStyle(
                                                      color: Colors.grey
                                                          .withOpacity(0.7),
                                                    ),
                                                  )
                                          ],
                                        ),
                                      ),
                                      Expanded(
                                        //Colonne de l'equipe 2
                                        child: Column(
                                          //Gère le centrage du texte
                                          mainAxisAlignment:
                                              MainAxisAlignment.spaceEvenly,
                                          crossAxisAlignment:
                                              CrossAxisAlignment.end,
                                          children: [
                                            Text(
                                              '',
                                              style: TextStyle(
                                                color: Colors.white,
                                              ),
                                            ),
                                            Text(
                                              resultsList[i].equipe2.nom ?? "",
                                              maxLines: 2,
                                              textAlign: TextAlign.center,
                                              overflow: TextOverflow.fade,
                                              style: TextStyle(
                                                color: Colors.black,
                                                fontSize: 17,
                                                fontWeight: FontWeight.bold,
                                              ),
                                            ),
                                            Text(
                                              "",
                                              style: TextStyle(
                                                color: Colors.white
                                                    .withOpacity(0.7),
                                              ),
                                            )
                                          ],
                                        ),
                                      ),
                                      Container(
                                        height: 50,
                                        width: 50,
                                        decoration: BoxDecoration(
                                          shape: BoxShape.circle,
                                        ),
                                        child: ClipRRect(
                                          borderRadius:
                                              BorderRadius.circular(10),
                                          child: Image.network(
                                            'https://ruiznicolas.ovh/img/logos/$resultsList[i].equipe2.logo ?? ""',
                                            height: 95,
                                            fit: BoxFit.fitHeight,
                                          ),
                                        ),
                                      ),
                                      SizedBox(
                                        //Marge du logo de gauche par rapport au reste
                                        width: 5,
                                      ),
                                    ],
                                  )
                                ],
                              ),
                            ),
                          ),
                        ),
                      ),
              ),
            ],
          ),
        )
      ],
    );
  

【问题讨论】:

【参考方案1】:

我认为ListView 中的嵌套ListView.builder 可能是问题所在。

在下面的示例中,我尝试复制您的小部件树,如果没有内部ListView.builder 上的physics: ClampingScrollPhysics(),我根本无法滚动结果列表。

import 'package:flutter/material.dart';

class ListViewScrollastPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text('ListView Scrollast'),
      ),
      body: ResultsWidget(),
    );
  


class ResultsData 
  List<int> results = List.generate(20, (index) => index + 1);


class ResultsWidget extends StatelessWidget 
  final List<int> results = List.generate(20, (index) => index + 1);

  @override
  Widget build(BuildContext context) 
    return Stack(
      children: [
        Container(
          child: ListView(
            children: [
              Container(
                child: ListView.builder(
                  itemCount: results.length,
                  shrinkWrap: true,
                  // ************************************************************
                  physics: ClampingScrollPhysics(), // ← can't scroll nested list without
                  // ************************************************************
                  itemBuilder: (context, index) 
                    return ListTile(
                      title: Text('Match $results[index]'),
                      subtitle: Text('Win Draw Loss'),
                    );
                  ,
                ),
              )
            ],
          ),
        )
      ],
    );
  

J'espère que ça t'aide ;)

【讨论】:

谢谢!我使用了您的代码,并用我的 Padding 小部件替换了您的 ListTile,它解决了我的问题

以上是关于Flutter ListView没有滚动到最后一个元素的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 应用程序中的 ListView 滚动上隐藏/关闭键盘

Flutter缓慢滚动到动态Listview的底部

Stream 内的 Flutter ListView.Builder 不更新

Flutter ListView 滚动索引滚动不足

带有滚动条的 Flutter Listview

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