【问题标题】:Expanded listview in column takes up extra space列中展开的列表视图占用了额外的空间
【发布时间】:2019-03-11 23:50:13
【问题描述】:

我在一列中有两个列表视图。我希望第一个列表视图占用尽可能少的空间。因此,如果列表中有一项,则包含列表视图的框的大小应该是一项高。
我曾尝试为 ListView 使用容器,但随后出现错误,告诉我在使用 FitFit.loose 时使用 Expanded 或 Flexible。使用这些的问题在于,它们都会导致 ListView 有额外的填充。

在此屏幕截图中,您可以在第一个请求下方看到一点红色。这是包含我的 ListView 的 Expanded 的一部分。

这是我的代码:

return new Scaffold(
  backgroundColor: Theme.of(context).backgroundColor,
  appBar: new PreferredSize(
    child: GradientAppBar(includeLogo: false),
    preferredSize: new Size.fromHeight(75.0),
  ),
  body: Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
      Container(
          padding: EdgeInsets.only(left: 10.0, top: 0.0),
          child: TextField(
            onChanged: (text) {
              setState(() {
                _searchText = text;
              });
              print("search text: $text");
            },
            decoration: new InputDecoration(
                hintText: 'Search',
                contentPadding: const EdgeInsets.symmetric(vertical: 20.0),
                border: InputBorder.none,
                hintStyle: new TextStyle(
                    color: Theme.of(context).secondaryHeaderColor),
                icon: new Icon(searchIcon,
                    color: Theme.of(context).secondaryHeaderColor)),
          )),
      FutureBuilder<FriendRequests>(
        future: fetchFriendRequests(),
        builder: (context, snapshot) {
          if (snapshot.hasData && snapshot.data.friendRequests.length > 0) {
            return Flexible(
                child: Column(mainAxisSize: MainAxisSize.min, children: <
                    Widget>[
              Container(
                  padding: EdgeInsets.all(15.0),
                  width: MediaQuery.of(context).size.width,
                  decoration: BoxDecoration(
                      color: Theme.of(context).bottomAppBarColor,
                      border: new Border(
                          bottom: new BorderSide(
                              color: Theme.of(context).accentColor,
                              width: 1.0,
                              style: BorderStyle.solid),
                          top: new BorderSide(
                              color: Theme.of(context).accentColor,
                              width: 1.0,
                              style: BorderStyle.solid))),
                  child: Center(child: Text("Requests"))),
              Flexible(
                  child: Container(
                      decoration: new BoxDecoration(
                        color: Colors.red,
                      ),
                      child: new ListView.builder(
                        shrinkWrap: true,
                        itemCount: snapshot.data.friendRequests.length,
                        itemBuilder: (BuildContext context, int index) {
                          return new Column(
                            mainAxisSize: MainAxisSize.min,
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              new Container(
                                decoration: new BoxDecoration(
                                    color:
                                        Theme.of(context).backgroundColor,
                                    border: new Border.all(
                                        color:
                                            Theme.of(context).accentColor)),
                                child: new FriendRequestView(
                                    snapshot.data.friendRequests[index]
                                        .friendName,
                                    snapshot.data.friendRequests[index]
                                        .pictureURL,
                                    snapshot.data.friendRequests[index].id,
                                    snapshot.data.friendRequests[index]
                                        .creationDate),
                              )
                            ],
                          );
                        },
                      )))
            ]));
          } else if (snapshot.hasError) {
            return Text("${snapshot.error}");
          } else if (snapshot.hasData &&
              snapshot.data.friendRequests.length == 0) {
            return Container();
          }

          // By default, show a loading spinner
          return Center(child: CircularProgressIndicator());
        },
      ),
      Container(
          padding: EdgeInsets.all(15.0),
          width: MediaQuery.of(context).size.width,
          decoration: BoxDecoration(
              color: Theme.of(context).bottomAppBarColor,
              border: new Border(
                  bottom: new BorderSide(
                      color: Theme.of(context).accentColor,
                      width: 1.0,
                      style: BorderStyle.solid),
                  top: new BorderSide(
                      color: Theme.of(context).accentColor,
                      width: 1.0,
                      style: BorderStyle.solid))),
          child: Center(child: Text("Suggestions"))),
      FriendSuggestionsView(
        searchText: _searchText,
      )
    ],
  ),
);

这是我的 FriendSuggestionsView:

