SingleChildScrollView 内的水平滚动 ListView.builder - 包装内容高度

Posted

技术标签:

【中文标题】SingleChildScrollView 内的水平滚动 ListView.builder - 包装内容高度【英文标题】:Horizontal scrolling ListView.builder inside SingleChildScrollView - wrap content height 【发布时间】:2021-11-11 05:35:54 【问题描述】:

我的布局是一个带有一些控件的表单小部件:

Column(
      mainAxisAlignment: MainAxisAlignment.start,
      mainAxisSize: MainAxisSize.max,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Form(
          key: widget.addEventFormKey,
          onChanged: () ,
          child: Expanded(
            child: SingleChildScrollView(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Text(CustomResources.strings["add_event_category_label"], style: TextStyle(fontWeight: FontWeight.bold)),
                  
                  /*some other widgets*/
                  
                  Visibility(
                    child: Container(
                      height: 200.0,
                      child: ListView.builder(
                        scrollDirection: Axis.horizontal,
                        itemCount: _attachments?.length,
                        itemBuilder: (context, index) 
                          return Stack(
                            children: [
                              Container(
                                margin: EdgeInsets.fromLTRB(0, 0, 5, 0),
                                child: Stack(
                                  children: [
                                    ClipRRect(
                                      child: Image.file(File(_attachments[index]), cacheWidth: 200),
                                      borderRadius: BorderRadius.circular(8.0),
                                    ),
                                  ],
                                ),
                              ),
                              IconButton(
                                onPressed: () 
                                  File(_attachments[index]).delete();
                                  setState(() => _attachments.remove(_attachments[index]));
                                ,
                                icon: Icon(FontAwesomeIcons.trash, color: Colors.white, size: 20),
                                padding: EdgeInsets.only(top: 4, left: 4),
                                constraints: BoxConstraints(),
                              ),
                            ],
                          );
                        ,
                      ),
                    ),
                    visible: _attachments.length > 0,
                  ),
                  Visibility(child: Padding(padding: EdgeInsets.fromLTRB(0, 18, 0, 0)),visible: _attachments.length > 0),
                  SizedBox(
                    child: RaisedButton(
                        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24.0)),
                        onPressed: _attachments.length < 3 ? () => _pickImage() : null,
                        padding: EdgeInsets.all(12.0),
                        color: Colors.blue,
                        child: Text(CustomResources.strings["add_event_add_photo_button_label"], style: TextStyle(color: Colors.white))),
                    width: double.infinity,
                  ),
                ],
              ),
            ),
          ),
        ),
      ],
    );

有问题的部分是ListView.builder 显示水平滚动的图像列表。如您所见,图片将始终获得固定宽度(200)和未知高度,因为高度取决于图像纵横比。 ListView.builderContainer 包裹,所以现在它的高度为 200。

我想强制我的ListView.builder 扩展到子图像高度(它是水平滚动的单行 ListView),图像宽度始终为 200,其他小部件应放置在其下方,没有任何剩余空间。使用当前方法,如果图像高度 200,图像将被缩放(宽度/高度)。

我尝试用Expanded 小部件而不是Container 包装列表视图,但它抛出异常:

RenderFlex 子级具有非零 flex 但传入的高度约束 是无限的。

它说我仍然需要提供高度,但我不想这样做。如何解决?

【问题讨论】:

【参考方案1】:

我认为 ListView.builder 无法做到这一点,因为在构建小部件树时它的动态项目高度是未知的。相反,我的缩略图小部件必须预先构建,并在构建后添加到Row,并用SingleChildScrollView 包裹行以使其可滚动。所以,我的缩略图列表准备好放到我的Form

class AttachmentsListWidget extends StatelessWidget 
  const AttachmentsListWidget(
    Key key,
    @required this.items,
    @required this.onAttachmentDeleted,
  ) : super(key: key);

  final List<String> items;
  final Function(String) onAttachmentDeleted;

  @override
  Widget build(BuildContext context) 
    var _thumbnailsScrollController = ScrollController();
    final thumbnails = <Widget>[];
    Widget thumbnailsWidget;

    if (items.length > 0) 
      for (int i = 0; i < items.length; i++) 
        thumbnails.add(
          AttachmentWidget(
            attachment: items[i],
            onDeleteClicked: (String attachment) => onAttachmentDeleted(attachment),
          ),
        );
      
      thumbnailsWidget = Container(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Scrollbar(
              isAlwaysShown: true,
              controller: _thumbnailsScrollController,
              child: SingleChildScrollView(
                controller: _thumbnailsScrollController,
                scrollDirection: Axis.horizontal,
                child: Row(
                  children: thumbnails,
                  crossAxisAlignment: CrossAxisAlignment.start,
                ),
              ),
            ),
          ],
        ),
      );
     else 
      thumbnailsWidget = Container();
    
    return thumbnailsWidget;
  

(另外,添加了始终可见的滚动条)。

【讨论】:

【参考方案2】:

如果您收到RenderFlex children have non-zero flex but incoming height constraints are unbounded.,请尝试以下代码,希望对您有所帮助。在 Expanded() 小部件中添加您的 Column 并在您的代码中删除 SingleChildScrollView()

Expanded(
  child: Column(
     children:[
     //Your Widgets
      ],
   ),
),

【讨论】:

您的意思是删除*** SingleChildScrollView 吗?我无法删除它,因为窗口内容需要可滚动 是的,但我认为当我们使用扩展小部件时,内容也可以滚动,只需尝试一下并告诉我。 不,它不可滚动。而且我认为***小部件与问题无关。问题是缩略图列表高度

以上是关于SingleChildScrollView 内的水平滚动 ListView.builder - 包装内容高度的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中自动滚动到 SingleChildScrollView 内的行的位置

SingleChildScrollView 内的水平滚动 ListView.builder - 包装内容高度

键盘溢出 * 像素。无法使用 SingleChildScrollView 或 ListView

ScrollView 内的 TabView 渲染错误 - Flutter

Row 内的 ListViewBuiler

SingleChildScrollView ,子列上的空格问题