【问题标题】:Flutter listview within listview not scrolling列表视图中的颤振列表视图不滚动
【发布时间】:2020-06-19 20:49:44
【问题描述】:

作为我的第一个 Flutter 项目,我正在为报纸构建一个应用程序。有许多新闻类别。对于这些类别,我创建了一个通用Widget,在主屏幕中,Widget 将在Listview 中的多个类别中多次显示,这些类别Widgets 在我带来时也有Listview来自这些类别的多个新闻。具有此泛型WidgetWidget 类是Newsfeed.dart,将在下面给出。

这个泛型Widget 是从另一个WidgetWidgetFactory.dart 调用的,该类实际上调用API 并通过使用上述泛型Widget 来构建主屏幕。此类使用Listview.builder,它位于FutureBuilder 内部。

问题是,当我在屏幕上打开应用程序时,会出现新闻但我无法滚动,它保持不变。我检查了 API 是否真的带来了新闻,在控制台中我打印了 API 响应,所有的新闻都被获取了,但我仍然无法滚动。

流程是ma​​in.dart -> WidgetFactory() -> Newsfeed()

WidgetFactory()

class WidgetFactory extends StatefulWidget {
  @override
  _WidgetFactoryState createState() => _WidgetFactoryState();
}

class _WidgetFactoryState extends State<WidgetFactory> {
  List homeScreenCategories = [4, 14, 13, 23, 8015, 22];

  Future<List> newsPostList;
  List<List<NewsPost>> categoryNewsPostList;

  @override
  void initState() {
    super.initState();

    newsPostList = fetchNews();
  }

  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);

    return Container(
      alignment: Alignment.center,
      child: Container(
        child: RefreshIndicator(
            child: FutureBuilder(
              future: newsPostList,
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                if(snapshot.data == null) {
                  return Container(
                      child: CircularProgressIndicator()
                  );
                } else {
                  return ListView.builder(
                    shrinkWrap: true,
                    physics: const AlwaysScrollableScrollPhysics(),
                    itemCount: snapshot.data.length,
                    itemBuilder: (BuildContext context, int index) {
                      return _getCategoryNews(snapshot, index);
                    },
                  );

                }
              },
            ),
            onRefresh: () {
              fetchNews();
            }
        ),
      ),
    );
  }

  Future<List> fetchNews() async {
    String url = "url";
    Response response = await Dio().get(url);

    if(response.statusCode == 200) {
      List newsPostList = [];

      for(int i=0; i<response.data.length; i++) {
        newsPostList.add(response.data[i]);
      }
      return newsPostList;
    } else {
      throw Exception("Failed to fetch category");
    }
  }

  Widget _getCategoryNews(snapshot, int index) {
    List<NewsPost> newsPostList = [];

    for(var c in snapshot.data[index]['items']) {
      NewsPost newsPost = NewsPost.getNewsPostFromAPI(c);
      newsPostList.add(newsPost);
    }
    return Newsfeed(newsPostList, "National");
  }
}

Newsfeed()

class Newsfeed extends StatefulWidget {
  String categoryName;

  List<NewsPost> newsPostList;

  Newsfeed(this.newsPostList, this.categoryName);
  @override
  _NewsfeedState createState() => _NewsfeedState(this.newsPostList, this.categoryName);
}

class _NewsfeedState extends State<Newsfeed> {
  final GlobalKey<ScaffoldState> _scaffoldKeyTwo = new GlobalKey<ScaffoldState>(debugLabel: '_MainScreenKey');

  String categoryName;

  _NewsfeedState(this.newsPostList, this.categoryName);

  List<NewsPost> newsPostList;