Widget build(BuildContext context) {
return Flexible(
    child: FutureBuilder<FriendSuggestions>(
        future: fetchSuggestions(),
        builder: (context, snapshot) {
          if (snapshot.hasData &&
              snapshot.data.friendSuggestions.length > 0) {
            return new ListView.builder(
                shrinkWrap: true,
                itemCount: snapshot.data.friendSuggestions.length,
                itemBuilder: (BuildContext context, int index) {
                  return FriendSuggestionRow(
                      name: snapshot.data.friendSuggestions[index].name,
                      userID: snapshot.data.friendSuggestions[index].userID,
                      pictureURL: snapshot
                          .data.friendSuggestions[index].pictureURL);
                });
          } else if (snapshot.hasError) {
            return Text("${snapshot.error}");
          } else if (snapshot.hasData &&
              snapshot.data.friendSuggestions.length == 0) {
            return Container(
                padding: EdgeInsets.all(20.0),
                child: Center(child: Text("No suggestions")));
          }

          // By default, show a loading spinner
          return Container(
              padding: EdgeInsets.all(20.0),
              child: Center(child: CircularProgressIndicator()));
        }));

}

【问题讨论】:

标签: listview flutter


【解决方案1】:

我也遇到了同样的问题,在做了一些研究后,我发现了一个适合我的解决方案: 您必须为 padding 属性指定 EdgeInsets.zero。

【讨论】:

    【解决方案2】:

    FutureBuilder 下,您应该使用Flexible 容器而不是Expanded,以防止其子级占用过多空间。在构建requests ListView 时,您还需要将shrinkWrap 属性设置为true。但是,请注意文档的最后一段:

    收缩包裹滚动视图的内容比展开到允许的最大尺寸 (...) 要昂贵得多。


    更新: 根据提供的其他信息,以下是您如何防止 suggestions 重叠 requests

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        ..., // other scaffold properties
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisSize: MainAxisSize.max,
          children: [
            ..., // search field widget
            Expanded(
              child: LayoutBuilder(
                builder: (context, constraints) => Column(children: [
                      LimitedBox(
                        maxHeight: constraints.maxHeight / 2,
                        child: Column(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            ..., // requests header widget
                            FutureBuilder<FriendRequests>(
                              future: fetchFriendRequests(),
                              builder: (context, snapshot) {
                                if (snapshot.hasData &&
                                    snapshot.data.friendRequests.length > 0) {
                                  return Flexible(
                                    child: Container(
                                      ..., // box decoration
                                      child: new ListView.builder(
                                        shrinkWrap: true,
                                        ..., // item count and builder
                                      ),
                                    ),
                                  );
                                } else ... // handle other data states
                              },
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        child: Column(
                          children: [
                            ..., // suggestions header widget
                            FutureBuilder<FriendSuggestions>(
                              future: fetchSuggestions(),
                              builder: (context, snapshot) {
                                if (snapshot.hasData &&
                                    snapshot.data.friendSuggestions.length > 0) {
                                  return Expanded(
                                    child: new ListView.builder(
                                      ..., // item count and builder
                                    ),
                                  );
                                } else ... // handle other data states
                              },
                            ),
                          ],
                        ),
                      ),
                    ]),
              ),
            ),
          ],
        ),
      );
    }
    

    【讨论】:

    • 我已经尝试了您的建议并编辑了 OP。当有 0-2 条建议时,它可以完美运行。但是,建议会扩展以填充整个视图,与请求重叠。这是一个希望解释得更好的画廊:imgur.com/a/Sk1ZWXp
    • 您能否详细说明如果请求和建议中都有多个项目,您希望布局如何表现? IE。两个列表视图都应该是可见且可滚动的,或者更确切地说,所有请求都应该首先滚动,建议紧随其后?
    • 两个视图都应该是可见和可滚动的,即请求的最大高度,但建议的无限高度。
    • @MikeBellika 我更新了答案,请看一下,如果这是正确的行为,请告诉我。我还删除了几行代码以使其尽可能简短。
    • 这几乎可以工作,但是当只有 1 个朋友请求时,建议不会占用其余空间:imgur.com/a/LkBWNHi
    【解决方案3】:

    使用padding: EdgeInsets.zero,In ListView.builder

    ListView.builder(
                          padding: EdgeInsets.zero,
                          shrinkWrap: true,
                          itemCount: 3,
                          physics: ScrollPhysics(),
                          itemBuilder: (context, index) {
                            return Container(
                           
                            );
                          },
                        ),
    

    【讨论】:

      【解决方案4】:

      这通常会从列表视图中移除额外的顶部填充:

         MediaQuery.removePadding(
                 context:context,
                  removeTop: true,
                   child  ListView.Builder(
                    itemCount:2,
                    itemBuilder(context,index){
                });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-11
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        相关资源
        最近更新 更多