  var dio = new Dio();

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

  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);
    return Container(
      alignment: Alignment.center,
      child: ListView.builder(
          shrinkWrap: true,
          itemCount: newsPostList.length,
          itemBuilder: (BuildContext context, int index) {
            print(newsPostList[index]);
            return _getNewsPostWidgets(index);
          }
      ),
    );

  }

  Widget _getNewsPostWidgets(int index) {
    var newsPost = newsPostList[index];

    if(index < 5) {
      if(index == 0) {
        return GestureDetector(
            onTap: () {
              Navigator.push(
                  context,
                  ScaleTransitionRoute(
                      page: NewsPostDetails(newsPostList, index)
                  )
              );
            },
            child: Column(
              children: <Widget>[
                Container(
                  padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
                  //constraints: BoxConstraints(minWidth: double.infinity, maxWidth: double.infinity),
                  constraints: BoxConstraints.expand(
                      width: double.infinity,
                      height: 40
                  ),
                  color: const Color(0xFF2b4849),
                  child: Text(
                    this.categoryName,
                    style: TextStyle(
                        fontSize: 33,
                        color: Colors.white
                    ),
                  ),
                ),
                BlockHeadline(newsPost)
              ],
            )
        );
      }
      else {
        return GestureDetector(
          onTap: () {
            Navigator.push(
                context,
                ScaleTransitionRoute(
                    page: NewsPostDetails(newsPostList, index)
                )
            );
          },
          child: ListedNews(newsPost),
        );
      }
    }
    else {
      return Container(
        color: const Color(0xFF2b4849),
        child: index == 5 ? FlatButton(
          child: Text(
            "See More",
            style: TextStyle(
                color: Colors.white
            ),
          ),
          onPressed: () {
            Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (BuildContext context) => NewsFeedForSpecificCategory(newsPostList)
                )
            );
          },
        ) : Container(),
      );
    }
  }

  openNewsPostDetails(List<NewsPost> newsPostList, int index) {
    Navigator.push(
        context,
        ScaleTransitionRoute(
            page: NewsPostDetails(newsPostList, index)
        )
    );
  }
}

我的尝试

我发现了一些与这个问题有关的问题。试过了。

  1. 我在Listview.builder 中使用了shrinkwrap=true,但没有用。
  2. 尝试在SingleChildScrollView() 中使用Column,仍然无效。
  3. Listview.builder里面加了physicsAlwaysScrollable(),同样无效。

因为我是新手,所以我尝试过的东西可能看起来很愚蠢。

还有一件事是,主屏幕上显示的新闻可以将我带到详细信息页面,并且左右滑动也会将我带到其他新闻。造成问题的是主屏幕,而不是滚动。

如果您能提供一些线索,那将是非常有帮助的。

【问题讨论】:

标签: android ios flutter mobile


【解决方案1】:

我已经找到了解决这个问题的方法。其实很简单。

在我的_NewsfeedState 类的build() 方法中,我将ClampingScrollPhysics() 添加为physics

@override
  Widget build(BuildContext context) {
    SizeConfig().init(context);
    return Container(
      alignment: Alignment.center,
      child: ListView.builder(
          shrinkWrap: true,
          physics: ClampingScrollPhysics(),
          itemCount: newsPostList.length,
          itemBuilder: (BuildContext context, int index) {
            print(newsPostList[index]);
            return _getNewsPostWidgets(index);
          }
      ),
    );

  }

成功了。

【讨论】:

    【解决方案2】:

    把 ListView 放在 ListView 里面是一种反模式。

    这个问题有几种解决方案,

    解决方案 1:

    将这两个项目列表合并为一个项目列表,然后 将其显示为单个 ListView。

    解决方案 2:

    您可以将 SliverList 用于您的用例。 SliverList 可以在单个 CustomScrollView 中包装多个 SliverList。

    【讨论】:

      【解决方案3】:

      这会对你有所帮助。

        child: ListView.builder(
          physics: NeverScrollableScrollPhysics(),
      

      谢谢。

      【讨论】:

        猜你喜欢
        • 2019-04-08
        • 1970-01-01
        • 2018-10-26
        • 2021-12-21
        • 2020-01-18
        • 2020-04-05
        • 1970-01-01
        • 1970-01-01
        • 2021-02-15
        相关资源
        最近更新 更多